1
0
mirror of https://github.com/s427/MARL.git synced 2025-01-31 11:34:46 +01:00

22 lines
45 KiB
HTML
Raw Normal View History

2025-01-09 15:24:56 +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"><link rel="stylesheet" href="./_astro/index.uwcihdcd.css"></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" x-init="$watch('$store.files.appReady', value => checkAppReady(value))"> <template x-if="!$store.files.appReady && !$store.files.someFilesLoaded && !$store.files.loading"> <main class="welcome"> <div class="intro"> <h1 x-html="$t('welcome.title', {appName: `MARL <span class='accronym'>(Mastodon Archive Reader Lite)</span>`})"></h1> <p x-html="$t('welcome.p1')"></p> <p x-html="$t('welcome.p2')"></p> <p x-html="$t('welcome.p3', {labelStart: `<label for='file-loader' tabindex='0'>`, labelEnd: `</label>`})"></p> <input id="file-loader" class="file-loader" type="file" accept=".zip" multiple @change="unZip(Object.values($event.target.files))"> </div> <div class="about"> <a href="https://github.com/s427/MARL"> <span x-text="$t('welcome.projectPage')"></span> </a> </div> </main> </template> <template x-if="(!$store.files.appReady && $store.files.someFilesLoaded) || $store.files.loading"> <main class="welcome loading-more"> <div class="intro"> <div class="file-loader loading"> <div>... <span x-text="$t('misc.loading')"></span> ...</div> <div class="filename" x-text="$store.files.loadingName"></div> </div> </div> </main> </template> <template x-if="$store.files.appReady"> <main class="main-section" id="main-section" tabindex="-1" x-on:resize.window="$store.ui.checkMenuState()"> <div class="main-section-inner" id="main-section-inner" :class="$store.files.sources.length > 1 ? 'multiple-actors' : ''"> <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"></use></svg> <span x-text="$t('menu.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"></use></svg> <span x-text="$t('menu.filters')"></span> <em x-text="$t('menu.filtersActive')" x-show="$store.files.filtersActive" class="visually-hidden"></em> </button> </li> <li> <button class="menu-tags" @click="$store.ui.menuToggle('tags')"> <svg aria-hidden="true"><use href="#menu-tags"></use></svg> <span x-text="$t('menu.tags')"></span> </button> </li> <li> <button class="menu-new" @click="startOver"> <svg aria-hidden="true"><use href="#menu-new"></use></svg> <span x-text="$t('menu.newFile')"></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"></use> </svg> <span class="visually-hidden" x-text="$t('misc.closePanelBtn')"></span> </button> <h2 class="visually-hidden" id="actor-title" x-text="$t('actor.accountInfo')"></h2> <h3 class="visually-hidden" id="actor-tabs-title" x-text="$t('actor.accounts')"></h3> <div class="actors-wrapper" :style="'--actor-hue: '+ $store.files.sources[$store.ui.actorPanel].hue"> <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.switchActorP
(<span class="count" x-text="source.likes.length"></span>)
</h2> </summary> <div class="details-content"> <template x-if="source.likes.length"> <ul> <template x-for="url in source.likes"> <li> <a :href="url" x-html="formatLikesBookmarks(url)"></a> </li> </template> </ul> </template> <template x-if="! source.likes.length"> <p class="no-content">&nbsp;<span x-text="$t('actor.likesEmpty')"></span>&nbsp;</p> </template> </div> </details> </div> <div class="actor-bookmarks"> <details> <summary> <span class="summary-icon"> <svg aria-hidden="true"> <use href="#favorite"></use> </svg> </span> <h2 class="summary-label"> <span x-text="$t('actor.bookmarks')"></span>
(<span class="count" x-text="source.bookmarks.length"></span>)
</h2> </summary> <div class="details-content"> <template x-if="source.bookmarks.length"> <ul> <template x-for="url in source.bookmarks"> <li> <a :href="url" x-html="formatLikesBookmarks(url)"></a> </li> </template> </ul> </template> <template x-if="! source.bookmarks.length"> <p class="no-content">&nbsp;<span x-text="$t('actor.bookmarksEmpty')"></span>&nbsp;</p> </template> </div> </details> </div> </div> </div> </template> </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"></use> </svg> <span class="visually-hidden" x-text="$t('misc.closePanelBtn')"></span> </button> <h2 id="toots-filter-title" x-text="$t('filters.panelTitle')"></h2> <p class="visually-hidden" x-text="$t('filters.panelNotice')"></p> <div class="toots-filters-group"> <div class="toots-filter text" :class="isFilterActive('fullText') ? 'active' : ''"> <label for="filter-fullText" x-text="$t('filters.fullText')"></label> <div class="input-wrapper"> <input id="filter-fullText" 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-hashtagText" x-text="$t('filters.hashtagText')"></label> <div class="input-wrapper"> <input id="filter-hashtagText" 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-mentionText" x-text="$t('filters.mentionText')"></label> <div class="input-wrapper"> <input id="filter-mentionText" 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-externalLink" x-text="$t('filters.externalLink')"></label> <div class="input-wrapper"> <input id="filter-externalLink" 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" x-text="$t('filters.summary')"></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> </div> <div class="toots-filters-group"> <div class="toots-filter checkbox" :class="isFilterActive('isEdited') ? 'active' : ''"> <label for="filter-isEdited"> <input id="filter-isEdited" type="checkbox" x-model.debounce="$store.files.filters.isEdited" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.isEdited')"></span> </label> </div> <template x-show="$store.files.duplicates"> <div class="toots-filter checkbox" :class="isFilterActive('isDuplicate') ? 'active' : ''"> <label for="filter-isDuplicate"> <input id="filter-isDuplicate" type="checkbox" x-model.debounce="$store.files.filters.isDuplicate" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.isDuplicate')"></span> </label> </div> </template> </div> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.mustContain')"></h3> <div class="toots-filter checkbox" :class="isFilterActive('hasHashtags') ? 'active' : ''"> <label for="filter-hasHashtags"> <input id="filter-hasHashtags" type="checkbox" x-model.debounce="$store.files.filters.hasHashtags" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.hasHashtags')"></span> </la
2025-01-06 18:14:41 +01:00
(<span x-text="lang[1]"></span>)
2025-01-09 15:24:56 +01:00
</span> </label> </div> </template> </div> <template x-if="$store.files.sources.length > 1"> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.author')"></h3> <template x-for="source in $store.files.sources"> <div class="toots-filter checkbox" :class="isFilterActive('actor_' + source.id) ? 'active' : ''"> <label :for="'filter-actor-' + source.id"> <input :id="'filter-actor-' + source.id" type="checkbox" x-model="$store.files.filters['actor_' + source.id]" @change="$store.files.setFilter()"> <span> <span x-text="source.actor.name"></span> </span> </label> </div> </template> </div> </template> <div class="toots-filters-reset"> <button @click="$store.files.resetFilters(true)" :disabled="!$store.files.filtersActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#reset-filters"></use> </svg> <span class="btn-label" x-text="$t('filters.resetFilters')"></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> <span x-text="$t('header.countLabel')"></span> </span> <span class="order">
2025-01-06 18:14:41 +01:00
-
2025-01-09 15:24:56 +01:00
<span x-text="await $store.files.sortAsc ? $t('header.oldestFirst') : $t('header.latestFirst')"></span> <button @click="$store.files.toggleTootsOrder()" class="toggle-order"> <svg class="btn-icon" aria-hidden="true"> <use href="#toggle-order"></use> </svg> <span class="btn-label" x-text="$t('header.reverse')"></span> </button> </span> <button @click="startOver" class="load-new"> <svg class="btn-icon" aria-hidden="true"> <use href="#load-file"></use></svg><span class="btn-label" x-text="$t('header.loadNewFile')"></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"></use> </svg> <span class="btn-label" x-text="$t('paging.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"></use> </svg> <span class="btn-label" x-text="$t('paging.prev')"></span> </button> </div> <div class="paging-options-toggle"> <button @click="$store.ui.togglePagingOptions()"> <svg class="btn-icon" aria-hidden="true"> <use href="#options"></use> </svg> <span class="btn-label" x-text="$t('paging.pagingOptions')"></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" x-text="$t('paging.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()">
2025-01-06 18:14:41 +01:00
/
<span class="total-pages" x-text="formatNumber($store.files.totalPages)"></span>
(
2025-01-09 15:24:56 +01:00
<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" x-text="$t('paging.postsPerPage')"></label>)
</div> <div class="paging-options-reverse"> <button @click="$store.files.toggleTootsOrder()"> <svg class="btn-icon" aria-hidden="true"> <use href="#toggle-order"></use> </svg> <span class="btn-label" x-text="$t('paging.reverseOrder')"></span> </button> </div> </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" x-text="$t('paging.next')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-next"></use> </svg> </button> <button id="paging-btn-last" @click="$store.files.lastPage()" :disabled="$store.files.currentPage >= $store.files.totalPages"> <span class="btn-label" x-text="$t('paging.last')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-last"></use> </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" x-text="$t('posts.panelTitle')"></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]]" :style="'--actor-hue: '+ $store.files.sources[toot._marl.source].hue"> <h3 class="toot-header visually-hidden"> <span x-text="contentType(toot.type)"></span> <span x-text="$t('post.by')"></span> <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)" :data-trigger="loadAttachedMedia(att, toot._marl.source)"> <template x-if="attachmentIsImage(att) && $store.files.sources[toot._marl.source][att.url]"><div class="att-wrapper"><button class="att-img-wrapper" @click="$store.lightbox.open(toot, index, 'att-' + toot._marl.id + '-' + index)" :id="'att-' + toot._marl.id + '-' + index"><img alt="" :src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`" :aria-labelledby="'att-' + toot._marl.id + '-' + index + '-desc'"></button><div class="att-description"> <span class="desc-body" x-text="att.name ?? $t('posts.attachmentNoAlt')" :id="'att-' + toot._marl.id + '-' + index + '-desc'" aria-hidden="true"></span> <span class="desc-source"> <strong x-text="$t('post.attachmentInArchive')"></strong> <span x-text="att.url"></span> </span> </div></div></template> <template x-if="attachmentIsSound(att) && $store.files.sources[toot._marl.source][att.url]"><div class="att-wrapper"><audio controls :src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`" :aria-labelledby="'att-' + toot._marl.id + '-' + index + '-desc'"></audio><div class="att-description"> <span class="desc-body" x-text="att.name ?? $t('posts.attachmentNoAlt')" :id="'att-' + toot._marl.id + '-' + index + '-desc'" aria-hidden="true"></span> <span class="desc-source"> <strong x-text="$t('post.attachmentInArchive')"></strong> <span x-text="att.url"></span> </span> </div></div></template> <template x-if="attachmentIsVideo(att) && $store.files.sources[toot._marl.source][att.url]"><div class="att-wrapper"><video controls :width="att.width" :height="att.height" :src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`" :aria-labelledby="'att-' + toot._marl.id + '-' + index + '-desc'"></video><div class="att-description"> <span class="desc-body" x-text="att.name ?? $t('posts.attachmentNoAlt')" :id="'att-' + toot._marl.id + '-' + index + '-desc'" aria-hidden="true"></span> <span class="desc-source"> <strong x-text="$t('post.attachmentInArchive')"></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>&nbsp;
</span> <span class="author"> <span x-text="$t('post.by')"></span>&nbsp;<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"> <span x-text="$t('post.lastUpdated')"></span> <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" x-text="$t('post.linkToPost')"></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 x-text="$t('post.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 x-text="$t('post.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 x-text="$t('post.extLinks')"></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"></use> </svg> </span> <span class="summary-label" :id="'raw-' + toot._marl.id" x-text="$t('post.rawData')"></span> </summary> <div class="details-content"> <textarea x-text="formatJson(toot)" :aria-labelledby="'raw-' + toot._marl.id" readonly></textarea> </div> </details> </div> </div> </template> <div class="toots-no-results" x-show="$store.files.pagedToots.length === 0"> <div x-show="$store.files.filtersActive"> <p x-text="$t('posts.noResults')"></p> <p class="action"> <button @click="$store.files.resetFilters(true)" :disabled="!$store.files.filtersActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#reset-filters"></use> </svg> <span class="btn-label" x-text="$t('filters.resetFilters')"></span> </button> </p> </div> <div x-show="!$store.files.filtersActive"> <p x-text="$t('posts.noPostsError')"></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"></use> </svg> <span class="btn-label" x-text="$t('paging.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"></use> </svg> <span class="btn-label" x-text="$t('paging.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" x-text="$t('paging.next')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-next"></use> </svg> </button> <button @click="$store.files.lastPage('toots')" :disabled="$store.files.currentPage >= $store.files.totalPages"> <span class="btn-label" x-text="$t('paging.last')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-last"></use> </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"></use> </svg> <span class="visually-hidden" x-text="$t('misc.close
2025-01-06 18:14:41 +01:00
(<span x-text="formatNumber($store.files.listHashtags.length)"></span>)
2025-01-09 15:24:56 +01:00
</span> </h3> <div class="tags-group-filter"> <label for="tags-group-hashtags-filter" class="visually-hidden" x-text="$t('tags.hashtagsFilter')"></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> <span x-text="$t('tags.mentions')"></span> <span class="count">
2025-01-06 18:14:41 +01:00
(<span x-text="formatNumber($store.files.listMentions.length)"></span>)
2025-01-09 15:24:56 +01:00
</span> </h3> <div class="tags-group-filter"> <label for="tags-group-mentions-filter" class="visually-hidden" x-text="$t('tags.mentionsFilter')"></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> <span x-text="$t('tags.boosts')"></span> <span class="count">
2025-01-06 18:14:41 +01:00
(<span x-text="formatNumber($store.files.listBoostsAuthors.length)"></span>)
2025-01-09 15:24:56 +01:00
</span> </h3> <div class="tags-group-filter"> <label for="tags-group-boostsAuthors-filter" class="visually-hidden" x-text="$t('tags.boostsFilter')"></label> <input id="tags-group-boostsAuthors-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 await $store.files.listBoostsAuthors"> <li :class="item.url === $store.files.filters.fullText ? 'active' : ''"> <button :id="'filter-boost-author-' + item.url.toLowerCase().replaceAll('/', '_')" @click="$store.files.filterByTag('fullText', item.url, '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" :src="`data:${$store.lightbox.data[$store.lightbox.index].mediaType}; base64,${$store.files.sources[$store.lightbox.source][$store.lightbox.data[$store.lightbox.index].url].content}`" @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"></use></svg><span class="visually-hidden" x-text="$t('lightbox.next')"></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"></use></svg><span class="visually-hidden" x-text="$t('lightbox.prev')"></span></button><button class="viewer-close" @click="$store.lightbox.close()"><svg class="btn-icon" aria-hidden="true"><use href="#close"></use></svg><span class="visually-hidden" x-text="$t('lightbox.close')"></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"></path> </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"></path> </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-240H