diff --git a/src/components/pages/Reader.tsx b/src/components/pages/Reader.tsx index 9025029..4193067 100644 --- a/src/components/pages/Reader.tsx +++ b/src/components/pages/Reader.tsx @@ -329,8 +329,11 @@ export default function Reader() { // Discard result if the user has already navigated to a different chapter if (loadingChapterRef.current !== targetId) return; - // Decode the first page before committing so no previous chapter flashes - await decodeImage(urls[0]); + // Decode the first page before committing so no previous chapter flashes. + // In longstrip mode skip the blocking decode — images stream in naturally. + if (style !== "longstrip") { + await decodeImage(urls[0]); + } if (loadingChapterRef.current !== targetId) return; @@ -348,10 +351,14 @@ export default function Reader() { setStripChapters([]); 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))) - .finally(() => { - if (loadingChapterRef.current === targetId) setLoading(false); + .catch((e) => { + if (loadingChapterRef.current === targetId) { + setError(e instanceof Error ? e.message : String(e)); + setLoading(false); + } }); }, [activeChapter?.id]); @@ -507,6 +514,7 @@ export default function Reader() { }, [pageGroups, pageNumber, adjacent, activeChapterList]); const goForward = useCallback(() => { + if (loading || !pageUrls.length) return; if (style === "double" && pageGroups.length) { advanceGroup(true); return; } if (pageNumber < lastPage) { const nextUrl = pageUrls[pageNumber]; // pageNumber is 1-based, so index is pageNumber @@ -521,9 +529,10 @@ export default function Reader() { } else { closeReader(); } - }, [pageNumber, lastPage, pageUrls, adjacent, activeChapterList, style, pageGroups, advanceGroup]); + }, [loading, pageNumber, lastPage, pageUrls, adjacent, activeChapterList, style, pageGroups, advanceGroup]); const goBack = useCallback(() => { + if (loading || !pageUrls.length) return; if (style === "double" && pageGroups.length) { advanceGroup(false); return; } if (pageNumber > 1) { const prevUrl = pageUrls[pageNumber - 2]; // 0-based index of previous page @@ -535,7 +544,7 @@ export default function Reader() { } else if (adjacent.prev) { 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 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.firstPage)) { e.preventDefault(); setPageNumber(1); } 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.chapterLeft)) { e.preventDefault(); if (adjacent.prev) openReader(adjacent.prev, 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 (!loading && adjacent.prev) openReader(adjacent.prev, activeChapterList); } 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.toggleFullscreen)) { e.preventDefault(); toggleFullscreen().catch(console.error); } @@ -609,7 +618,7 @@ export default function Reader() { }; window.addEventListener("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 ───────────────────────────────────────────────── // Tracks current page number. In autoNext mode, appends the next chapter's @@ -935,11 +944,11 @@ export default function Reader() { ) : ( pageReady && ( {`Page ) )} @@ -947,10 +956,10 @@ export default function Reader() { {/* ── Bottom nav ── */}
- -
diff --git a/src/store/index.ts b/src/store/index.ts index d4eb9ec..2fff536 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -64,7 +64,7 @@ export interface Settings { } export const DEFAULT_SETTINGS: Settings = { - pageStyle: "single", + pageStyle: "longstrip", readingDirection: "ltr", fitMode: "width", maxPageWidth: 900,