2024-11-29 14:58:03 +01:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8" />
|
|
|
|
|
<title>MARL - Mastodon Archive Reader Lite</title>
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
|
|
<link rel="icon" href="data:," />
|
|
|
|
|
<base target="_blank" />
|
2024-12-28 01:29:09 +01:00
|
|
|
|
<link rel="stylesheet" href="css/main.css?20241228" />
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
<noscript>
|
|
|
|
|
<div class="nojs">JavaScript is required for this app to run.</div>
|
|
|
|
|
</noscript>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="main-page"
|
|
|
|
|
id="app"
|
|
|
|
|
x-data
|
|
|
|
|
:class="$store.ui.appClasses"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
x-init="$watch('$store.files.appReady', value => checkAppReady(value))"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
2024-12-27 23:37:47 +01:00
|
|
|
|
<template
|
|
|
|
|
x-if="!$store.files.appReady && !$store.files.someFilesLoaded && !$store.files.loading"
|
|
|
|
|
>
|
|
|
|
|
<main class="welcome">
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<div class="intro">
|
|
|
|
|
<h1>
|
|
|
|
|
Welcome to MARL
|
|
|
|
|
<span class="accronym">(Mastodon Archive Reader Lite)</span>
|
|
|
|
|
</h1>
|
|
|
|
|
<p>
|
|
|
|
|
MARL allows you to explore the content of your Mastodon archive
|
|
|
|
|
file in a user-friendly interface. Everything takes place in the
|
|
|
|
|
browser: your archive stays strictly on your computer; none of its
|
|
|
|
|
data is sent to any server.
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
You can request your Mastodon archive by logging into your account
|
|
|
|
|
on the web, then visiting "Preferences > Import and export >
|
2024-12-01 00:37:22 +01:00
|
|
|
|
Request your archive".<br />
|
|
|
|
|
<strong>Please note:</strong> only ZIP files are supported (not
|
|
|
|
|
GZ).
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</p>
|
|
|
|
|
<p>
|
2024-12-01 00:37:22 +01:00
|
|
|
|
<strong>Start by opening your archive file with MARL.</strong
|
|
|
|
|
><br />
|
2024-11-29 14:58:03 +01:00
|
|
|
|
You can drag and drop it anywhere on this page, or
|
|
|
|
|
<label for="file-loader" tabindex="0"
|
|
|
|
|
>click here to select it</label
|
|
|
|
|
>.
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
id="file-loader"
|
|
|
|
|
class="file-loader"
|
|
|
|
|
type="file"
|
2024-12-01 00:37:22 +01:00
|
|
|
|
accept=".zip"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
multiple
|
2024-11-29 14:58:03 +01:00
|
|
|
|
@change="unZip(Object.values($event.target.files))"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="about">
|
|
|
|
|
<a href="https://github.com/s427/MARL">Project page (github)</a>
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-12-27 23:37:47 +01:00
|
|
|
|
<template
|
|
|
|
|
x-if="(!$store.files.appReady && $store.files.someFilesLoaded) || $store.files.loading"
|
|
|
|
|
>
|
2024-12-05 19:35:07 +01:00
|
|
|
|
<main class="welcome loading-more">
|
|
|
|
|
<div class="intro">
|
|
|
|
|
<div class="file-loader loading">
|
2024-12-27 23:37:47 +01:00
|
|
|
|
<div>... Loading ...</div>
|
|
|
|
|
<div class="filename" x-text="$store.files.loadingName"></div>
|
2024-12-05 19:35:07 +01:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<template x-if="$store.files.appReady">
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<main
|
|
|
|
|
class="main-section"
|
|
|
|
|
id="main-section"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
x-on:resize.window="$store.ui.checkMenuState()"
|
|
|
|
|
>
|
2024-12-05 19:35:07 +01:00
|
|
|
|
<div
|
|
|
|
|
class="main-section-inner"
|
|
|
|
|
id="main-section-inner"
|
|
|
|
|
:class="$store.files.sources.length > 1 ? 'multiple-actors' : ''"
|
|
|
|
|
>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<div class="mobile-menu" id="mobile-menu">
|
|
|
|
|
<nav>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>
|
|
|
|
|
<button
|
|
|
|
|
class="menu-actor"
|
|
|
|
|
@click="$store.ui.menuToggle('actor')"
|
|
|
|
|
>
|
|
|
|
|
<svg aria-hidden="true"><use href="#menu-actor" /></svg>
|
|
|
|
|
<span>Profile</span>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<button
|
|
|
|
|
class="menu-filters"
|
|
|
|
|
:class="$store.files.filtersActive ? 'filters-active' : ''"
|
|
|
|
|
@click="$store.ui.menuToggle('filters')"
|
|
|
|
|
>
|
|
|
|
|
<svg aria-hidden="true"><use href="#menu-filters" /></svg>
|
|
|
|
|
<span
|
|
|
|
|
>Filters
|
|
|
|
|
<em
|
|
|
|
|
x-show="$store.files.filtersActive"
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
>(some filters are active)</em
|
|
|
|
|
>
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<button
|
|
|
|
|
class="menu-tags"
|
|
|
|
|
@click="$store.ui.menuToggle('tags')"
|
|
|
|
|
>
|
|
|
|
|
<svg aria-hidden="true"><use href="#menu-tags" /></svg>
|
|
|
|
|
<span>Tags</span>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<button class="menu-new" @click="startOver">
|
|
|
|
|
<svg aria-hidden="true"><use href="#menu-new" /></svg>
|
|
|
|
|
<span>New File</span>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</nav>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="panel-backdrop"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
@click="$store.ui.menuClose()"
|
|
|
|
|
@keyup.esc="$store.ui.menuClose()"
|
|
|
|
|
></div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="actor mobile-menu-panel"
|
|
|
|
|
id="panel-actor"
|
|
|
|
|
role="region"
|
|
|
|
|
aria-labelledby="actor-title"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
class="panel-close"
|
|
|
|
|
@click="$store.ui.menuClose()"
|
|
|
|
|
x-show="$store.ui.menuIsActive"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#close" /></svg
|
|
|
|
|
><span class="visually-hidden">Close panel</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<h2 class="visually-hidden" id="actor-title">Account info</h2>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<h3 class="visually-hidden" id="actor-tabs-title">Accounts</h3>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-05 19:35:07 +01:00
|
|
|
|
<div
|
|
|
|
|
class="actors-wrapper"
|
|
|
|
|
:style="'--actor-hue: '+ $store.files.sources[$store.ui.actorPanel].hue"
|
|
|
|
|
>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<template x-if="$store.files.sources.length > 1">
|
|
|
|
|
<div
|
|
|
|
|
class="actors-tabs"
|
|
|
|
|
role="tablist"
|
|
|
|
|
aria-labelledby="actor-tabs-title"
|
|
|
|
|
>
|
|
|
|
|
<template x-for="(_, source) in $store.files.sources">
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
role="tab"
|
|
|
|
|
:id="'actortab-' + source"
|
|
|
|
|
:aria-selected="source === $store.ui.actorPanel ? 'true': 'false'"
|
|
|
|
|
:aria-controls="'actorpanel-' + source"
|
|
|
|
|
:style="'--actor-hue: '+ $store.files.sources[source].hue"
|
|
|
|
|
@click="$store.ui.openActorPanel(source)"
|
|
|
|
|
@keyup.right="$store.ui.switchActorPanel('up')"
|
|
|
|
|
@keyup.left="$store.ui.switchActorPanel('down')"
|
|
|
|
|
>
|
|
|
|
|
<span
|
|
|
|
|
x-text="$store.files.sources[source].actor.name"
|
|
|
|
|
></span>
|
|
|
|
|
</button>
|
|
|
|
|
</template>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
</template>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="$store.files.sources.length === 1">
|
|
|
|
|
<span
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
id="actortab-0"
|
|
|
|
|
x-text="$store.files.sources[0].actor.name"
|
|
|
|
|
></span>
|
|
|
|
|
</template>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-for="source in $store.files.sources">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div
|
|
|
|
|
class="actor-panel"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
:id="'actorpanel-' + source.id"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
role="tabpanel"
|
|
|
|
|
tabindex="0"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
:aria-labelledby="'actortab-' + source.id"
|
|
|
|
|
x-data="{a: source.actor}"
|
|
|
|
|
x-show="$store.ui.actorPanel === source.id"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
>
|
|
|
|
|
<div class="actor-pretty">
|
|
|
|
|
<div class="actor-banner">
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="source.header.noImg">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<img alt="header" src="img/no-header.png" />
|
|
|
|
|
</template>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="! source.header.noImg">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<button
|
|
|
|
|
id="actor-header"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
@click="$store.lightbox.openProfileImg('header', 'actor-header', source.id)"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
alt="header"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
:src="`data:${source.header.type}; base64,${source.header.content}`"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
/>
|
|
|
|
|
</button>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div class="actor-id">
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="source.avatar.noImg">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div class="actor-avatar no-avatar">
|
|
|
|
|
<img :alt="a.name" src="img/no-avatar.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="! source.avatar.noImg">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<button
|
|
|
|
|
id="actor-avatar"
|
|
|
|
|
class="actor-avatar"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
@click="$store.lightbox.openProfileImg('avatar', 'actor-avatar', source.id)"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
:alt="a.name"
|
|
|
|
|
class="actor-avatar"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
:src="`data:${source.avatar.type}; base64,${source.avatar.content}`"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
/>
|
|
|
|
|
</button>
|
|
|
|
|
</template>
|
|
|
|
|
<h1 class="actor-name" x-text="await a.name"></h1>
|
|
|
|
|
<div class="actor-url">
|
|
|
|
|
<a :href="await a.url" x-text="await a.url"></a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div
|
|
|
|
|
class="actor-summary"
|
|
|
|
|
x-show="a.summary"
|
|
|
|
|
x-html="await a.summary"
|
|
|
|
|
></div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div class="actor-infos">
|
|
|
|
|
<dl>
|
|
|
|
|
<dt>Member since</dt>
|
|
|
|
|
<dd x-text="await formatDate(a.published)"></dd>
|
|
|
|
|
</dl>
|
|
|
|
|
<template x-for="item in await a.attachment">
|
|
|
|
|
<dl>
|
|
|
|
|
<dt x-text="item.name"></dt>
|
|
|
|
|
<dd x-html="item.value"></dd>
|
|
|
|
|
</dl>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div class="actor-posts-count">
|
|
|
|
|
<div class="total">
|
|
|
|
|
<span
|
|
|
|
|
class="count"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
x-text="formatNumber(source.outbox.totalItems)"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
></span>
|
|
|
|
|
<span class="label">posts</span>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div class="archive">
|
|
|
|
|
<span
|
|
|
|
|
class="count"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
x-text="formatNumber(source.nbToots)"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
></span>
|
|
|
|
|
<span class="label">in archive</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<details
|
|
|
|
|
class="comment"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
x-show="source.nbToots != source.outbox.totalItems"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
>
|
|
|
|
|
<summary>
|
|
|
|
|
<span class="summary-icon">
|
|
|
|
|
<svg aria-hidden="true">
|
|
|
|
|
<use href="#question" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
|
|
|
|
<span class="summary-label"
|
|
|
|
|
>Why are those two numbers different?</span
|
|
|
|
|
>
|
|
|
|
|
</summary>
|
|
|
|
|
<div class="details-content">
|
|
|
|
|
<p>
|
|
|
|
|
Posts that are not directly hosted on your
|
|
|
|
|
instance are kept in a cache by your instance for
|
|
|
|
|
a given time, after what they are deleted from
|
|
|
|
|
that cache. Posts that are not in your instance
|
|
|
|
|
cache any more are not included in your archive.
|
|
|
|
|
This affects boosts, likes, and bookmarks.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div class="actor-raw">
|
|
|
|
|
<div class="actor-raw-inner">
|
|
|
|
|
<details>
|
|
|
|
|
<summary>
|
|
|
|
|
<span class="summary-icon">
|
|
|
|
|
<svg aria-hidden="true">
|
|
|
|
|
<use href="#json" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
2024-12-27 23:37:47 +01:00
|
|
|
|
<span
|
|
|
|
|
class="summary-label"
|
|
|
|
|
:id="source + 'raw-data-label'"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
>Raw data <em>(actor.json)</em></span
|
|
|
|
|
>
|
|
|
|
|
</summary>
|
|
|
|
|
<div class="details-content">
|
2024-12-27 23:37:47 +01:00
|
|
|
|
<textarea
|
|
|
|
|
x-text="formatJson(await a)"
|
|
|
|
|
:aria-labelledby="source + 'raw-data-label'"
|
|
|
|
|
readonly
|
|
|
|
|
></textarea>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
|
|
|
|
|
<div class="actor-likes-bookmarks">
|
|
|
|
|
<div class="actor-likes">
|
|
|
|
|
<details>
|
|
|
|
|
<summary>
|
|
|
|
|
<span class="summary-icon">
|
|
|
|
|
<svg aria-hidden="true">
|
|
|
|
|
<use href="#favorite" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
|
|
|
|
<h2 class="summary-label">
|
|
|
|
|
Favorites (<span
|
|
|
|
|
class="count"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
x-text="source.likes.length"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
></span
|
|
|
|
|
>)
|
|
|
|
|
</h2>
|
|
|
|
|
</summary>
|
|
|
|
|
<div class="details-content">
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="source.likes.length">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<ul>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-for="url in source.likes">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<li>
|
2024-12-14 17:28:54 +01:00
|
|
|
|
<a
|
|
|
|
|
:href="url"
|
|
|
|
|
x-html="formatLikesBookmarks(url)"
|
|
|
|
|
></a>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</template>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="! source.likes.length">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<p class="no-content">... no favorites ...</p>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="actor-bookmarks">
|
|
|
|
|
<details>
|
|
|
|
|
<summary>
|
|
|
|
|
<span class="summary-icon">
|
|
|
|
|
<svg aria-hidden="true">
|
|
|
|
|
<use href="#bookmark" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
|
|
|
|
<h2 class="summary-label">
|
|
|
|
|
Bookmarks (<span
|
|
|
|
|
class="count"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
x-text="source.bookmarks.length"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
></span
|
|
|
|
|
>)
|
|
|
|
|
</h2>
|
|
|
|
|
</summary>
|
|
|
|
|
<div class="details-content">
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="source.bookmarks.length">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<ul>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-for="url in source.bookmarks">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<li>
|
2024-12-14 17:28:54 +01:00
|
|
|
|
<a
|
|
|
|
|
:href="url"
|
|
|
|
|
x-html="formatLikesBookmarks(url)"
|
|
|
|
|
></a>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</template>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-if="! source.bookmarks.length">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<p class="no-content">... no bookmarks ...</p>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
</div>
|
|
|
|
|
</template>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filters mobile-menu-panel"
|
|
|
|
|
id="panel-filters"
|
|
|
|
|
role="search"
|
|
|
|
|
aria-labelledby="toots-filter-title"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
class="panel-close"
|
|
|
|
|
@click="$store.ui.menuClose()"
|
|
|
|
|
x-show="$store.ui.menuIsActive"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#close" /></svg
|
|
|
|
|
><span class="visually-hidden">Close panel</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<h2 id="toots-filter-title">Filter posts</h2>
|
|
|
|
|
|
|
|
|
|
<p class="visually-hidden">
|
|
|
|
|
The list of posts will be automatically updated based on the
|
|
|
|
|
active filters below.
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<div class="toots-filters-group">
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter text"
|
|
|
|
|
:class="isFilterActive('fullText') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-full-text">Full text</label>
|
|
|
|
|
<div class="input-wrapper">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-full-text"
|
|
|
|
|
type="text"
|
|
|
|
|
x-model.debounce="$store.files.filters.fullText"
|
|
|
|
|
@keyup.debounce="$store.files.setFilter()"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter text"
|
|
|
|
|
:class="isFilterActive('hashtagText') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-hashtag-text">Hashtags</label>
|
|
|
|
|
<div class="input-wrapper">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-hashtag-text"
|
|
|
|
|
type="text"
|
|
|
|
|
x-model.debounce="$store.files.filters.hashtagText"
|
|
|
|
|
@keyup.debounce="$store.files.setFilter()"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter text"
|
|
|
|
|
:class="isFilterActive('mentionText') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-mention-text">Mentions</label>
|
|
|
|
|
<div class="input-wrapper">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-mention-text"
|
|
|
|
|
type="text"
|
|
|
|
|
x-model.debounce="$store.files.filters.mentionText"
|
|
|
|
|
@keyup.debounce="$store.files.setFilter()"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter text"
|
|
|
|
|
:class="isFilterActive('externalLink') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-ext-link">External links</label>
|
|
|
|
|
<div class="input-wrapper">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-ext-link"
|
|
|
|
|
type="text"
|
|
|
|
|
x-model.debounce="$store.files.filters.externalLink"
|
|
|
|
|
@keyup.debounce="$store.files.setFilter()"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter text"
|
|
|
|
|
:class="isFilterActive('summary') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-summary">Summary (CW)</label>
|
|
|
|
|
<div class="input-wrapper">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-summary"
|
|
|
|
|
type="text"
|
|
|
|
|
x-model.debounce="$store.files.filters.summary"
|
|
|
|
|
@keyup.debounce="$store.files.setFilter()"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-12-13 18:39:27 +01:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="toots-filters-group">
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox sep-above"
|
|
|
|
|
:class="isFilterActive('isEdited') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-is-edited">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-is-edited"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.isEdited"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Has been edited</span>
|
|
|
|
|
</label>
|
2024-12-13 18:39:27 +01:00
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
x-show="$store.files.duplicates"
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('isDuplicate') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-is-duplicate">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-is-duplicate"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.isDuplicate"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Non-exact duplicates</span>
|
|
|
|
|
</label>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="toots-filters-group">
|
|
|
|
|
<h3 class="toots-filters-group-title">Must contain</h3>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('hasHashtags') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-has-hashtags">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-has-hashtags"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.hasHashtags"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Hashtag(s)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('hasMentions') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-has-mentions">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-has-mentions"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.hasMentions"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Mention(s)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('hasExternalLink') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-has-external-links">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-has-external-links"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.hasExternalLink"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>External link(s)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('hasSummary') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-has-summary">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-has-summary"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.hasSummary"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Summary (CW)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="toots-filters-group">
|
|
|
|
|
<h3 class="toots-filters-group-title">Type</h3>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('typeOriginal') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-type-original">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-type-original"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.typeOriginal"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Original posts (incl. replies)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('typeBoost') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-type-boost">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-type-boost"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.typeBoost"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Boosts</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox sep-above"
|
|
|
|
|
:class="isFilterActive('noStartingAt') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-no-at">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-no-at"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.noStartingAt"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Does not start with "@"</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('isSensitive') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-is-sensitive">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-is-sensitive"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.isSensitive"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Marked as sensitive</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="toots-filters-group">
|
|
|
|
|
<h3 class="toots-filters-group-title">Must have attachment</h3>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('attachmentAny') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-attachment-any">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-attachment-any"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.attachmentAny"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Any type</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('attachmentImage') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-attachment-image">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-attachment-image"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.attachmentImage"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Image(s)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('attachmentVideo') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-attachment-video">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-attachment-video"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.attachmentVideo"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Video(s)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('attachmentSound') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-attachment-sound">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-attachment-sound"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.attachmentSound"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Sound(s)</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox sep-above"
|
|
|
|
|
:class="isFilterActive('attachmentNoAltText') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-attachment-no-alt-text">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-attachment-no-alt-text"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.attachmentNoAltText"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Without alt text</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('attachmentWithAltText') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-attachment-with-alt-text">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-attachment-with-alt-text"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.attachmentWithAltText"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>With alt text</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="toots-filters-group">
|
|
|
|
|
<h3 class="toots-filters-group-title">Visibility</h3>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('visibilityPublic') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-visibility-public">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-visibility-public"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.visibilityPublic"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Public</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('visibilityUnlisted') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-visibility-unlisted">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-visibility-unlisted"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model="$store.files.filters.visibilityUnlisted"
|
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Unlisted</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('visibilityFollowers') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-visibility-followers">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-visibility-followers"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.visibilityFollowers"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Followers only</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
|
|
|
|
:class="isFilterActive('visibilityMentioned') ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<label for="filter-visibility-mentioned">
|
|
|
|
|
<input
|
|
|
|
|
id="filter-visibility-mentioned"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
x-model.debounce="$store.files.filters.visibilityMentioned"
|
|
|
|
|
@change.debounce="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>Mentioned people only</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<div
|
|
|
|
|
class="toots-filters-group"
|
|
|
|
|
x-show="$store.files.toots.length"
|
|
|
|
|
>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<h3 class="toots-filters-group-title">Language</h3>
|
2024-12-13 18:40:21 +01:00
|
|
|
|
<template x-for="lang in $store.files.sortedLanguages">
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
2024-12-13 18:40:21 +01:00
|
|
|
|
:class="isFilterActive('lang_' + lang[0]) ? 'active' : ''"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
2024-12-13 18:40:21 +01:00
|
|
|
|
<label :for="'filter-lang-' + lang[0]">
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<input
|
2024-12-13 18:40:21 +01:00
|
|
|
|
:id="'filter-lang-' + lang[0]"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
type="checkbox"
|
2024-12-13 18:40:21 +01:00
|
|
|
|
x-model="$store.files.filters['lang_' + lang[0]]"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>
|
2024-12-13 18:40:21 +01:00
|
|
|
|
<span x-text="lang[0]"></span>
|
|
|
|
|
(<span x-text="lang[1]"></span>)
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<template x-if="$store.files.sources.length > 1">
|
|
|
|
|
<div class="toots-filters-group">
|
|
|
|
|
<h3 class="toots-filters-group-title">Author</h3>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<template x-for="source in $store.files.sources">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<div
|
|
|
|
|
class="toots-filter checkbox"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
:class="isFilterActive('actor_' + source.id) ? 'active' : ''"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<label :for="'filter-actor-' + source.id">
|
2024-12-04 21:58:42 +01:00
|
|
|
|
<input
|
2024-12-09 15:20:29 +01:00
|
|
|
|
:id="'filter-actor-' + source.id"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
type="checkbox"
|
2024-12-09 15:20:29 +01:00
|
|
|
|
x-model="$store.files.filters['actor_' + source.id]"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
@change="$store.files.setFilter()"
|
|
|
|
|
/>
|
|
|
|
|
<span>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<span x-text="source.actor.name"></span>
|
2024-12-04 21:58:42 +01:00
|
|
|
|
</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-11-29 14:58:03 +01:00
|
|
|
|
<div class="toots-filters-reset">
|
|
|
|
|
<button
|
2024-12-01 10:45:20 +01:00
|
|
|
|
@click="$store.files.resetFilters(true)"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
:disabled="!$store.files.filtersActive"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#reset-filters" /></svg
|
|
|
|
|
><span class="btn-label">Reset filters</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<header class="toots-header" aria-labelledby="toots-header-title">
|
|
|
|
|
<h2 id="toots-header-title">
|
|
|
|
|
<span class="count">
|
|
|
|
|
<span
|
|
|
|
|
x-text="await formatNumber($store.files.filteredToots.length)"
|
|
|
|
|
class="nb"
|
|
|
|
|
></span>
|
|
|
|
|
posts
|
|
|
|
|
</span>
|
|
|
|
|
<span class="order">
|
|
|
|
|
-
|
|
|
|
|
<span
|
|
|
|
|
x-text="await $store.files.sortAsc ? 'oldest' : 'latest'"
|
|
|
|
|
></span>
|
|
|
|
|
first
|
|
|
|
|
<button
|
|
|
|
|
@click="$store.files.toggleTootsOrder()"
|
|
|
|
|
class="toggle-order"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#toggle-order" /></svg
|
|
|
|
|
><span class="btn-label">Reverse</span>
|
|
|
|
|
</button>
|
|
|
|
|
</span>
|
|
|
|
|
<button @click="startOver" class="load-new">
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#load-file" /></svg
|
|
|
|
|
><span class="btn-label">Load new file</span>
|
|
|
|
|
</button>
|
|
|
|
|
</h2>
|
|
|
|
|
|
|
|
|
|
<div class="paging">
|
|
|
|
|
<div class="direction-back">
|
|
|
|
|
<button
|
|
|
|
|
id="paging-btn-first"
|
|
|
|
|
@click="$store.files.firstPage()"
|
|
|
|
|
:disabled="$store.files.currentPage <= 1"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-first" /></svg
|
|
|
|
|
><span class="btn-label">First</span>
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
id="paging-btn-prev"
|
|
|
|
|
@click="$store.files.prevPage()"
|
|
|
|
|
:disabled="$store.files.currentPage <= 1"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-prev" /></svg
|
|
|
|
|
><span class="btn-label">Prev</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="paging-options-toggle">
|
|
|
|
|
<button @click="$store.ui.togglePagingOptions()">
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#options" /></svg
|
|
|
|
|
><span class="btn-label">Paging options</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="paging-options"
|
|
|
|
|
id="paging-options"
|
|
|
|
|
:class="$store.ui.pagingOptionsClass"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
>
|
|
|
|
|
<div class="paging-options-inner">
|
|
|
|
|
<label for="paging-current-page">Page</label>
|
|
|
|
|
<input
|
|
|
|
|
class="current-page"
|
|
|
|
|
id="paging-current-page"
|
|
|
|
|
type="number"
|
|
|
|
|
min="1"
|
|
|
|
|
max="$store.files.totalPages"
|
|
|
|
|
x-model="$store.files.currentPage"
|
|
|
|
|
@keyup="$store.files.checkPagingValue()"
|
|
|
|
|
@change="$store.files.checkPagingValue()"
|
|
|
|
|
onClick="this.select()"
|
|
|
|
|
/>
|
|
|
|
|
/
|
|
|
|
|
<span
|
|
|
|
|
class="total-pages"
|
|
|
|
|
x-text="formatNumber($store.files.totalPages)"
|
|
|
|
|
></span>
|
|
|
|
|
(
|
|
|
|
|
<input
|
|
|
|
|
class="page-size"
|
|
|
|
|
id="paging-page-size"
|
|
|
|
|
type="number"
|
|
|
|
|
min="1"
|
|
|
|
|
x-model="$store.files.pageSize"
|
|
|
|
|
@keyup="$store.files.checkPagingValue()"
|
|
|
|
|
@change="$store.files.checkPagingValue()"
|
|
|
|
|
onClick="this.select()"
|
|
|
|
|
/>
|
|
|
|
|
<label for="paging-page-size">posts per page)</label>
|
|
|
|
|
</div>
|
2024-11-29 17:26:57 +01:00
|
|
|
|
<div class="paging-options-reverse">
|
|
|
|
|
<button @click="$store.files.toggleTootsOrder()">
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#toggle-order" /></svg
|
|
|
|
|
><span class="btn-label">Reverse order</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="direction-fwd">
|
|
|
|
|
<button
|
|
|
|
|
id="paging-btn-next"
|
|
|
|
|
@click="$store.files.nextPage()"
|
|
|
|
|
:disabled="$store.files.currentPage >= $store.files.totalPages"
|
|
|
|
|
>
|
|
|
|
|
<span class="btn-label">Next</span
|
|
|
|
|
><svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-next" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
id="paging-btn-last"
|
|
|
|
|
@click="$store.files.lastPage()"
|
|
|
|
|
:disabled="$store.files.currentPage >= $store.files.totalPages"
|
|
|
|
|
>
|
|
|
|
|
<span class="btn-label">Last</span
|
|
|
|
|
><svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-last" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="toots"
|
|
|
|
|
id="toots"
|
|
|
|
|
role="region"
|
|
|
|
|
aria-labelledby="toots-title"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
>
|
|
|
|
|
<h2 id="toots-title" class="visually-hidden">Posts</h2>
|
|
|
|
|
|
|
|
|
|
<template
|
|
|
|
|
x-show="$store.files.pagedToots.length"
|
|
|
|
|
x-for="toot in await $store.files.pagedToots"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="toot"
|
|
|
|
|
:class="['toot-type-' + contentType(toot.type).toLowerCase(), 'toot-visibility-' + toot._marl.visibility[0]]"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
:style="'--actor-hue: '+ $store.files.sources[toot._marl.source].hue"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
|
|
|
|
<h3 class="toot-header visually-hidden">
|
|
|
|
|
<span x-text="contentType(toot.type)"></span>
|
|
|
|
|
by <span x-text="formatAuthor(toot.actor, true)"></span>,
|
|
|
|
|
<span x-text="formatDateTime(toot.published)"></span>
|
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<template x-if="toot.type === 'Create'">
|
|
|
|
|
<div class="toot-pretty">
|
|
|
|
|
<div class="toot-summary" x-show="toot.object.summary">
|
|
|
|
|
<span x-text="toot.object.summary"></span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="toot-content"
|
|
|
|
|
x-html="toot.object.content"
|
|
|
|
|
></div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="toot-attachments"
|
|
|
|
|
x-show="toot.object.attachment && toot.object.attachment.length"
|
|
|
|
|
>
|
|
|
|
|
<ul>
|
|
|
|
|
<template
|
|
|
|
|
x-for="(att, index) in toot.object.attachment"
|
|
|
|
|
>
|
|
|
|
|
<li
|
|
|
|
|
:class="attachmentWrapperClass(att)"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
:data-trigger="loadAttachedMedia(att, toot._marl.source)"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
|
|
|
|
<!-- image -->
|
|
|
|
|
<template
|
2024-12-04 21:58:42 +01:00
|
|
|
|
x-if="attachmentIsImage(att) && $store.files.sources[toot._marl.source][att.url]"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
|
|
|
|
<div class="att-wrapper">
|
|
|
|
|
<button
|
|
|
|
|
class="att-img-wrapper"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
@click="$store.lightbox.open(toot, index, toot._marl.id + '-' + index)"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
:id="toot._marl.id + '-' + index"
|
|
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
alt=""
|
2024-12-04 21:58:42 +01:00
|
|
|
|
:src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
:aria-labelledby="toot._marl.id + '-' + index + '-desc'"
|
|
|
|
|
/>
|
|
|
|
|
</button>
|
|
|
|
|
<div
|
|
|
|
|
class="att-description"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
:id="toot._marl.id + '-' + index + '-desc'"
|
|
|
|
|
>
|
|
|
|
|
<span
|
|
|
|
|
class="desc-body"
|
|
|
|
|
x-text="att.name ?? 'No description provided'"
|
|
|
|
|
></span>
|
|
|
|
|
<span class="desc-source"
|
|
|
|
|
><strong>In archive:</strong>
|
|
|
|
|
<span x-text="att.url"></span
|
|
|
|
|
></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<!-- sound -->
|
|
|
|
|
<template
|
2024-12-04 21:58:42 +01:00
|
|
|
|
x-if="attachmentIsSound(att) && $store.files.sources[toot._marl.source][att.url]"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
|
|
|
|
<div class="att-wrapper">
|
|
|
|
|
<audio
|
|
|
|
|
controls
|
2024-12-04 21:58:42 +01:00
|
|
|
|
:src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
:aria-labelledby="toot._marl.id + '-' + index + '-desc'"
|
|
|
|
|
></audio>
|
|
|
|
|
<div
|
|
|
|
|
class="att-description"
|
|
|
|
|
:id="toot._marl.id + '-' + index + '-desc'"
|
|
|
|
|
>
|
|
|
|
|
<span
|
|
|
|
|
class="desc-body"
|
|
|
|
|
x-text="att.name ?? 'No description provided'"
|
|
|
|
|
></span>
|
|
|
|
|
<span class="desc-source"
|
|
|
|
|
><strong>In archive:</strong>
|
|
|
|
|
<span x-text="att.url"></span
|
|
|
|
|
></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<!-- video -->
|
|
|
|
|
<template
|
2024-12-04 21:58:42 +01:00
|
|
|
|
x-if="attachmentIsVideo(att) && $store.files.sources[toot._marl.source][att.url]"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
>
|
|
|
|
|
<div class="att-wrapper">
|
|
|
|
|
<video
|
|
|
|
|
controls
|
|
|
|
|
:width="att.width"
|
|
|
|
|
:height="att.height"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
:src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
:aria-labelledby="toot._marl.id + '-' + index + '-desc'"
|
|
|
|
|
></video>
|
|
|
|
|
<div
|
|
|
|
|
class="att-description"
|
|
|
|
|
:id="toot._marl.id + '-' + index + '-desc'"
|
|
|
|
|
>
|
|
|
|
|
<span
|
|
|
|
|
class="desc-body"
|
|
|
|
|
x-text="att.name ?? 'No description provided'"
|
|
|
|
|
></span>
|
|
|
|
|
<span class="desc-source"
|
|
|
|
|
><strong>In archive:</strong>
|
|
|
|
|
<span x-text="att.url"></span
|
|
|
|
|
></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template
|
|
|
|
|
x-if="toot.type === 'Announce' && toot.object && toot.object.content"
|
|
|
|
|
>
|
|
|
|
|
<div class="toot-pretty">
|
|
|
|
|
<div class="toot-content">
|
|
|
|
|
<div
|
|
|
|
|
class="toot-content-inner"
|
|
|
|
|
x-html="toot.object.content"
|
|
|
|
|
></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template
|
|
|
|
|
x-if="toot.type === 'Announce' && toot.object && !toot.object.content"
|
|
|
|
|
>
|
|
|
|
|
<div class="toot-pretty">
|
|
|
|
|
<div class="toot-content">
|
|
|
|
|
<div class="toot-content-inner">
|
|
|
|
|
<a :href="toot.object" x-text="toot.object"></a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<div class="toot-infos">
|
|
|
|
|
<span class="type">
|
|
|
|
|
<span x-text="contentType(toot.type)"></span>
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<span class="author">
|
|
|
|
|
by
|
|
|
|
|
<span x-html="formatAuthor(toot.actor)"></span>
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<span class="published"
|
|
|
|
|
><span x-text="formatDateTime(toot.published)"></span>
|
|
|
|
|
<span
|
|
|
|
|
x-show="toot.object && toot.object.updated"
|
|
|
|
|
class="updated"
|
|
|
|
|
>
|
|
|
|
|
Last updated
|
|
|
|
|
<span
|
|
|
|
|
x-text="formatDateTime(toot.object.updated)"
|
|
|
|
|
></span>
|
|
|
|
|
</span>
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<span class="visibility">
|
|
|
|
|
<span x-text="toot._marl.visibility[1]"></span>
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<span class="link">
|
|
|
|
|
<a x-show="toot.object.id" :href="toot.object.id">link</a>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<template
|
|
|
|
|
x-if="(toot.object.tag && toot.object.tag.length) || (toot._marl.externalLinks && toot._marl.externalLinks.length)"
|
|
|
|
|
>
|
|
|
|
|
<div class="toot-meta">
|
|
|
|
|
<template
|
|
|
|
|
x-if="toot.object.tag && toot.object.tag.filter(x => x.type === 'Mention').length"
|
|
|
|
|
>
|
|
|
|
|
<div class="toot-people">
|
|
|
|
|
<h4>People</h4>
|
|
|
|
|
<ul>
|
|
|
|
|
<template x-for="tag in toot.object.tag">
|
|
|
|
|
<li x-show="tag.type === 'Mention'">
|
|
|
|
|
<a :href="tag.href" x-text="tag.name"></a>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template
|
|
|
|
|
x-if="toot.object.tag && toot.object.tag.filter(x => x.type === 'Hashtag').length"
|
|
|
|
|
>
|
|
|
|
|
<div class="toot-hashtags">
|
|
|
|
|
<h4>Hashtags</h4>
|
|
|
|
|
<ul>
|
|
|
|
|
<template x-for="tag in toot.object.tag">
|
|
|
|
|
<li x-show="tag.type === 'Hashtag'">
|
|
|
|
|
<a :href="tag.href" x-text="tag.name"></a>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template x-if="toot._marl.externalLinks.length">
|
|
|
|
|
<div class="toot-links">
|
|
|
|
|
<h4>External links</h4>
|
|
|
|
|
<ul>
|
|
|
|
|
<template x-for="link in toot._marl.externalLinks">
|
|
|
|
|
<li>
|
|
|
|
|
<a :href="link.href" x-text="link.text"></a>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<div class="toot-raw">
|
|
|
|
|
<details>
|
|
|
|
|
<summary>
|
|
|
|
|
<span class="summary-icon">
|
|
|
|
|
<svg aria-hidden="true">
|
|
|
|
|
<use href="#json" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<span class="summary-label" :id="'raw-' + toot._marl.id"
|
|
|
|
|
>Raw data</span
|
|
|
|
|
>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</summary>
|
|
|
|
|
<div class="details-content">
|
2024-12-09 15:20:29 +01:00
|
|
|
|
<textarea
|
|
|
|
|
x-text="formatJson(toot)"
|
|
|
|
|
:aria-labelledby="'raw-' + toot._marl.id"
|
|
|
|
|
readonly
|
|
|
|
|
></textarea>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="toots-no-results"
|
|
|
|
|
x-show="$store.files.pagedToots.length === 0"
|
|
|
|
|
>
|
|
|
|
|
<div x-show="$store.files.filtersActive">
|
|
|
|
|
<p>No results for the specified filters</p>
|
|
|
|
|
<p class="action">
|
|
|
|
|
<button
|
2024-12-01 10:45:20 +01:00
|
|
|
|
@click="$store.files.resetFilters(true)"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
:disabled="!$store.files.filtersActive"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#reset-filters" /></svg
|
|
|
|
|
><span class="btn-label">Reset filters</span>
|
|
|
|
|
</button>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div x-show="!$store.files.filtersActive">
|
|
|
|
|
<p>No posts found in archive (?!)</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="paging">
|
|
|
|
|
<div class="direction-back">
|
|
|
|
|
<button
|
|
|
|
|
@click="$store.files.firstPage('toots')"
|
|
|
|
|
:disabled="$store.files.currentPage <= 1"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-first" /></svg
|
|
|
|
|
><span class="btn-label">First</span>
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
@click="$store.files.prevPage('paging-btn-prev')"
|
|
|
|
|
:disabled="$store.files.currentPage <= 1"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-prev" /></svg
|
|
|
|
|
><span class="btn-label">Prev</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="direction-fwd">
|
|
|
|
|
<button
|
|
|
|
|
@click="$store.files.nextPage('paging-btn-next')"
|
|
|
|
|
:disabled="$store.files.currentPage >= $store.files.totalPages"
|
|
|
|
|
>
|
|
|
|
|
<span class="btn-label">Next</span
|
|
|
|
|
><svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-next" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
@click="$store.files.lastPage('toots')"
|
|
|
|
|
:disabled="$store.files.currentPage >= $store.files.totalPages"
|
|
|
|
|
>
|
|
|
|
|
<span class="btn-label">Last</span
|
|
|
|
|
><svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#nav-last" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<aside
|
|
|
|
|
class="toots-tags mobile-menu-panel"
|
|
|
|
|
id="panel-tags"
|
|
|
|
|
aria-labelledby="toots-tags-title"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
class="panel-close"
|
|
|
|
|
@click="$store.ui.menuClose()"
|
|
|
|
|
x-show="$store.ui.menuIsActive"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#close" /></svg
|
|
|
|
|
><span class="visually-hidden">Close panel</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<h2 class="tags-title" id="toots-tags-title">Tags</h2>
|
|
|
|
|
|
|
|
|
|
<div class="tags-group">
|
|
|
|
|
<div class="tags-group-header">
|
|
|
|
|
<h3>
|
|
|
|
|
Hashtags
|
|
|
|
|
<span class="count">
|
|
|
|
|
(<span
|
|
|
|
|
x-text="formatNumber($store.files.listHashtags.length)"
|
|
|
|
|
></span
|
|
|
|
|
>)
|
|
|
|
|
</span>
|
|
|
|
|
</h3>
|
|
|
|
|
<div class="tags-group-filter">
|
|
|
|
|
<label
|
|
|
|
|
for="tags-group-hashtags-filter"
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
>filter hashtags</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
id="tags-group-hashtags-filter"
|
|
|
|
|
type="text"
|
|
|
|
|
onClick="this.select()"
|
|
|
|
|
x-model.debounce="$store.files.tagsFilters.hashtags"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="tags-group-scroll">
|
|
|
|
|
<ul x-show="$store.files.listHashtags.length">
|
|
|
|
|
<template x-for="item in await $store.files.listHashtags">
|
|
|
|
|
<li
|
|
|
|
|
:class="item.name === $store.files.filters.hashtagText ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
:id="'filter-hashtag-' + item.name.toLowerCase().slice(1)"
|
|
|
|
|
@click="$store.files.filterByTag('hashtagText', item.name, 'filter-hashtag-' + item.name.toLowerCase().slice(1))"
|
|
|
|
|
>
|
|
|
|
|
<div>
|
|
|
|
|
<span
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
x-text="item.name === $store.files.filters.hashtagText ? 'active item:' : ''"
|
|
|
|
|
></span>
|
|
|
|
|
<span class="count" x-text="`(${item.nb})`"></span>
|
|
|
|
|
<span class="name" x-text="item.name"></span>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="tags-group">
|
|
|
|
|
<div class="tags-group-header">
|
|
|
|
|
<h3>
|
|
|
|
|
Mentions
|
|
|
|
|
<span class="count">
|
|
|
|
|
(<span
|
|
|
|
|
x-text="formatNumber($store.files.listMentions.length)"
|
|
|
|
|
></span
|
|
|
|
|
>)
|
|
|
|
|
</span>
|
|
|
|
|
</h3>
|
|
|
|
|
<div class="tags-group-filter">
|
|
|
|
|
<label
|
|
|
|
|
for="tags-group-mentions-filter"
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
>filter hashtags</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
id="tags-group-mentions-filter"
|
|
|
|
|
type="text"
|
|
|
|
|
onClick="this.select()"
|
|
|
|
|
x-model.debounce="$store.files.tagsFilters.mentions"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="tags-group-scroll">
|
|
|
|
|
<ul x-show="$store.files.listMentions.length">
|
|
|
|
|
<template x-for="item in await $store.files.listMentions">
|
|
|
|
|
<li
|
|
|
|
|
:class="item.name === $store.files.filters.mentionText ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
:id="'filter-mention-' + item.name.toLowerCase().replaceAll('@', '_').replaceAll('.', '_')"
|
|
|
|
|
@click="$store.files.filterByTag('mentionText', item.name, 'filter-mention-' + item.name.toLowerCase().replaceAll('@', '_').replaceAll('.', '_'))"
|
|
|
|
|
>
|
|
|
|
|
<div>
|
|
|
|
|
<span
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
x-text="item.name === $store.files.filters.mentionText ? 'active item:' : ''"
|
|
|
|
|
></span>
|
|
|
|
|
<span class="count" x-text="`(${item.nb})`"></span>
|
|
|
|
|
<span class="name" x-text="item.name"></span>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="tags-group">
|
|
|
|
|
<div class="tags-group-header">
|
|
|
|
|
<h3>
|
|
|
|
|
Boosted users
|
|
|
|
|
<span class="count">
|
|
|
|
|
(<span
|
|
|
|
|
x-text="formatNumber($store.files.listBoostsAuthors.length)"
|
|
|
|
|
></span
|
|
|
|
|
>)
|
|
|
|
|
</span>
|
|
|
|
|
</h3>
|
|
|
|
|
<div class="tags-group-filter">
|
|
|
|
|
<label
|
|
|
|
|
for="tags-group-boosts-authors-filter"
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
>filter boosts users</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
id="tags-group-boosts-authors-filter"
|
|
|
|
|
type="text"
|
|
|
|
|
onClick="this.select()"
|
|
|
|
|
x-model.debounce="$store.files.tagsFilters.boostsAuthors"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="tags-group-scroll">
|
|
|
|
|
<ul x-show="$store.files.listBoostsAuthors.length">
|
|
|
|
|
<template x-for="item in $store.files.listBoostsAuthors">
|
|
|
|
|
<li
|
|
|
|
|
:class="item.url === $store.files.filters.fullText ? 'active' : ''"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
@click="$store.files.filterByTag('fullText', item.url, 'filter-boost-author-' + item.url.toLowerCase().replaceAll('/', '_'))"
|
|
|
|
|
:id="'filter-boost-author-' + item.url.toLowerCase().replaceAll('/', '_')"
|
|
|
|
|
>
|
|
|
|
|
<div>
|
|
|
|
|
<span
|
|
|
|
|
class="visually-hidden"
|
|
|
|
|
x-text="item.url === $store.files.filters.fullText ? 'active item:' : ''"
|
|
|
|
|
></span>
|
|
|
|
|
<span class="count" x-text="`(${item.nb})`"></span>
|
|
|
|
|
<span class="name">
|
|
|
|
|
<span x-text="item.name"></span>
|
|
|
|
|
<span x-text="item.domain" class="domain"></span>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
</template>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</aside>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<template x-if="$store.lightbox.show && $store.lightbox.data.length">
|
|
|
|
|
<div
|
|
|
|
|
id="lightbox"
|
|
|
|
|
class="lightbox overlay"
|
|
|
|
|
tabindex="-1"
|
|
|
|
|
@keyup.left="$store.lightbox.showPrev()"
|
|
|
|
|
@keyup.right="$store.lightbox.showNext()"
|
|
|
|
|
@keyup.esc="$store.lightbox.close()"
|
|
|
|
|
>
|
|
|
|
|
<div class="overlay-content">
|
|
|
|
|
<img
|
|
|
|
|
:alt="$store.lightbox.data[$store.lightbox.index].name"
|
2024-12-04 21:58:42 +01:00
|
|
|
|
:src="`data:${$store.lightbox.data[$store.lightbox.index].mediaType}; base64,${$store.files.sources[$store.lightbox.source][$store.lightbox.data[$store.lightbox.index].url].content}`"
|
2024-11-29 14:58:03 +01:00
|
|
|
|
@click="$store.lightbox.showNext()"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="overlay-ui">
|
|
|
|
|
<div class="backdrop" @click="$store.lightbox.close()"></div>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
x-show="$store.lightbox.data.length > 1"
|
|
|
|
|
class="viewer-next"
|
|
|
|
|
@click="$store.lightbox.showNext()"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#viewer-next" /></svg
|
|
|
|
|
><span class="visually-hidden">Next image</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
x-show="$store.lightbox.data.length > 1"
|
|
|
|
|
class="viewer-prev"
|
|
|
|
|
@click="$store.lightbox.showPrev()"
|
|
|
|
|
>
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#viewer-prev" /></svg
|
|
|
|
|
><span class="visually-hidden">Previous image</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<button class="viewer-close" @click="$store.lightbox.close()">
|
|
|
|
|
<svg class="btn-icon" aria-hidden="true">
|
|
|
|
|
<use href="#close" /></svg
|
|
|
|
|
><span class="visually-hidden">Close image</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</main>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<svg style="display: none">
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="reset-filters">
|
|
|
|
|
<path
|
|
|
|
|
d="m653-208-46 46q-17 17-42 17.5T522-162q-17-17-17-42.5t17-42.5l46-46q-4-11-6-23t-2-24q0-58 41-99t99-41q9 0 18 .5t17 3.5q11 4 13.5 16.5T743-439l-43 43q-11 11-11 28t11 28q11 11 28 11t28-11l43-43q8-8 20.5-5.5T836-375q3 8 3.5 17t.5 18q0 58-41 99t-99 41q-13 0-24.5-2t-22.5-6ZM480-760q-117 0-198.5 81.5T200-480q0 72 32.5 132t87.5 98v-70q0-17 11.5-28.5T360-360q17 0 28.5 11.5T400-320v160q0 17-11.5 28.5T360-120H200q-17 0-28.5-11.5T160-160q0-17 11.5-28.5T200-200h54q-62-50-98-122.5T120-480q0-75 28.5-140.5t77-114q48.5-48.5 114-77T480-840q113 0 203.5 63T814-615q6 16 0 31t-22 21q-16 6-31.5 0T739-585q-31-78-100.5-126.5T480-760Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="toggle-order">
|
|
|
|
|
<path
|
|
|
|
|
d="M360-440q-17 0-28.5-11.5T320-480v-247l-75 75q-11 11-27.5 11T189-652q-12-12-12-28.5t12-28.5l143-143q6-6 13-8.5t15-2.5q8 0 15 2.5t13 8.5l144 144q12 12 11.5 28T531-652q-12 11-28 11.5T475-652l-75-75v247q0 17-11.5 28.5T360-440ZM600-97q-8 0-15-2.5t-13-8.5L428-252q-12-12-11.5-28t12.5-28q12-11 28-11.5t28 11.5l75 75v-247q0-17 11.5-28.5T600-520q17 0 28.5 11.5T640-480v247l75-75q11-11 27.5-11t28.5 11q12 12 12 28.5T771-251L628-108q-6 6-13 8.5T600-97Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="load-file">
|
|
|
|
|
<path
|
|
|
|
|
d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h360q17 0 28.5 11.5T880-680q0 17-11.5 28.5T840-640H447l-80-80H160v480l79-263q8-26 29.5-41.5T316-560h516q41 0 64.5 32.5T909-457l-72 240q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm-84-262v-218 218Zm84 262 72-240-72 240Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="nav-first">
|
|
|
|
|
<path
|
|
|
|
|
d="m313-480 155 156q11 11 11.5 27.5T468-268q-11 11-28 11t-28-11L228-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T468-692q11 11 11 28t-11 28L313-480Zm264 0 155 156q11 11 11.5 27.5T732-268q-11 11-28 11t-28-11L492-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T732-692q11 11 11 28t-11 28L577-480Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="nav-prev">
|
|
|
|
|
<path
|
|
|
|
|
d="m432-480 156 156q11 11 11 28t-11 28q-11 11-28 11t-28-11L348-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 28-11t28 11q11 11 11 28t-11 28L432-480Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="nav-next">
|
|
|
|
|
<path
|
|
|
|
|
d="M504-480 348-636q-11-11-11-28t11-28q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L404-268q-11 11-28 11t-28-11q-11-11-11-28t11-28l156-156Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="nav-last">
|
|
|
|
|
<path
|
|
|
|
|
d="M383-480 228-636q-11-11-11.5-27.5T228-692q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L284-268q-11 11-27.5 11.5T228-268q-11-11-11-28t11-28l155-156Zm264 0L492-636q-11-11-11.5-27.5T492-692q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L548-268q-11 11-27.5 11.5T492-268q-11-11-11-28t11-28l155-156Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="close">
|
|
|
|
|
<path
|
|
|
|
|
d="M480-424 284-228q-11 11-28 11t-28-11q-11-11-11-28t11-28l196-196-196-196q-11-11-11-28t11-28q11-11 28-11t28 11l196 196 196-196q11-11 28-11t28 11q11 11 11 28t-11 28L536-480l196 196q11 11 11 28t-11 28q-11 11-28 11t-28-11L480-424Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="viewer-next">
|
|
|
|
|
<path
|
|
|
|
|
d="M504-480 348-636q-11-11-11-28t11-28q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L404-268q-11 11-28 11t-28-11q-11-11-11-28t11-28l156-156Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="viewer-prev">
|
|
|
|
|
<path
|
|
|
|
|
d="m432-480 156 156q11 11 11 28t-11 28q-11 11-28 11t-28-11L348-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 28-11t28 11q11 11 11 28t-11 28L432-480Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="menu-actor">
|
|
|
|
|
<path
|
|
|
|
|
d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-240v-32q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v32q0 33-23.5 56.5T720-160H240q-33 0-56.5-23.5T160-240Zm80 0h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm240-320q33 0 56.5-23.5T560-640q0-33-23.5-56.5T480-720q-33 0-56.5 23.5T400-640q0 33 23.5 56.5T480-560Zm0-80Zm0 400Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="menu-filters">
|
|
|
|
|
<path
|
|
|
|
|
d="M440-240q-17 0-28.5-11.5T400-280q0-17 11.5-28.5T440-320h80q17 0 28.5 11.5T560-280q0 17-11.5 28.5T520-240h-80ZM280-440q-17 0-28.5-11.5T240-480q0-17 11.5-28.5T280-520h400q17 0 28.5 11.5T720-480q0 17-11.5 28.5T680-440H280ZM160-640q-17 0-28.5-11.5T120-680q0-17 11.5-28.5T160-720h640q17 0 28.5 11.5T840-680q0 17-11.5 28.5T800-640H160Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="menu-tags">
|
|
|
|
|
<path
|
|
|
|
|
d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h440q19 0 36 8.5t28 23.5l180 240q16 21 16 48t-16 48L664-192q-11 15-28 23.5t-36 8.5H160Zm0-80h440l180-240-180-240H160v480Zm310-240Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="menu-new">
|
|
|
|
|
<path
|
|
|
|
|
d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h360q17 0 28.5 11.5T880-680q0 17-11.5 28.5T840-640H447l-80-80H160v480l79-263q8-26 29.5-41.5T316-560h516q41 0 64.5 32.5T909-457l-72 240q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm-84-262v-218 218Zm84 262 72-240-72 240Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="fetch-data">
|
|
|
|
|
<path
|
|
|
|
|
d="M440-474v-242q-76 14-118 73.5T280-520h-20q-58 0-99 41t-41 99q0 58 41 99t99 41h480q42 0 71-29t29-71q0-42-29-71t-71-29h-60v-80q0-48-22-89.5T600-680v-93q74 35 117 103.5T760-520q69 8 114.5 59.5T920-340q0 75-52.5 127.5T740-160H260q-91 0-155.5-63T40-377q0-78 47-139t123-78q17-72 85-137t145-65q33 0 56.5 23.5T520-716v242l36-35q11-11 27.5-11t28.5 12q11 11 11 28t-11 28L508-348q-12 12-28 12t-28-12L348-452q-11-11-11.5-27.5T348-508q11-11 27.5-11.5T404-509l36 35Zm40-44Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="options">
|
|
|
|
|
<path
|
|
|
|
|
d="M433-80q-27 0-46.5-18T363-142l-9-66q-13-5-24.5-12T307-235l-62 26q-25 11-50 2t-39-32l-47-82q-14-23-8-49t27-43l53-40q-1-7-1-13.5v-27q0-6.5 1-13.5l-53-40q-21-17-27-43t8-49l47-82q14-23 39-32t50 2l62 26q11-8 23-15t24-12l9-66q4-26 23.5-44t46.5-18h94q27 0 46.5 18t23.5 44l9 66q13 5 24.5 12t22.5 15l62-26q25-11 50-2t39 32l47 82q14 23 8 49t-27 43l-53 40q1 7 1 13.5v27q0 6.5-2 13.5l53 40q21 17 27 43t-8 49l-48 82q-14 23-39 32t-50-2l-60-26q-11 8-23 15t-24 12l-9 66q-4 26-23.5 44T527-80h-94Zm7-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="json">
|
|
|
|
|
<path
|
|
|
|
|
d="M190-360h70q17 0 28.5-11.5T300-400v-200h-60v190h-40v-50h-50v60q0 17 11.5 28.5T190-360Zm177 0h60q17 0 28.5-11.5T467-400v-60q0-17-11.5-28.5T427-500h-50v-50h40v20h50v-30q0-17-11.5-28.5T427-600h-60q-17 0-28.5 11.5T327-560v60q0 17 11.5 28.5T367-460h50v50h-40v-20h-50v30q0 17 11.5 28.5T367-360Zm176-60v-120h40v120h-40Zm-10 60h60q17 0 28.5-11.5T633-400v-160q0-17-11.5-28.5T593-600h-60q-17 0-28.5 11.5T493-560v160q0 17 11.5 28.5T533-360Zm127 0h50v-105l40 105h50v-240h-50v105l-40-105h-50v240ZM120-160q-33 0-56.5-23.5T40-240v-480q0-33 23.5-56.5T120-800h720q33 0 56.5 23.5T920-720v480q0 33-23.5 56.5T840-160H120Zm0-80h720v-480H120v480Zm0 0v-480 480Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="question">
|
|
|
|
|
<path
|
|
|
|
|
d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="bookmark">
|
|
|
|
|
<path
|
|
|
|
|
d="M200-120v-640q0-33 23.5-56.5T280-840h400q33 0 56.5 23.5T760-760v640L480-240 200-120Zm80-122 200-86 200 86v-518H280v518Zm0-518h400-400Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
<symbol viewBox="0 -960 960 960" id="favorite">
|
|
|
|
|
<path
|
|
|
|
|
d="m354-287 126-76 126 77-33-144 111-96-146-13-58-136-58 135-146 13 111 97-33 143ZM233-120l65-281L80-590l288-25 112-265 112 265 288 25-218 189 65 281-247-149-247 149Zm247-350Z"
|
|
|
|
|
/>
|
|
|
|
|
</symbol>
|
|
|
|
|
</svg>
|
2024-12-01 10:45:20 +01:00
|
|
|
|
|
2024-12-14 17:28:54 +01:00
|
|
|
|
<script src="js/main.js?20241215"></script>
|
2024-11-29 14:58:03 +01:00
|
|
|
|
</body>
|
|
|
|
|
</html>
|