[V1] Addressed Laggy Single-Page (Applied Cache-Loading)

This commit is contained in:
Youwes09
2026-02-23 10:57:52 -06:00
parent edf2af8618
commit cd2d79f80c
2 changed files with 23 additions and 14 deletions
+22 -13
View File
@@ -329,8 +329,11 @@ export default function Reader() {
// Discard result if the user has already navigated to a different chapter // Discard result if the user has already navigated to a different chapter
if (loadingChapterRef.current !== targetId) return; if (loadingChapterRef.current !== targetId) return;
// Decode the first page before committing so no previous chapter flashes // Decode the first page before committing so no previous chapter flashes.
await decodeImage(urls[0]); // In longstrip mode skip the blocking decode — images stream in naturally.
if (style !== "longstrip") {
await decodeImage(urls[0]);
}
if (loadingChapterRef.current !== targetId) return; if (loadingChapterRef.current !== targetId) return;
@@ -348,10 +351,14 @@ export default function Reader() {
setStripChapters([]); setStripChapters([]);
setVisibleChapterId(null); setVisibleChapterId(null);
} }
// Only clear loading after state is fully committed — no flash frames
setLoading(false);
}) })
.catch((e) => setError(e instanceof Error ? e.message : String(e))) .catch((e) => {
.finally(() => { if (loadingChapterRef.current === targetId) {
if (loadingChapterRef.current === targetId) setLoading(false); setError(e instanceof Error ? e.message : String(e));
setLoading(false);
}
}); });
}, [activeChapter?.id]); }, [activeChapter?.id]);
@@ -507,6 +514,7 @@ export default function Reader() {
}, [pageGroups, pageNumber, adjacent, activeChapterList]); }, [pageGroups, pageNumber, adjacent, activeChapterList]);
const goForward = useCallback(() => { const goForward = useCallback(() => {
if (loading || !pageUrls.length) return;
if (style === "double" && pageGroups.length) { advanceGroup(true); return; } if (style === "double" && pageGroups.length) { advanceGroup(true); return; }
if (pageNumber < lastPage) { if (pageNumber < lastPage) {
const nextUrl = pageUrls[pageNumber]; // pageNumber is 1-based, so index is pageNumber const nextUrl = pageUrls[pageNumber]; // pageNumber is 1-based, so index is pageNumber
@@ -521,9 +529,10 @@ export default function Reader() {
} else { } else {
closeReader(); closeReader();
} }
}, [pageNumber, lastPage, pageUrls, adjacent, activeChapterList, style, pageGroups, advanceGroup]); }, [loading, pageNumber, lastPage, pageUrls, adjacent, activeChapterList, style, pageGroups, advanceGroup]);
const goBack = useCallback(() => { const goBack = useCallback(() => {
if (loading || !pageUrls.length) return;
if (style === "double" && pageGroups.length) { advanceGroup(false); return; } if (style === "double" && pageGroups.length) { advanceGroup(false); return; }
if (pageNumber > 1) { if (pageNumber > 1) {
const prevUrl = pageUrls[pageNumber - 2]; // 0-based index of previous page const prevUrl = pageUrls[pageNumber - 2]; // 0-based index of previous page
@@ -535,7 +544,7 @@ export default function Reader() {
} else if (adjacent.prev) { } else if (adjacent.prev) {
openReader(adjacent.prev, activeChapterList); openReader(adjacent.prev, activeChapterList);
} }
}, [pageNumber, pageUrls, adjacent, activeChapterList, style, pageGroups, advanceGroup]); }, [loading, pageNumber, pageUrls, adjacent, activeChapterList, style, pageGroups, advanceGroup]);
const goNext = rtl ? goBack : goForward; const goNext = rtl ? goBack : goForward;
const goPrev = rtl ? goForward : goBack; const goPrev = rtl ? goForward : goBack;
@@ -600,8 +609,8 @@ export default function Reader() {
else if (matchesKeybind(e, kb.pageLeft)) { e.preventDefault(); goBack(); } else if (matchesKeybind(e, kb.pageLeft)) { e.preventDefault(); goBack(); }
else if (matchesKeybind(e, kb.firstPage)) { e.preventDefault(); setPageNumber(1); } else if (matchesKeybind(e, kb.firstPage)) { e.preventDefault(); setPageNumber(1); }
else if (matchesKeybind(e, kb.lastPage)) { e.preventDefault(); setPageNumber(lastPage); } else if (matchesKeybind(e, kb.lastPage)) { e.preventDefault(); setPageNumber(lastPage); }
else if (matchesKeybind(e, kb.chapterRight)) { e.preventDefault(); if (adjacent.next) openReader(adjacent.next, activeChapterList); } else if (matchesKeybind(e, kb.chapterRight)) { e.preventDefault(); if (!loading && adjacent.next) openReader(adjacent.next, activeChapterList); }
else if (matchesKeybind(e, kb.chapterLeft)) { e.preventDefault(); if (adjacent.prev) openReader(adjacent.prev, activeChapterList); } else if (matchesKeybind(e, kb.chapterLeft)) { e.preventDefault(); if (!loading && adjacent.prev) openReader(adjacent.prev, activeChapterList); }
else if (matchesKeybind(e, kb.togglePageStyle)) { e.preventDefault(); cycleStyle(); } else if (matchesKeybind(e, kb.togglePageStyle)) { e.preventDefault(); cycleStyle(); }
else if (matchesKeybind(e, kb.toggleReadingDirection)) { e.preventDefault(); updateSettings({ readingDirection: rtl ? "ltr" : "rtl" }); } else if (matchesKeybind(e, kb.toggleReadingDirection)) { e.preventDefault(); updateSettings({ readingDirection: rtl ? "ltr" : "rtl" }); }
else if (matchesKeybind(e, kb.toggleFullscreen)) { e.preventDefault(); toggleFullscreen().catch(console.error); } else if (matchesKeybind(e, kb.toggleFullscreen)) { e.preventDefault(); toggleFullscreen().catch(console.error); }
@@ -609,7 +618,7 @@ export default function Reader() {
}; };
window.addEventListener("keydown", onKey); window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey);
}, [goForward, goBack, kb, style, rtl, lastPage, adjacent, activeChapterList, zoomOpen, dlOpen, maxW]); }, [goForward, goBack, kb, style, rtl, lastPage, adjacent, activeChapterList, zoomOpen, dlOpen, maxW, loading]);
// ── Longstrip scroll tracker ───────────────────────────────────────────────── // ── Longstrip scroll tracker ─────────────────────────────────────────────────
// Tracks current page number. In autoNext mode, appends the next chapter's // Tracks current page number. In autoNext mode, appends the next chapter's
@@ -935,11 +944,11 @@ export default function Reader() {
) : ( ) : (
pageReady && ( pageReady && (
<img <img
key={pageNumber}
src={pageUrls[pageNumber - 1]} src={pageUrls[pageNumber - 1]}
alt={`Page ${pageNumber}`} alt={`Page ${pageNumber}`}
className={imgCls} className={imgCls}
decoding="async" decoding="async"
style={{ transition: "opacity 0.1s ease" }}
/> />
) )
)} )}
@@ -947,10 +956,10 @@ export default function Reader() {
{/* ── Bottom nav ── */} {/* ── Bottom nav ── */}
<div className={[s.bottombar, uiVisible ? "" : s.uiHidden].join(" ")}> <div className={[s.bottombar, uiVisible ? "" : s.uiHidden].join(" ")}>
<button className={s.navBtn} onClick={goPrev} disabled={pageNumber === 1 && !adjacent.prev}> <button className={s.navBtn} onClick={goPrev} disabled={loading || (pageNumber === 1 && !adjacent.prev)}>
<ArrowLeft size={13} weight="light" /> <ArrowLeft size={13} weight="light" />
</button> </button>
<button className={s.navBtn} onClick={goNext} disabled={pageNumber === lastPage && !adjacent.next}> <button className={s.navBtn} onClick={goNext} disabled={loading || (pageNumber === lastPage && !adjacent.next)}>
<ArrowRight size={13} weight="light" /> <ArrowRight size={13} weight="light" />
</button> </button>
</div> </div>
+1 -1
View File
@@ -64,7 +64,7 @@ export interface Settings {
} }
export const DEFAULT_SETTINGS: Settings = { export const DEFAULT_SETTINGS: Settings = {
pageStyle: "single", pageStyle: "longstrip",
readingDirection: "ltr", readingDirection: "ltr",
fitMode: "width", fitMode: "width",
maxPageWidth: 900, maxPageWidth: 900,