From 7d9724ff8b95fcb695c733876f9dabb76a7333af Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Sun, 31 Aug 2025 16:15:28 +0800 Subject: [PATCH] fix: close books with the system back key on Android, closes #1933 (#1938) --- .../src/app/reader/components/Reader.tsx | 34 +++++++++++-------- .../app/reader/components/ReaderContent.tsx | 2 ++ apps/readest-app/src/store/notebookStore.ts | 2 ++ apps/readest-app/src/store/sidebarStore.ts | 4 ++- apps/readest-app/src/utils/nav.ts | 2 +- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/apps/readest-app/src/app/reader/components/Reader.tsx b/apps/readest-app/src/app/reader/components/Reader.tsx index 84f1a6bf..bf7b1dc4 100644 --- a/apps/readest-app/src/app/reader/components/Reader.tsx +++ b/apps/readest-app/src/app/reader/components/Reader.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import * as React from 'react'; import { useEffect, Suspense, useRef, useState } from 'react'; +import { useRouter } from 'next/navigation'; import { useEnv } from '@/context/EnvContext'; import { useTheme } from '@/hooks/useTheme'; @@ -28,12 +29,13 @@ import { initDayjs } from '@/utils/time'; import ReaderContent from './ReaderContent'; const Reader: React.FC<{ ids?: string }> = ({ ids }) => { + const router = useRouter(); const { envConfig, appService } = useEnv(); const { setLibrary } = useLibraryStore(); const { hoveredBookKey } = useReaderStore(); const { settings, setSettings } = useSettingsStore(); - const { isSideBarVisible, setSideBarVisible } = useSidebarStore(); - const { isNotebookVisible, setNotebookVisible } = useNotebookStore(); + const { isSideBarVisible, getIsSideBarVisible, setSideBarVisible } = useSidebarStore(); + const { isNotebookVisible, getIsNotebookVisible, setNotebookVisible } = useNotebookStore(); const { isDarkMode, systemUIAlwaysHidden, showSystemUI, dismissSystemUI } = useThemeStore(); const { acquireBackKeyInterception, releaseBackKeyInterception } = useDeviceControlStore(); const [libraryLoaded, setLibraryLoaded] = useState(false); @@ -49,12 +51,24 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => { setTimeout(getSysFontsList, 3000); } initDayjs(getLocale()); + + acquireBackKeyInterception(); + return () => { + releaseBackKeyInterception(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleKeyDown = (event: CustomEvent) => { if (event.detail.keyName === 'Back') { - setSideBarVisible(false); - setNotebookVisible(false); + if (getIsSideBarVisible()) { + setSideBarVisible(false); + } else if (getIsNotebookVisible()) { + setNotebookVisible(false); + } else { + eventDispatcher.dispatch('close-reader'); + router.back(); + } return true; } return false; @@ -62,22 +76,14 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => { useEffect(() => { if (!appService?.isAndroidApp) return; - if (isSideBarVisible || isNotebookVisible) { - acquireBackKeyInterception(); - eventDispatcher.onSync('native-key-down', handleKeyDown); - } - if (!isSideBarVisible && !isNotebookVisible) { - releaseBackKeyInterception(); - eventDispatcher.offSync('native-key-down', handleKeyDown); - } + eventDispatcher.onSync('native-key-down', handleKeyDown); return () => { if (appService?.isAndroidApp) { - releaseBackKeyInterception(); eventDispatcher.offSync('native-key-down', handleKeyDown); } }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isSideBarVisible, isNotebookVisible]); + }, [appService?.isAndroidApp, isSideBarVisible, isNotebookVisible]); useEffect(() => { if (isInitiating.current) return; diff --git a/apps/readest-app/src/app/reader/components/ReaderContent.tsx b/apps/readest-app/src/app/reader/components/ReaderContent.tsx index 0defebf0..14af63af 100644 --- a/apps/readest-app/src/app/reader/components/ReaderContent.tsx +++ b/apps/readest-app/src/app/reader/components/ReaderContent.tsx @@ -94,10 +94,12 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i } window.addEventListener('beforeunload', handleCloseBooks); eventDispatcher.on('beforereload', handleCloseBooks); + eventDispatcher.on('close-reader', handleCloseBooks); eventDispatcher.on('quit-app', handleCloseBooks); return () => { window.removeEventListener('beforeunload', handleCloseBooks); eventDispatcher.off('beforereload', handleCloseBooks); + eventDispatcher.off('close-reader', handleCloseBooks); eventDispatcher.off('quit-app', handleCloseBooks); unlistenOnCloseWindow?.then((fn) => fn()); }; diff --git a/apps/readest-app/src/store/notebookStore.ts b/apps/readest-app/src/store/notebookStore.ts index be9b5b7c..071e521d 100644 --- a/apps/readest-app/src/store/notebookStore.ts +++ b/apps/readest-app/src/store/notebookStore.ts @@ -9,6 +9,7 @@ interface NotebookState { notebookNewAnnotation: TextSelection | null; notebookEditAnnotation: BookNote | null; notebookAnnotationDrafts: { [key: string]: string }; + getIsNotebookVisible: () => boolean; toggleNotebook: () => void; toggleNotebookPin: () => void; setNotebookWidth: (width: string) => void; @@ -27,6 +28,7 @@ export const useNotebookStore = create((set, get) => ({ notebookNewAnnotation: null, notebookEditAnnotation: null, notebookAnnotationDrafts: {}, + getIsNotebookVisible: () => get().isNotebookVisible, setNotebookWidth: (width: string) => set({ notebookWidth: width }), toggleNotebook: () => set((state) => ({ isNotebookVisible: !state.isNotebookVisible })), toggleNotebookPin: () => set((state) => ({ isNotebookPinned: !state.isNotebookPinned })), diff --git a/apps/readest-app/src/store/sidebarStore.ts b/apps/readest-app/src/store/sidebarStore.ts index 33ebc18b..9d463aad 100644 --- a/apps/readest-app/src/store/sidebarStore.ts +++ b/apps/readest-app/src/store/sidebarStore.ts @@ -5,6 +5,7 @@ interface SidebarState { sideBarWidth: string; isSideBarVisible: boolean; isSideBarPinned: boolean; + getIsSideBarVisible: () => boolean; setSideBarBookKey: (key: string) => void; setSideBarWidth: (width: string) => void; toggleSideBar: () => void; @@ -13,11 +14,12 @@ interface SidebarState { setSideBarPin: (pinned: boolean) => void; } -export const useSidebarStore = create((set) => ({ +export const useSidebarStore = create((set, get) => ({ sideBarBookKey: null, sideBarWidth: '', isSideBarVisible: false, isSideBarPinned: false, + getIsSideBarVisible: () => get().isSideBarVisible, setSideBarBookKey: (key: string) => set({ sideBarBookKey: key }), setSideBarWidth: (width: string) => set({ sideBarWidth: width }), toggleSideBar: () => set((state) => ({ isSideBarVisible: !state.isSideBarVisible })), diff --git a/apps/readest-app/src/utils/nav.ts b/apps/readest-app/src/utils/nav.ts index f9f140e5..7620a3aa 100644 --- a/apps/readest-app/src/utils/nav.ts +++ b/apps/readest-app/src/utils/nav.ts @@ -81,7 +81,7 @@ export const navigateToLibrary = ( queryParams?: string, navOptions?: { scroll?: boolean }, ) => { - router.push(`/library${queryParams ? `?${queryParams}` : ''}`, navOptions); + router.replace(`/library${queryParams ? `?${queryParams}` : ''}`, navOptions); }; export const redirectToLibrary = () => {