From bd79169f7131b7e1bfc06bf76bab4539957a2069 Mon Sep 17 00:00:00 2001 From: Zerebos Date: Thu, 21 May 2026 02:23:09 -0400 Subject: [PATCH] Basic caching --- src/core/cache/queryCache.ts | 1 + .../recent/components/UpdatesPanel.svelte | 24 +++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/core/cache/queryCache.ts b/src/core/cache/queryCache.ts index 4eae1cf..1baae89 100644 --- a/src/core/cache/queryCache.ts +++ b/src/core/cache/queryCache.ts @@ -147,6 +147,7 @@ export const CACHE_GROUPS = { export const CACHE_KEYS = { LIBRARY: "library", + RECENT_UPDATES: "recent_updates", ALL_MANGA: "all_manga_unfiltered", CATEGORIES: "categories", SEARCH: "search_all_manga", diff --git a/src/features/recent/components/UpdatesPanel.svelte b/src/features/recent/components/UpdatesPanel.svelte index c4c9932..f63a865 100644 --- a/src/features/recent/components/UpdatesPanel.svelte +++ b/src/features/recent/components/UpdatesPanel.svelte @@ -3,6 +3,7 @@ import { BookOpen, CircleNotch } from "phosphor-svelte"; import { gql } from "@api/client"; import { GET_RECENTLY_UPDATED, GET_CHAPTERS } from "@api/queries"; + import { cache, CACHE_GROUPS, CACHE_KEYS } from "@core/cache"; import { store, openReader, setActiveManga, addToast } from "@store/state.svelte"; import { dayLabel } from "@core/util"; import { buildReaderChapterList } from "@features/series/lib/chapterList"; @@ -30,9 +31,10 @@ let openingId = $state(null); let ctrl: AbortController | null = null; + const RECENT_UPDATES_TTL_MS = 60 * 1_000; onMount(() => { - onRegisterRefresh?.(loadUpdates); + onRegisterRefresh?.(() => loadUpdates(true)); void loadUpdates(); }); @@ -46,13 +48,13 @@ } const groups = $derived.by(() => { - const map = new Map(); + const grouped: Record = {}; for (const item of updates) { const label = dayLabel(fetchedAtMs(item)); - if (!map.has(label)) map.set(label, []); - map.get(label)!.push(item); + if (!grouped[label]) grouped[label] = []; + grouped[label].push(item); } - return Array.from(map.entries()).map(([label, items]) => ({ label, items })) as UpdateGroup[]; + return Object.entries(grouped).map(([label, items]) => ({ label, items })) as UpdateGroup[]; }); const lastCheckedTs = $derived( @@ -86,7 +88,7 @@ return "Chapter"; } - async function loadUpdates() { + async function loadUpdates(force = false) { ctrl?.abort(); const nextCtrl = new AbortController(); ctrl = nextCtrl; @@ -94,7 +96,15 @@ error = null; try { - const res = await gql<{ chapters: { nodes: RecentUpdate[] } }>(GET_RECENTLY_UPDATED, {}, nextCtrl.signal); + const key = CACHE_KEYS.RECENT_UPDATES; + if (force) cache.clear(key); + + const res = await cache.get<{ chapters: { nodes: RecentUpdate[] } }>( + key, + () => gql<{ chapters: { nodes: RecentUpdate[] } }>(GET_RECENTLY_UPDATED, {}, nextCtrl.signal), + RECENT_UPDATES_TTL_MS, + CACHE_GROUPS.LIBRARY, + ); if (nextCtrl.signal.aborted) return; updates = res.chapters.nodes