aboutsummaryrefslogtreecommitdiff
path: root/src/routes/+page.svelte
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-03-22 04:11:18 +0000
committerFuwn <[email protected]>2026-03-22 04:20:41 +0000
commitbf633af5eab9e402b5f5c382e6eb1bb95eaf5886 (patch)
treec4b2bfe3f03b11000c189ecf16f51e57d02b825f /src/routes/+page.svelte
parentrefactor: isolate last activity fetch path (diff)
downloaddue.moe-bf633af5eab9e402b5f5c382e6eb1bb95eaf5886.tar.xz
due.moe-bf633af5eab9e402b5f5c382e6eb1bb95eaf5886.zip
perf: lazy-load authenticated list surfaces
Diffstat (limited to 'src/routes/+page.svelte')
-rw-r--r--src/routes/+page.svelte99
1 files changed, 85 insertions, 14 deletions
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 21fd7b01..ecd799d8 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,30 +1,71 @@
<script lang="ts">
+import type { Component } from "svelte";
import Spacer from "$lib/Layout/Spacer.svelte";
import { onDestroy, onMount } from "svelte";
-import MangaListTemplate from "$lib/List/Manga/MangaListTemplate.svelte";
-import UpcomingAnimeList from "$lib/List/Anime/UpcomingAnimeList.svelte";
import userIdentity from "$stores/identity.js";
import settings from "$stores/settings";
import ListTitle from "$lib/List/ListTitle.svelte";
import HeadTitle from "$lib/Home/HeadTitle.svelte";
-import LastActivity from "$lib/Home/LastActivity.svelte";
import { createHeightObserver } from "$lib/Utility/html.js";
import Skeleton from "$lib/Loading/Skeleton.svelte";
import locale from "$stores/locale.js";
import Landing from "$lib/Landing.svelte";
import LandingHero from "$lib/LandingHero.svelte";
-import IndexColumn from "$lib/List/Anime/DueIndexColumn.svelte";
import stateBin from "$stores/stateBin.js";
import type { PageData } from "./$types";
-export let data: PageData;
+let { data }: { data: PageData } = $props();
+
+type UserProp = PageData["user"];
+type LastActivitySvelteComponent = Component<{
+ user: UserProp;
+}>;
+type UpcomingAnimeListSvelteComponent = Component<{
+ user: UserProp;
+}>;
+type IndexColumnSvelteComponent = Component<{
+ user: UserProp;
+ userIdentity: { id: number };
+}>;
+type MangaListTemplateSvelteComponent = Component<{
+ user: UserProp;
+ displayUnresolved: boolean;
+ due: boolean;
+}>;
let removeHeightObserver: (() => void) | undefined;
+let LastActivityComponent: LastActivitySvelteComponent | null = $state(null);
+let UpcomingAnimeListComponent: UpcomingAnimeListSvelteComponent | null =
+ $state(null);
+let IndexColumnComponent: IndexColumnSvelteComponent | null = $state(null);
+let MangaListTemplateComponent: MangaListTemplateSvelteComponent | null =
+ $state(null);
+let authenticatedHomeSurfaceImport: Promise<void> | null = null;
+
+const loadAuthenticatedHomeSurface = () => {
+ if (data.user === undefined) return null;
+ if (authenticatedHomeSurfaceImport) return authenticatedHomeSurfaceImport;
+
+ authenticatedHomeSurfaceImport = Promise.all([
+ import("$lib/Home/LastActivity.svelte"),
+ import("$lib/List/Anime/UpcomingAnimeList.svelte"),
+ import("$lib/List/Anime/DueIndexColumn.svelte"),
+ import("$lib/List/Manga/MangaListTemplate.svelte"),
+ ]).then(([lastActivity, upcomingAnimeList, indexColumn, mangaListTemplate]) => {
+ LastActivityComponent = lastActivity.default;
+ UpcomingAnimeListComponent = upcomingAnimeList.default;
+ IndexColumnComponent = indexColumn.default;
+ MangaListTemplateComponent = mangaListTemplate.default;
+ });
+
+ return authenticatedHomeSurfaceImport;
+};
onMount(() => {
removeHeightObserver = createHeightObserver();
$stateBin.upcomingAnimeListOpen ??= true;
$stateBin.dueMangaListOpen ??= true;
+ void loadAuthenticatedHomeSurface();
});
onDestroy(() => removeHeightObserver?.());
@@ -32,7 +73,9 @@ onDestroy(() => removeHeightObserver?.());
<HeadTitle />
-<LastActivity user={data.user} />
+{#if LastActivityComponent}
+ <LastActivityComponent user={data.user} />
+{/if}
{#if data.user === undefined}
<LandingHero />
@@ -57,7 +100,13 @@ onDestroy(() => removeHeightObserver?.());
{#if !$settings.disableUpcomingAnime}
<details bind:open={$stateBin.upcomingAnimeListOpen} class="list list-upcoming">
{#if $userIdentity.id !== -2}
- <UpcomingAnimeList user={data.user} />
+ {#if UpcomingAnimeListComponent}
+ <UpcomingAnimeListComponent user={data.user} />
+ {:else}
+ <ListTitle title={$locale().lists.upcoming.episodes} />
+
+ <Skeleton card={false} count={5} height="0.9rem" list />
+ {/if}
{:else}
<ListTitle title={$locale().lists.upcoming.episodes} />
@@ -67,23 +116,45 @@ onDestroy(() => removeHeightObserver?.());
{/if}
{#if !$settings.disableAnime && !$settings.disableManga}
- <IndexColumn user={data.user} userIdentity={$userIdentity} />
+ {#if IndexColumnComponent}
+ <IndexColumnComponent user={data.user} userIdentity={$userIdentity} />
+ {:else}
+ <details bind:open={$stateBin.dueAnimeListOpen} class="list list-due">
+ <ListTitle title={$locale().lists.due.episodes} />
+
+ <Skeleton card={false} count={5} height="0.9rem" list />
+ </details>
+ {/if}
{/if}
</div>
<div class="right-column">
{#if !$settings.disableAnime && $settings.disableManga}
- <IndexColumn user={data.user} userIdentity={$userIdentity} />
+ {#if IndexColumnComponent}
+ <IndexColumnComponent user={data.user} userIdentity={$userIdentity} />
+ {:else}
+ <details bind:open={$stateBin.dueAnimeListOpen} class="list list-due">
+ <ListTitle title={$locale().lists.due.episodes} />
+
+ <Skeleton card={false} count={5} height="0.9rem" list />
+ </details>
+ {/if}
{/if}
{#if !$settings.disableManga}
<details bind:open={$stateBin.dueMangaListOpen} class="list list-manga">
{#if $userIdentity.id !== -2}
- <MangaListTemplate
- user={data.user}
- displayUnresolved={$settings.displayUnresolved}
- due={true}
- />
+ {#if MangaListTemplateComponent}
+ <MangaListTemplateComponent
+ user={data.user}
+ displayUnresolved={$settings.displayUnresolved}
+ due={true}
+ />
+ {:else}
+ <ListTitle title={$locale().lists.due.mangaAndLightNovels} />
+
+ <Skeleton card={false} count={5} height="0.9rem" list />
+ {/if}
{:else}
<ListTitle title={$locale().lists.due.mangaAndLightNovels} />