aboutsummaryrefslogtreecommitdiff
path: root/src/lib/List/Manga/MangaListTemplate.svelte
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-10-09 00:41:20 -0700
committerFuwn <[email protected]>2024-10-09 00:41:43 -0700
commit998b63a35256ac985a5a2714dd1ca451af4dfd8a (patch)
tree50796121a9d5ab0330fdc5d7e098bda2860d9726 /src/lib/List/Manga/MangaListTemplate.svelte
parentfeat(graphql): add badgeCount field (diff)
downloaddue.moe-998b63a35256ac985a5a2714dd1ca451af4dfd8a.tar.xz
due.moe-998b63a35256ac985a5a2714dd1ca451af4dfd8a.zip
chore(prettier): use spaces instead of tabs
Diffstat (limited to 'src/lib/List/Manga/MangaListTemplate.svelte')
-rw-r--r--src/lib/List/Manga/MangaListTemplate.svelte762
1 files changed, 381 insertions, 381 deletions
diff --git a/src/lib/List/Manga/MangaListTemplate.svelte b/src/lib/List/Manga/MangaListTemplate.svelte
index fe01465f..1303419f 100644
--- a/src/lib/List/Manga/MangaListTemplate.svelte
+++ b/src/lib/List/Manga/MangaListTemplate.svelte
@@ -1,387 +1,387 @@
<script lang="ts">
- import sampleManga from '$lib/Data/Static/SampleMedia/manga.json';
- import { mediaListCollection, Type, type Media } from '$lib/Data/AniList/media';
- import type { AniListAuthorisation } from '$lib/Data/AniList/identity';
- import { onDestroy, onMount } from 'svelte';
- import { chapterCount } from '$lib/Media/Manga/chapters';
- import { pruneAllManga } from '$lib/Media/Manga/cache';
- import manga from '$stores/manga';
- import { database } from '$lib/Database/IDB/chapters';
- import settings from '$stores/settings';
- import lastPruneTimes from '$stores/lastPruneTimes';
- import ListTitle from '../ListTitle.svelte';
- import Error from '$lib/Error/RateLimited.svelte';
- import CleanMangaList from './CleanMangaList.svelte';
- import authorisedJson from '$lib/Data/Static/authorised.json';
- import { incrementMediaProgress } from '$lib/Media/Anime/cache';
- import { getNotificationsContext } from 'svelte-notifications';
- import { options } from '$lib/Notification/options';
- import Skeleton from '$lib/Loading/Skeleton.svelte';
- import locale from '$stores/locale';
- import { browser } from '$app/environment';
- import identity from '$stores/identity';
-
- export let user: AniListAuthorisation = {
- accessToken: '',
- refreshToken: '',
- expiresIn: 0,
- tokenType: ''
- };
- export let displayUnresolved: boolean;
- export let due: boolean;
- export let dummy = $settings.debugDummyLists || false;
-
- const { addNotification } = getNotificationsContext();
- const authorised = authorisedJson.includes($identity.id);
- let mangaLists: Promise<Media[]>;
- let startTime: number;
- let endTime: number;
- let lastUpdatedMedia = -1;
- let previousMangaList: Media[];
- let pendingUpdate: number | null = null;
- let progress = 0;
- let rateLimited = false;
- let forceFlag = false;
- let lastListSize = 5;
-
- const keyCacher = setInterval(() => {
- startTime = performance.now();
- endTime = -1;
- mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
- addNotification
- });
- }, $settings.cacheMinutes * 1000 * 60);
-
- onMount(async () => {
- if (browser) {
- const lastStoredList = localStorage.getItem(`last${due ? '' : 'Completed'}MangaListLength`);
-
- if (lastStoredList) lastListSize = parseInt(lastStoredList);
- }
-
- startTime = performance.now();
-
- if (dummy) {
- mangaLists = Promise.resolve(
- sampleManga
- .filter(
- (manga) =>
- manga.chapters &&
- !manga.tags.some((tag) => tag.name === 'Nudity') &&
- !manga.tags.some((tag) => tag.name === 'Rape') &&
- !manga.tags.some((tag) => tag.name === 'Tragedy') &&
- !manga.tags.some((tag) => tag.name === 'Bondage') &&
- !manga.genres.some((genre) => genre === 'Hentai') &&
- manga.genres.some((genre) => genre === 'Comedy') &&
- manga.status !== 'NOT_YET_RELEASED'
- )
- .sort(() => 0.5 - Math.random())
- .map((manga) => {
- manga.status = 'FINISHED';
- manga.episodes = Math.floor(Math.random() * (manga.chapters || 0)) as unknown as null;
- manga.mediaListEntry.progress = Math.floor(Math.random() * (manga.episodes || 0)) + 1;
-
- return manga;
- })
- .slice(0, 7) as unknown as Media[]
- );
- } else {
- mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
- addNotification
- });
- }
- });
-
- onDestroy(() => clearInterval(keyCacher));
-
- const cleanMedia = async (manga: Media[], displayUnresolved: boolean, force: boolean) => {
- progress = 0;
-
- if (manga && dummy) return manga;
-
- if (manga === undefined) return [];
-
- if (!authorised && (await database.chapters.toArray()).length <= 0 && !force) return [];
-
- if (authorised) {
- let refreshing = false;
-
- if ($lastPruneTimes.chapters === 1) {
- refreshing = true;
-
- lastPruneTimes.setKey('chapters', new Date().getTime());
- } else {
- const currentDate = new Date();
-
- if (
- (currentDate.getTime() - $lastPruneTimes.chapters) / 1000 / 60 >
- Math.max($settings.cacheMangaMinutes, 5)
- ) {
- refreshing = true;
-
- lastPruneTimes.setKey('chapters', currentDate.getTime());
- (async () => {
- await database.chapters.bulkDelete(
- (await database.chapters.toArray()).map((m) => m.id)
- );
- })();
- }
- }
-
- if (refreshing) {
- addNotification(
- options({
- heading: 'Manga',
- description: 'Re-freshing manga data ...'
- })
- );
- }
- }
-
- const releasingMedia = manga.filter(
- (media: Media) =>
- (due ? media.status === 'RELEASING' : media.status === 'FINISHED') &&
- (media.mediaListEntry || { status: 'DROPPED' }).status !==
- ($settings.displayPausedMedia ? '' : 'PAUSED') &&
- (media.mediaListEntry || { status: 'DROPPED' }).status !== 'DROPPED' &&
- (media.mediaListEntry || { progress: 0 }).progress >=
- ($settings.displayNotStarted === true ? 0 : 1)
- );
- let finalMedia = releasingMedia;
- const progressStep = 100 / finalMedia.length / 2;
- const chapterPromises = finalMedia.map((m: Media) =>
- database.chapters.get(m.id).then((c) => {
- if (progress < 100) progress += progressStep;
-
- if (!due) return new Promise((resolve) => resolve(m.chapters)) as Promise<number | null>;
-
- if (c !== undefined) return chapterCount($identity, m, $settings.calculateGuessingDisabled);
- else {
- // A = On 1 second interval,
- // B = a maximum of 5 requests per second are allowed.
- // C = chapterCount makes 3 requests per call.
- // F = A / (B / C) = 0.6 seconds
- return new Promise((resolve) => setTimeout(resolve, 600)).then(() =>
- chapterCount($identity, m, $settings.calculateGuessingDisabled)
- );
- }
- })
- );
- const chapterCounts: (number | null)[] = [];
-
- for (let i = 0; i < chapterPromises.length; i++) {
- const count = await chapterPromises[i];
-
- if (count === -22) {
- rateLimited = true;
-
- break;
- }
-
- chapterCounts.push(count);
-
- if (progress < 100) progress += progressStep;
- }
-
- finalMedia.forEach((m: Media, i) => (m.episodes = chapterCounts[i] || -1337));
-
- if (!displayUnresolved) finalMedia = finalMedia.filter((m: Media) => m.episodes !== -1337);
-
- finalMedia.sort(
- (a: Media, b: Media) =>
- (a.episodes || 9999) -
- (a.mediaListEntry || { progress: 0 }).progress -
- ((b.episodes || 9999) - (b.mediaListEntry || { progress: 0 }).progress)
- );
-
- finalMedia = finalMedia.filter(
- (item, index, array) =>
- array.findIndex((i) => i.id === item.id) === index &&
- (item.episodes === -1337 && displayUnresolved
- ? true
- : (item.mediaListEntry?.progress || 0) <
- ($settings.calculateChaptersRoundedDown === true
- ? Math.floor(item.episodes)
- : item.episodes))
- );
-
- if (!endTime || endTime === -1) endTime = performance.now() - startTime;
-
- return finalMedia;
- };
-
- const updateMedia = async (id: number, progress: number | undefined, media: Media[]) => {
- pendingUpdate = id;
- lastUpdatedMedia = id;
-
- await database.chapters.delete(id);
-
- incrementMediaProgress(id, progress, user, () => {
- previousMangaList = media;
-
- const foundEntry = media.find((m) => m.id === id);
-
- if (foundEntry && foundEntry.mediaListEntry)
- foundEntry.mediaListEntry.progress = (progress || 0) + 1;
-
- mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
- forcePrune: true
- });
- pendingUpdate = null;
- });
- };
-
- const cleanCache = () => {
- startTime = performance.now();
- endTime = -1;
-
- pruneAllManga().then(() => {
- mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
- forcePrune: true
- });
- });
- };
+ import sampleManga from '$lib/Data/Static/SampleMedia/manga.json';
+ import { mediaListCollection, Type, type Media } from '$lib/Data/AniList/media';
+ import type { AniListAuthorisation } from '$lib/Data/AniList/identity';
+ import { onDestroy, onMount } from 'svelte';
+ import { chapterCount } from '$lib/Media/Manga/chapters';
+ import { pruneAllManga } from '$lib/Media/Manga/cache';
+ import manga from '$stores/manga';
+ import { database } from '$lib/Database/IDB/chapters';
+ import settings from '$stores/settings';
+ import lastPruneTimes from '$stores/lastPruneTimes';
+ import ListTitle from '../ListTitle.svelte';
+ import Error from '$lib/Error/RateLimited.svelte';
+ import CleanMangaList from './CleanMangaList.svelte';
+ import authorisedJson from '$lib/Data/Static/authorised.json';
+ import { incrementMediaProgress } from '$lib/Media/Anime/cache';
+ import { getNotificationsContext } from 'svelte-notifications';
+ import { options } from '$lib/Notification/options';
+ import Skeleton from '$lib/Loading/Skeleton.svelte';
+ import locale from '$stores/locale';
+ import { browser } from '$app/environment';
+ import identity from '$stores/identity';
+
+ export let user: AniListAuthorisation = {
+ accessToken: '',
+ refreshToken: '',
+ expiresIn: 0,
+ tokenType: ''
+ };
+ export let displayUnresolved: boolean;
+ export let due: boolean;
+ export let dummy = $settings.debugDummyLists || false;
+
+ const { addNotification } = getNotificationsContext();
+ const authorised = authorisedJson.includes($identity.id);
+ let mangaLists: Promise<Media[]>;
+ let startTime: number;
+ let endTime: number;
+ let lastUpdatedMedia = -1;
+ let previousMangaList: Media[];
+ let pendingUpdate: number | null = null;
+ let progress = 0;
+ let rateLimited = false;
+ let forceFlag = false;
+ let lastListSize = 5;
+
+ const keyCacher = setInterval(() => {
+ startTime = performance.now();
+ endTime = -1;
+ mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
+ addNotification
+ });
+ }, $settings.cacheMinutes * 1000 * 60);
+
+ onMount(async () => {
+ if (browser) {
+ const lastStoredList = localStorage.getItem(`last${due ? '' : 'Completed'}MangaListLength`);
+
+ if (lastStoredList) lastListSize = parseInt(lastStoredList);
+ }
+
+ startTime = performance.now();
+
+ if (dummy) {
+ mangaLists = Promise.resolve(
+ sampleManga
+ .filter(
+ (manga) =>
+ manga.chapters &&
+ !manga.tags.some((tag) => tag.name === 'Nudity') &&
+ !manga.tags.some((tag) => tag.name === 'Rape') &&
+ !manga.tags.some((tag) => tag.name === 'Tragedy') &&
+ !manga.tags.some((tag) => tag.name === 'Bondage') &&
+ !manga.genres.some((genre) => genre === 'Hentai') &&
+ manga.genres.some((genre) => genre === 'Comedy') &&
+ manga.status !== 'NOT_YET_RELEASED'
+ )
+ .sort(() => 0.5 - Math.random())
+ .map((manga) => {
+ manga.status = 'FINISHED';
+ manga.episodes = Math.floor(Math.random() * (manga.chapters || 0)) as unknown as null;
+ manga.mediaListEntry.progress = Math.floor(Math.random() * (manga.episodes || 0)) + 1;
+
+ return manga;
+ })
+ .slice(0, 7) as unknown as Media[]
+ );
+ } else {
+ mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
+ addNotification
+ });
+ }
+ });
+
+ onDestroy(() => clearInterval(keyCacher));
+
+ const cleanMedia = async (manga: Media[], displayUnresolved: boolean, force: boolean) => {
+ progress = 0;
+
+ if (manga && dummy) return manga;
+
+ if (manga === undefined) return [];
+
+ if (!authorised && (await database.chapters.toArray()).length <= 0 && !force) return [];
+
+ if (authorised) {
+ let refreshing = false;
+
+ if ($lastPruneTimes.chapters === 1) {
+ refreshing = true;
+
+ lastPruneTimes.setKey('chapters', new Date().getTime());
+ } else {
+ const currentDate = new Date();
+
+ if (
+ (currentDate.getTime() - $lastPruneTimes.chapters) / 1000 / 60 >
+ Math.max($settings.cacheMangaMinutes, 5)
+ ) {
+ refreshing = true;
+
+ lastPruneTimes.setKey('chapters', currentDate.getTime());
+ (async () => {
+ await database.chapters.bulkDelete(
+ (await database.chapters.toArray()).map((m) => m.id)
+ );
+ })();
+ }
+ }
+
+ if (refreshing) {
+ addNotification(
+ options({
+ heading: 'Manga',
+ description: 'Re-freshing manga data ...'
+ })
+ );
+ }
+ }
+
+ const releasingMedia = manga.filter(
+ (media: Media) =>
+ (due ? media.status === 'RELEASING' : media.status === 'FINISHED') &&
+ (media.mediaListEntry || { status: 'DROPPED' }).status !==
+ ($settings.displayPausedMedia ? '' : 'PAUSED') &&
+ (media.mediaListEntry || { status: 'DROPPED' }).status !== 'DROPPED' &&
+ (media.mediaListEntry || { progress: 0 }).progress >=
+ ($settings.displayNotStarted === true ? 0 : 1)
+ );
+ let finalMedia = releasingMedia;
+ const progressStep = 100 / finalMedia.length / 2;
+ const chapterPromises = finalMedia.map((m: Media) =>
+ database.chapters.get(m.id).then((c) => {
+ if (progress < 100) progress += progressStep;
+
+ if (!due) return new Promise((resolve) => resolve(m.chapters)) as Promise<number | null>;
+
+ if (c !== undefined) return chapterCount($identity, m, $settings.calculateGuessingDisabled);
+ else {
+ // A = On 1 second interval,
+ // B = a maximum of 5 requests per second are allowed.
+ // C = chapterCount makes 3 requests per call.
+ // F = A / (B / C) = 0.6 seconds
+ return new Promise((resolve) => setTimeout(resolve, 600)).then(() =>
+ chapterCount($identity, m, $settings.calculateGuessingDisabled)
+ );
+ }
+ })
+ );
+ const chapterCounts: (number | null)[] = [];
+
+ for (let i = 0; i < chapterPromises.length; i++) {
+ const count = await chapterPromises[i];
+
+ if (count === -22) {
+ rateLimited = true;
+
+ break;
+ }
+
+ chapterCounts.push(count);
+
+ if (progress < 100) progress += progressStep;
+ }
+
+ finalMedia.forEach((m: Media, i) => (m.episodes = chapterCounts[i] || -1337));
+
+ if (!displayUnresolved) finalMedia = finalMedia.filter((m: Media) => m.episodes !== -1337);
+
+ finalMedia.sort(
+ (a: Media, b: Media) =>
+ (a.episodes || 9999) -
+ (a.mediaListEntry || { progress: 0 }).progress -
+ ((b.episodes || 9999) - (b.mediaListEntry || { progress: 0 }).progress)
+ );
+
+ finalMedia = finalMedia.filter(
+ (item, index, array) =>
+ array.findIndex((i) => i.id === item.id) === index &&
+ (item.episodes === -1337 && displayUnresolved
+ ? true
+ : (item.mediaListEntry?.progress || 0) <
+ ($settings.calculateChaptersRoundedDown === true
+ ? Math.floor(item.episodes)
+ : item.episodes))
+ );
+
+ if (!endTime || endTime === -1) endTime = performance.now() - startTime;
+
+ return finalMedia;
+ };
+
+ const updateMedia = async (id: number, progress: number | undefined, media: Media[]) => {
+ pendingUpdate = id;
+ lastUpdatedMedia = id;
+
+ await database.chapters.delete(id);
+
+ incrementMediaProgress(id, progress, user, () => {
+ previousMangaList = media;
+
+ const foundEntry = media.find((m) => m.id === id);
+
+ if (foundEntry && foundEntry.mediaListEntry)
+ foundEntry.mediaListEntry.progress = (progress || 0) + 1;
+
+ mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
+ forcePrune: true
+ });
+ pendingUpdate = null;
+ });
+ };
+
+ const cleanCache = () => {
+ startTime = performance.now();
+ endTime = -1;
+
+ pruneAllManga().then(() => {
+ mangaLists = mediaListCollection(user, $identity, Type.Manga, $manga, $lastPruneTimes.manga, {
+ forcePrune: true
+ });
+ });
+ };
</script>
{#await mangaLists}
- {#if previousMangaList}
- <CleanMangaList
- media={previousMangaList}
- {cleanCache}
- {lastUpdatedMedia}
- {updateMedia}
- {endTime}
- {pendingUpdate}
- {due}
- {rateLimited}
- {authorised}
- {dummy}
- />
- {:else}
- {#if !authorised}
- <ListTitle
- count={0}
- time={endTime / 1000}
- title={$locale().lists.due.mangaAndLightNovels}
- hideTime={dummy}
- hideCount={dummy}
- >
- {#if !dummy}
- <button
- data-umami-event="Force Refresh Manga"
- title="Force a full refresh"
- on:click={() => {
- cleanCache();
-
- forceFlag = true;
- }}>Refresh</button
- >
- {/if}
- </ListTitle>
- {:else}
- <ListTitle
- {progress}
- title={$locale().lists.due.mangaAndLightNovels}
- hideTime={dummy}
- hideCount={dummy}
- />
- {/if}
-
- <Skeleton card={false} count={lastListSize} height="0.9rem" list />
- {/if}
+ {#if previousMangaList}
+ <CleanMangaList
+ media={previousMangaList}
+ {cleanCache}
+ {lastUpdatedMedia}
+ {updateMedia}
+ {endTime}
+ {pendingUpdate}
+ {due}
+ {rateLimited}
+ {authorised}
+ {dummy}
+ />
+ {:else}
+ {#if !authorised}
+ <ListTitle
+ count={0}
+ time={endTime / 1000}
+ title={$locale().lists.due.mangaAndLightNovels}
+ hideTime={dummy}
+ hideCount={dummy}
+ >
+ {#if !dummy}
+ <button
+ data-umami-event="Force Refresh Manga"
+ title="Force a full refresh"
+ on:click={() => {
+ cleanCache();
+
+ forceFlag = true;
+ }}>Refresh</button
+ >
+ {/if}
+ </ListTitle>
+ {:else}
+ <ListTitle
+ {progress}
+ title={$locale().lists.due.mangaAndLightNovels}
+ hideTime={dummy}
+ hideCount={dummy}
+ />
+ {/if}
+
+ <Skeleton card={false} count={lastListSize} height="0.9rem" list />
+ {/if}
{:then media}
- {#await cleanMedia(media, displayUnresolved, forceFlag)}
- {#if previousMangaList}
- <CleanMangaList
- media={previousMangaList}
- {cleanCache}
- {lastUpdatedMedia}
- {updateMedia}
- {endTime}
- {pendingUpdate}
- {due}
- {rateLimited}
- {authorised}
- {dummy}
- />
- {:else}
- {#if !authorised}
- <ListTitle
- count={0}
- time={endTime / 1000}
- title={$locale().lists.due.mangaAndLightNovels}
- hideTime={dummy}
- hideCount={dummy}
- >
- {#if !dummy}
- <button
- data-umami-event="Force Refresh Manga"
- title="Force a full refresh"
- on:click={() => {
- cleanCache();
-
- forceFlag = true;
- }}>Refresh</button
- >
- {/if}
- </ListTitle>
- {:else}
- <ListTitle
- {progress}
- title={$locale().lists.due.mangaAndLightNovels}
- hideTime={dummy}
- hideCount={dummy}
- />
- {/if}
-
- <Skeleton card={false} count={lastListSize} height="0.9rem" list />
- {/if}
- {:then cleanedMedia}
- {#if !authorised}
- <ListTitle
- count={cleanedMedia.length}
- time={endTime / 1000}
- title={$locale().lists.due.mangaAndLightNovels}
- hideTime={dummy}
- hideCount={dummy}
- >
- {#if !dummy}
- <button
- data-umami-event="Force Refresh Manga"
- title="Force a full refresh"
- on:click={() => {
- cleanCache();
-
- forceFlag = true;
- }}>Refresh</button
- >
- {/if}
- </ListTitle>
- {/if}
-
- <CleanMangaList
- media={cleanedMedia}
- {cleanCache}
- {lastUpdatedMedia}
- {updateMedia}
- {endTime}
- {pendingUpdate}
- {due}
- {rateLimited}
- {authorised}
- {dummy}
- />
- {:catch}
- {#if authorised}
- <ListTitle
- count={-1337}
- time={0}
- title={$locale().lists.due.mangaAndLightNovels}
- hideTime={dummy}
- hideCount={dummy}
- />
- {/if}
-
- <Error list={false} />
- {/await}
+ {#await cleanMedia(media, displayUnresolved, forceFlag)}
+ {#if previousMangaList}
+ <CleanMangaList
+ media={previousMangaList}
+ {cleanCache}
+ {lastUpdatedMedia}
+ {updateMedia}
+ {endTime}
+ {pendingUpdate}
+ {due}
+ {rateLimited}
+ {authorised}
+ {dummy}
+ />
+ {:else}
+ {#if !authorised}
+ <ListTitle
+ count={0}
+ time={endTime / 1000}
+ title={$locale().lists.due.mangaAndLightNovels}
+ hideTime={dummy}
+ hideCount={dummy}
+ >
+ {#if !dummy}
+ <button
+ data-umami-event="Force Refresh Manga"
+ title="Force a full refresh"
+ on:click={() => {
+ cleanCache();
+
+ forceFlag = true;
+ }}>Refresh</button
+ >
+ {/if}
+ </ListTitle>
+ {:else}
+ <ListTitle
+ {progress}
+ title={$locale().lists.due.mangaAndLightNovels}
+ hideTime={dummy}
+ hideCount={dummy}
+ />
+ {/if}
+
+ <Skeleton card={false} count={lastListSize} height="0.9rem" list />
+ {/if}
+ {:then cleanedMedia}
+ {#if !authorised}
+ <ListTitle
+ count={cleanedMedia.length}
+ time={endTime / 1000}
+ title={$locale().lists.due.mangaAndLightNovels}
+ hideTime={dummy}
+ hideCount={dummy}
+ >
+ {#if !dummy}
+ <button
+ data-umami-event="Force Refresh Manga"
+ title="Force a full refresh"
+ on:click={() => {
+ cleanCache();
+
+ forceFlag = true;
+ }}>Refresh</button
+ >
+ {/if}
+ </ListTitle>
+ {/if}
+
+ <CleanMangaList
+ media={cleanedMedia}
+ {cleanCache}
+ {lastUpdatedMedia}
+ {updateMedia}
+ {endTime}
+ {pendingUpdate}
+ {due}
+ {rateLimited}
+ {authorised}
+ {dummy}
+ />
+ {:catch}
+ {#if authorised}
+ <ListTitle
+ count={-1337}
+ time={0}
+ title={$locale().lists.due.mangaAndLightNovels}
+ hideTime={dummy}
+ hideCount={dummy}
+ />
+ {/if}
+
+ <Error list={false} />
+ {/await}
{/await}