From 7ed4937d9d0de06928e5600b851630e06f348595 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Thu, 19 Jun 2025 00:15:55 +0800 Subject: [PATCH] settings: add an option to always show status bar (#1417) --- .../public/locales/ar/translation.json | 3 +- .../public/locales/de/translation.json | 3 +- .../public/locales/el/translation.json | 3 +- .../public/locales/es/translation.json | 3 +- .../public/locales/fr/translation.json | 3 +- .../public/locales/hi/translation.json | 3 +- .../public/locales/id/translation.json | 3 +- .../public/locales/it/translation.json | 3 +- .../public/locales/ja/translation.json | 3 +- .../public/locales/ko/translation.json | 3 +- .../public/locales/nl/translation.json | 3 +- .../public/locales/pl/translation.json | 3 +- .../public/locales/pt/translation.json | 3 +- .../public/locales/ru/translation.json | 3 +- .../public/locales/tr/translation.json | 3 +- .../public/locales/uk/translation.json | 3 +- .../public/locales/vi/translation.json | 3 +- .../public/locales/zh-CN/translation.json | 3 +- .../public/locales/zh-TW/translation.json | 3 +- .../app/library/components/SettingsMenu.tsx | 16 +++++ .../src/app/reader/components/Reader.tsx | 18 +----- apps/readest-app/src/hooks/useTheme.ts | 60 +++++++++++++------ apps/readest-app/src/services/constants.ts | 1 + apps/readest-app/src/types/settings.ts | 1 + 24 files changed, 99 insertions(+), 54 deletions(-) diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index 495532df..47461738 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -374,5 +374,6 @@ "Bottom Margin (px)": "الهامش السفلي (بكسل)", "Right Margin (px)": "الهامش الأيمن (بكسل)", "Left Margin (px)": "الهامش الأيسر (بكسل)", - "Column Gap (%)": "تباعد الأعمدة (%)" + "Column Gap (%)": "تباعد الأعمدة (%)", + "Always Show Status Bar": "دائمًا إظهار شريط الحالة" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index d901ca11..640a0d8c 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -362,5 +362,6 @@ "Bottom Margin (px)": "Unterer Rand (px)", "Right Margin (px)": "Rechter Rand (px)", "Left Margin (px)": "Linker Rand (px)", - "Column Gap (%)": "Spaltenabstand (%)" + "Column Gap (%)": "Spaltenabstand (%)", + "Always Show Status Bar": "Statusleiste immer anzeigen" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 32ff5787..69241fb5 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -362,5 +362,6 @@ "Bottom Margin (px)": "Κάτω περιθώριο (px)", "Right Margin (px)": "Δεξί περιθώριο (px)", "Left Margin (px)": "Αριστερό περιθώριο (px)", - "Column Gap (%)": "Απόσταση στηλών (%)" + "Column Gap (%)": "Απόσταση στηλών (%)", + "Always Show Status Bar": "Πάντα εμφάνιση γραμμής κατάστασης" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index a5284a4c..f506c5c7 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -365,5 +365,6 @@ "Bottom Margin (px)": "Margen inferior (px)", "Right Margin (px)": "Margen derecho (px)", "Left Margin (px)": "Margen izquierdo (px)", - "Column Gap (%)": "Espacio entre columnas (%)" + "Column Gap (%)": "Espacio entre columnas (%)", + "Always Show Status Bar": "Mostrar siempre la barra de estado" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index f1df10c3..0249bf07 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -365,5 +365,6 @@ "Bottom Margin (px)": "Marge inférieure (px)", "Right Margin (px)": "Marge droite (px)", "Left Margin (px)": "Marge gauche (px)", - "Column Gap (%)": "Espacement des colonnes (%)" + "Column Gap (%)": "Espacement des colonnes (%)", + "Always Show Status Bar": "Afficher toujours la barre d'état" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index b85df537..91442ee1 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -362,5 +362,6 @@ "Bottom Margin (px)": "निचला हाशिया (px)", "Right Margin (px)": "दायां हाशिया (px)", "Left Margin (px)": "बायां हाशिया (px)", - "Column Gap (%)": "स्तंभों के बीच की दूरी (%)" + "Column Gap (%)": "स्तंभों के बीच की दूरी (%)", + "Always Show Status Bar": "स्थिति पट्टी हमेशा दिखाएं" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 5125e1a7..6d0192e2 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -359,5 +359,6 @@ "Bottom Margin (px)": "Margin Bawah (px)", "Right Margin (px)": "Margin Kanan (px)", "Left Margin (px)": "Margin Kiri (px)", - "Column Gap (%)": "Jarak Antar Kolom (%)" + "Column Gap (%)": "Jarak Antar Kolom (%)", + "Always Show Status Bar": "Selalu Tampilkan Bilah Status" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 2224ae2a..fe2a91c4 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -365,5 +365,6 @@ "Bottom Margin (px)": "Margine Inferiore (px)", "Right Margin (px)": "Margine Destro (px)", "Left Margin (px)": "Margine Sinistro (px)", - "Column Gap (%)": "Spazio tra Colonne (%)" + "Column Gap (%)": "Spazio tra Colonne (%)", + "Always Show Status Bar": "Mostra sempre la barra di stato" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 83605f56..21dbc78a 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -359,5 +359,6 @@ "Bottom Margin (px)": "下マージン (px)", "Right Margin (px)": "右マージン (px)", "Left Margin (px)": "左マージン (px)", - "Column Gap (%)": "列間の間隔 (%)" + "Column Gap (%)": "列間の間隔 (%)", + "Always Show Status Bar": "ステータスバーを常に表示" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index f64e42dc..770d912a 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -359,5 +359,6 @@ "Bottom Margin (px)": "아래쪽 여백 (px)", "Right Margin (px)": "오른쪽 여백 (px)", "Left Margin (px)": "왼쪽 여백 (px)", - "Column Gap (%)": "열 간격 (%)" + "Column Gap (%)": "열 간격 (%)", + "Always Show Status Bar": "상태 표시줄 항상 표시" } diff --git a/apps/readest-app/public/locales/nl/translation.json b/apps/readest-app/public/locales/nl/translation.json index c6e380cb..fbe536ab 100644 --- a/apps/readest-app/public/locales/nl/translation.json +++ b/apps/readest-app/public/locales/nl/translation.json @@ -362,5 +362,6 @@ "Bottom Margin (px)": "Ondermarge (px)", "Right Margin (px)": "Rechter marge (px)", "Left Margin (px)": "Linker marge (px)", - "Column Gap (%)": "Kolomafstand (%)" + "Column Gap (%)": "Kolomafstand (%)", + "Always Show Status Bar": "Statusbalk altijd weergeven" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index 6ac5c047..5b5644b0 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -368,5 +368,6 @@ "Bottom Margin (px)": "Dolny margines (px)", "Right Margin (px)": "Prawy margines (px)", "Left Margin (px)": "Lewy margines (px)", - "Column Gap (%)": "Odstęp między kolumnami (%)" + "Column Gap (%)": "Odstęp między kolumnami (%)", + "Always Show Status Bar": "Zawsze pokazuj pasek stanu" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index d5468b76..d8daf47b 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -365,5 +365,6 @@ "Bottom Margin (px)": "Margem inferior (px)", "Right Margin (px)": "Margem direita (px)", "Left Margin (px)": "Margem esquerda (px)", - "Column Gap (%)": "Espaço entre colunas (%)" + "Column Gap (%)": "Espaço entre colunas (%)", + "Always Show Status Bar": "Exibir sempre a barra de status" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index 905bd9d1..1f65bcf6 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -368,5 +368,6 @@ "Bottom Margin (px)": "Нижний отступ (пикс)", "Right Margin (px)": "Правый отступ (пикс)", "Left Margin (px)": "Левый отступ (пикс)", - "Column Gap (%)": "Промежуток между колонками (%)" + "Column Gap (%)": "Промежуток между колонками (%)", + "Always Show Status Bar": "Всегда показывать панель состояния" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index f76b8801..d0095308 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -362,5 +362,6 @@ "Bottom Margin (px)": "Alt Kenar Boşluğu (px)", "Right Margin (px)": "Sağ Kenar Boşluğu (px)", "Left Margin (px)": "Sol Kenar Boşluğu (px)", - "Column Gap (%)": "Sütun Aralığı (%)" + "Column Gap (%)": "Sütun Aralığı (%)", + "Always Show Status Bar": "Durum Çubuğunu Her Zaman Göster" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 5ba8a994..e7d7930f 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -368,5 +368,6 @@ "Bottom Margin (px)": "Нижній відступ (px)", "Right Margin (px)": "Правий відступ (px)", "Left Margin (px)": "Лівий відступ (px)", - "Column Gap (%)": "Проміжок між стовпцями (%)" + "Column Gap (%)": "Проміжок між стовпцями (%)", + "Always Show Status Bar": "Завжди показувати панель стану" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 8a90a2c0..baa92d3e 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -359,5 +359,6 @@ "Bottom Margin (px)": "Lề dưới (px)", "Right Margin (px)": "Lề phải (px)", "Left Margin (px)": "Lề trái (px)", - "Column Gap (%)": "Khoảng cách cột (%)" + "Column Gap (%)": "Khoảng cách cột (%)", + "Always Show Status Bar": "Luôn hiển thị thanh trạng thái" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index 5f92ca75..c9b39aac 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -359,5 +359,6 @@ "Bottom Margin (px)": "下边距", "Right Margin (px)": "右边距", "Left Margin (px)": "左边距", - "Column Gap (%)": "列间距" + "Column Gap (%)": "列间距", + "Always Show Status Bar": "始终显示状态栏" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 752a66f9..8f0304ca 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -359,5 +359,6 @@ "Bottom Margin (px)": "下邊距", "Right Margin (px)": "右邊距", "Left Margin (px)": "左邊距", - "Column Gap (%)": "欄間距" + "Column Gap (%)": "欄間距", + "Always Show Status Bar": "始終顯示狀態欄" } diff --git a/apps/readest-app/src/app/library/components/SettingsMenu.tsx b/apps/readest-app/src/app/library/components/SettingsMenu.tsx index a546d6c0..559ea2d7 100644 --- a/apps/readest-app/src/app/library/components/SettingsMenu.tsx +++ b/apps/readest-app/src/app/library/components/SettingsMenu.tsx @@ -38,6 +38,7 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { const [isAutoUpload, setIsAutoUpload] = useState(settings.autoUpload); const [isAutoCheckUpdates, setIsAutoCheckUpdates] = useState(settings.autoCheckUpdates); const [isAlwaysOnTop, setIsAlwaysOnTop] = useState(settings.alwaysOnTop); + const [isAlwaysShowStatusBar, setIsAlwaysShowStatusBar] = useState(settings.alwaysShowStatusBar); const [isScreenWakeLock, setIsScreenWakeLock] = useState(settings.screenWakeLock); const [isOpenLastBooks, setIsOpenLastBooks] = useState(settings.openLastBooks); const [isAutoImportBooksOnOpen, setIsAutoImportBooksOnOpen] = useState( @@ -92,6 +93,14 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { setIsDropdownOpen?.(false); }; + const toggleAlwaysShowStatusBar = () => { + settings.alwaysShowStatusBar = !settings.alwaysShowStatusBar; + setSettings(settings); + saveSettings(envConfig, settings); + setIsAlwaysShowStatusBar(settings.alwaysShowStatusBar); + setIsDropdownOpen?.(false); + }; + const toggleAutoUploadBooks = () => { settings.autoUpload = !settings.autoUpload; setSettings(settings); @@ -214,6 +223,13 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { onClick={toggleAlwaysOnTop} /> )} + {appService?.isMobileApp && ( + + )} = ({ ids }) => { const [libraryLoaded, setLibraryLoaded] = useState(false); const isInitiating = useRef(false); - useTheme({ systemUIVisible: false, appThemeColor: 'base-100' }); + useTheme({ systemUIVisible: settings.alwaysShowStatusBar, appThemeColor: 'base-100' }); useScreenWakeLock(settings.screenWakeLock); useEffect(() => { @@ -50,20 +50,6 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => { initDayjs(getLocale()); }, []); - useEffect(() => { - const handleVisibilityChange = () => { - if (appService?.isMobileApp && !document.hidden) { - dismissSystemUI(); - setSystemUIVisibility({ visible: false, darkMode: isDarkMode }); - } - }; - document.addEventListener('visibilitychange', handleVisibilityChange); - return () => { - document.removeEventListener('visibilitychange', handleVisibilityChange); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [appService, isDarkMode]); - const handleKeyDown = (event: CustomEvent) => { if (event.detail.keyName === 'Back') { setSideBarVisible(false); @@ -109,7 +95,7 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => { useEffect(() => { if (!appService?.isMobileApp) return; - const systemUIVisible = !!hoveredBookKey; + const systemUIVisible = !!hoveredBookKey || settings.alwaysShowStatusBar; setSystemUIVisibility({ visible: systemUIVisible, darkMode: isDarkMode }); if (systemUIVisible) { showSystemUI(); diff --git a/apps/readest-app/src/hooks/useTheme.ts b/apps/readest-app/src/hooks/useTheme.ts index bcf43368..b2c33b89 100644 --- a/apps/readest-app/src/hooks/useTheme.ts +++ b/apps/readest-app/src/hooks/useTheme.ts @@ -4,6 +4,7 @@ import { useThemeStore } from '@/store/themeStore'; import { useSettingsStore } from '@/store/settingsStore'; import { applyCustomTheme, Palette } from '@/styles/themes'; import { getStatusBarHeight, setSystemUIVisibility } from '@/utils/bridge'; +import { getOSPlatform } from '@/utils/misc'; type UseThemeProps = { systemUIVisible?: boolean; @@ -27,14 +28,6 @@ export const useTheme = ({ useEffect(() => { updateAppTheme(appThemeColor); - if (appService?.isMobileApp) { - if (systemUIVisible) { - showSystemUI(); - } else { - dismissSystemUI(); - } - setSystemUIVisibility({ visible: systemUIVisible, darkMode: isDarkMode }); - } if (appService?.isAndroidApp) { getStatusBarHeight().then((res) => { if (res.height && res.height > 0) { @@ -43,27 +36,56 @@ export const useTheme = ({ }); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [appService, isDarkMode]); + }, []); - const handleOrientationChange = useCallback(() => { - if (appService?.isIOSApp) { - if (screen.orientation.type.includes('landscape')) { - dismissSystemUI(); - setSystemUIVisibility({ visible: false, darkMode: isDarkMode }); - } else if (systemUIVisible) { - showSystemUI(); - setSystemUIVisibility({ visible: true, darkMode: isDarkMode }); - } + const handleSystemUIVisibility = useCallback(() => { + if (!appService?.isMobileApp) return; + + // This is a workaround for iPhone apps where the system UI is not visible in landscape mode + // when the app is in fullscreen mode until we find a better solution to override the prefersStatusBarHidden + // in the ViewController. + const isIPhoneApp = appService.isIOSApp && getOSPlatform() === 'ios'; + const systemUINeverVisible = isIPhoneApp && screen.orientation.type.includes('landscape'); + const visible = systemUIVisible && !systemUINeverVisible; + if (visible) { + showSystemUI(); + } else { + dismissSystemUI(); } + setSystemUIVisibility({ visible, darkMode: isDarkMode }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [appService, isDarkMode, systemUIVisible]); useEffect(() => { + if (appService?.isMobileApp) { + handleSystemUIVisibility(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [handleSystemUIVisibility]); + + useEffect(() => { + if (!appService?.isMobileApp) return; + + handleSystemUIVisibility(); + const handleVisibilityChange = () => { + if (document.visibilityState === 'visible') { + handleSystemUIVisibility(); + } + }; + const handleOrientationChange = () => { + // Only handle orientation change for iPhone apps + if (appService?.isIOSApp && getOSPlatform() === 'ios') { + handleSystemUIVisibility(); + } + }; + document.addEventListener('visibilitychange', handleVisibilityChange); screen.orientation.addEventListener('change', handleOrientationChange); return () => { + document.removeEventListener('visibilitychange', handleVisibilityChange); screen.orientation.removeEventListener('change', handleOrientationChange); }; - }, [handleOrientationChange]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [handleSystemUIVisibility]); useEffect(() => { const customThemes = settings.globalReadSettings?.customThemes ?? []; diff --git a/apps/readest-app/src/services/constants.ts b/apps/readest-app/src/services/constants.ts index 8c10b67a..b6010ffb 100644 --- a/apps/readest-app/src/services/constants.ts +++ b/apps/readest-app/src/services/constants.ts @@ -37,6 +37,7 @@ export const DEFAULT_SYSTEM_SETTINGS: Partial = { keepLogin: false, autoUpload: true, alwaysOnTop: false, + alwaysShowStatusBar: false, autoCheckUpdates: true, screenWakeLock: false, openLastBooks: false, diff --git a/apps/readest-app/src/types/settings.ts b/apps/readest-app/src/types/settings.ts index 0b2a520e..cb94ad03 100644 --- a/apps/readest-app/src/types/settings.ts +++ b/apps/readest-app/src/types/settings.ts @@ -28,6 +28,7 @@ export interface SystemSettings { alwaysOnTop: boolean; autoCheckUpdates: boolean; screenWakeLock: boolean; + alwaysShowStatusBar: boolean; openLastBooks: boolean; lastOpenBooks: string[]; autoImportBooksOnOpen: boolean;