From 5f229cd8452018fcb93a0e1193a17fccc967a8b3 Mon Sep 17 00:00:00 2001 From: ZGY1999 <1051684164@qq.com> Date: Fri, 1 May 2026 16:52:31 +0800 Subject: [PATCH 1/3] feat: add vertical scroll reading mode --- .../app/src/components/reader/ReaderView.tsx | 32 ++++++++++++++----- .../src/components/settings/ReadSettings.tsx | 16 ++++++++++ .../core/src/hooks/reader/usePagination.ts | 12 +++++-- packages/foliate-js/paginator.js | 9 ++++++ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/packages/app/src/components/reader/ReaderView.tsx b/packages/app/src/components/reader/ReaderView.tsx index b384d17e..1cfc7282 100644 --- a/packages/app/src/components/reader/ReaderView.tsx +++ b/packages/app/src/components/reader/ReaderView.tsx @@ -189,6 +189,7 @@ function useAutoHideControls( delay = 2000, keepVisible = false, isDoublePage = false, + clickNavigationEnabled = true, ) { const [isVisible, setIsVisible] = useState(true); const timeoutRef = useRef | null>(null); @@ -246,6 +247,18 @@ function useAutoHideControls( const leftNavEnd = viewStartX + viewWidth * (isDoublePage ? 0.25 : 0.375); const rightNavStart = viewStartX + viewWidth * (isDoublePage ? 0.75 : 0.625); + if (!clickNavigationEnabled) { + setIsVisible((prev) => { + if (prev) { + clearTimer(); + return false; + } + showAndScheduleHide(); + return true; + }); + return; + } + if (clickScreenX > leftNavEnd && clickScreenX < rightNavStart) { // Middle zone: toggle toolbar setIsVisible((prev) => { @@ -272,7 +285,16 @@ function useAutoHideControls( window.addEventListener("message", handleMessage); return () => window.removeEventListener("message", handleMessage); - }, [bookKey, clearTimer, containerRef, onNext, onPrev, showAndScheduleHide, isDoublePage]); + }, [ + bookKey, + clearTimer, + clickNavigationEnabled, + containerRef, + onNext, + onPrev, + showAndScheduleHide, + isDoublePage, + ]); // Mouse enter/leave handlers for toolbar area const handleMouseEnter = useCallback(() => { @@ -321,7 +343,6 @@ export function ReaderView({ bookId, tabId }: ReaderViewProps) { const appTab = useAppStore((s) => s.tabs.find((t) => t.id === tabId)); const closeAppTab = useAppStore((s) => s.removeTab); const viewSettings = useSettingsStore((s) => s.readSettings); - const updateReadSettings = useSettingsStore((s) => s.updateReadSettings); const setProgress = useReaderStore((s) => s.setProgress); const setChapter = useReaderStore((s) => s.setChapter); const setSelectedText = useReaderStore((s) => s.setSelectedText); @@ -804,6 +825,7 @@ export function ReaderView({ bookId, tabId }: ReaderViewProps) { 2000, keepControlsVisible, (viewSettings.paginatedLayout ?? "double") === "double", + viewSettings.viewMode !== "scroll", ); const toolbarVisible = controlsVisible || isToolbarPinned; const readingHeaderTitle = (readerTab?.chapterTitle || book?.meta.title || "").trim(); @@ -860,12 +882,6 @@ export function ReaderView({ bookId, tabId }: ReaderViewProps) { }, 5000), ).current; - useEffect(() => { - if (viewSettings.viewMode === "scroll") { - updateReadSettings({ viewMode: "paginated" }); - } - }, [viewSettings.viewMode, updateReadSettings]); - // --- Load book on mount --- useEffect(() => { if (!book?.filePath || isInitializedRef.current) return; diff --git a/packages/app/src/components/settings/ReadSettings.tsx b/packages/app/src/components/settings/ReadSettings.tsx index 9902d620..0aa59268 100644 --- a/packages/app/src/components/settings/ReadSettings.tsx +++ b/packages/app/src/components/settings/ReadSettings.tsx @@ -38,6 +38,22 @@ export function ReadSettingsPanel() {

{t("settings.readingNotice")}

+
+ {t("settings.viewMode")} + +
+
{t("settings.paginatedLayout")}