diff --git a/src/lib/components/reader/lib/chapterLoader.ts b/src/lib/components/reader/lib/chapterLoader.ts
index 9eee8ea..5634eff 100644
--- a/src/lib/components/reader/lib/chapterLoader.ts
+++ b/src/lib/components/reader/lib/chapterLoader.ts
@@ -1,13 +1,15 @@
import { readerState } from "$lib/state/reader.svelte";
import { fetchPages } from "./pageLoader";
import { cancelQueuedFetches, revokeBlobUrl } from "$lib/core/cache/imageCache";
-import { clearResolvedUrlCache } from "$lib/core/cache/pageCache";
+import { clearResolvedUrlCache, clearPageCache } from "$lib/core/cache/pageCache";
export function scheduleResumeDismiss() {
setTimeout(() => { readerState.resumeFading = true; }, 1500);
setTimeout(() => { readerState.resumeVisible = false; readerState.resumeFading = false; }, 2500);
}
+let prefetchedChapterId: number | null = null;
+
export async function loadChapter(
id: number,
useBlob: boolean,
@@ -23,11 +25,16 @@ export async function loadChapter(
cancelQueuedFetches();
if (useBlob) {
clearResolvedUrlCache();
- // revoke blob URLs for all loaded pages so the GPU can release their textures
for (const url of readerState.pageUrls) revokeBlobUrl(url);
for (const strip of readerState.stripChapters) {
for (const url of strip.urls) revokeBlobUrl(url);
}
+ if (prefetchedChapterId !== null && prefetchedChapterId !== id) {
+ const prefetchedUrls = await fetchPages(prefetchedChapterId, false).catch(() => [] as string[]);
+ for (const url of prefetchedUrls) revokeBlobUrl(url);
+ clearPageCache(prefetchedChapterId);
+ }
+ prefetchedChapterId = null;
}
startAtLastPage.current = false;
@@ -51,10 +58,13 @@ export async function loadChapter(
else if (resumeTo > 1) readerState.pageNumber = Math.min(resumeTo, urls.length || resumeTo);
readerState.pageReady = true;
readerState.loading = false;
- if (adjacent.next) fetchPages(adjacent.next.id, useBlob, ctrl.signal).catch(() => {});
+ if (adjacent.next) {
+ prefetchedChapterId = adjacent.next.id;
+ fetchPages(adjacent.next.id, useBlob, ctrl.signal).catch(() => {});
+ }
} catch (e: unknown) {
if (ctrl.signal.aborted) return;
readerState.error = e instanceof Error ? e.message : String(e);
readerState.loading = false;
}
-}
+}
\ No newline at end of file
diff --git a/src/lib/components/settings/Settings.css b/src/lib/components/settings/Settings.css
index 85adcef..1f6e904 100644
--- a/src/lib/components/settings/Settings.css
+++ b/src/lib/components/settings/Settings.css
@@ -10,9 +10,7 @@
/* ── Backdrop & Modal Shell ───────────────────────────────────────── */
.s-backdrop {
position: fixed; inset: 0;
- background: rgba(0,0,0,0.6);
- backdrop-filter: blur(8px);
- -webkit-backdrop-filter: blur(8px);
+
z-index: var(--z-settings);
display: flex; align-items: center; justify-content: center;
animation: s-fade-in 0.14s ease both;
@@ -29,10 +27,7 @@
overflow: visible;
position: relative;
animation: s-scale-in 0.2s cubic-bezier(0.16,1,0.3,1) both;
- box-shadow:
- 0 0 0 1px rgba(255,255,255,0.04) inset,
- 0 24px 80px rgba(0,0,0,0.7),
- 0 8px 24px rgba(0,0,0,0.4);
+ box-shadow: 0 0 0 1px var(--border-dim), 0 24px 64px rgba(0,0,0,0.6);
}
@@ -46,7 +41,7 @@
display: flex;
flex-direction: column;
gap: 1px;
- overflow-y: auto;
+ overflow-y: hidden;
border-radius: var(--radius-2xl) 0 0 var(--radius-2xl);
}
@@ -140,7 +135,6 @@
.s-content-body {
flex: 1;
overflow-y: auto;
- will-change: transform;
}
diff --git a/src/lib/components/settings/Settings.svelte b/src/lib/components/settings/Settings.svelte
index 8e618a7..edc1851 100644
--- a/src/lib/components/settings/Settings.svelte
+++ b/src/lib/components/settings/Settings.svelte
@@ -19,6 +19,7 @@
import ContentSettings from './sections/ContentSettings.svelte'
import AboutSettings from './sections/AboutSettings.svelte'
import DevtoolsSettings from './sections/DevToolsSettings.svelte'
+ import ModalBlur from '$lib/components/shared/ui/ModalBlur.svelte'
interface Props { onclose?: () => void; onOpenThemeEditor?: (id?: string | null) => void }
let { onclose, onOpenThemeEditor }: Props = $props()
@@ -111,6 +112,7 @@
})
+