settings: add an option to always show status bar (#1417)

This commit is contained in:
Huang Xin
2025-06-19 00:15:55 +08:00
committed by GitHub
parent b3593c0365
commit 7ed4937d9d
24 changed files with 99 additions and 54 deletions
@@ -374,5 +374,6 @@
"Bottom Margin (px)": "الهامش السفلي (بكسل)",
"Right Margin (px)": "الهامش الأيمن (بكسل)",
"Left Margin (px)": "الهامش الأيسر (بكسل)",
"Column Gap (%)": "تباعد الأعمدة (%)"
"Column Gap (%)": "تباعد الأعمدة (%)",
"Always Show Status Bar": "دائمًا إظهار شريط الحالة"
}
@@ -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"
}
@@ -362,5 +362,6 @@
"Bottom Margin (px)": "Κάτω περιθώριο (px)",
"Right Margin (px)": "Δεξί περιθώριο (px)",
"Left Margin (px)": "Αριστερό περιθώριο (px)",
"Column Gap (%)": "Απόσταση στηλών (%)"
"Column Gap (%)": "Απόσταση στηλών (%)",
"Always Show Status Bar": "Πάντα εμφάνιση γραμμής κατάστασης"
}
@@ -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"
}
@@ -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"
}
@@ -362,5 +362,6 @@
"Bottom Margin (px)": "निचला हाशिया (px)",
"Right Margin (px)": "दायां हाशिया (px)",
"Left Margin (px)": "बायां हाशिया (px)",
"Column Gap (%)": "स्तंभों के बीच की दूरी (%)"
"Column Gap (%)": "स्तंभों के बीच की दूरी (%)",
"Always Show Status Bar": "स्थिति पट्टी हमेशा दिखाएं"
}
@@ -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"
}
@@ -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"
}
@@ -359,5 +359,6 @@
"Bottom Margin (px)": "下マージン (px)",
"Right Margin (px)": "右マージン (px)",
"Left Margin (px)": "左マージン (px)",
"Column Gap (%)": "列間の間隔 (%)"
"Column Gap (%)": "列間の間隔 (%)",
"Always Show Status Bar": "ステータスバーを常に表示"
}
@@ -359,5 +359,6 @@
"Bottom Margin (px)": "아래쪽 여백 (px)",
"Right Margin (px)": "오른쪽 여백 (px)",
"Left Margin (px)": "왼쪽 여백 (px)",
"Column Gap (%)": "열 간격 (%)"
"Column Gap (%)": "열 간격 (%)",
"Always Show Status Bar": "상태 표시줄 항상 표시"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -368,5 +368,6 @@
"Bottom Margin (px)": "Нижний отступ (пикс)",
"Right Margin (px)": "Правый отступ (пикс)",
"Left Margin (px)": "Левый отступ (пикс)",
"Column Gap (%)": "Промежуток между колонками (%)"
"Column Gap (%)": "Промежуток между колонками (%)",
"Always Show Status Bar": "Всегда показывать панель состояния"
}
@@ -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"
}
@@ -368,5 +368,6 @@
"Bottom Margin (px)": "Нижній відступ (px)",
"Right Margin (px)": "Правий відступ (px)",
"Left Margin (px)": "Лівий відступ (px)",
"Column Gap (%)": "Проміжок між стовпцями (%)"
"Column Gap (%)": "Проміжок між стовпцями (%)",
"Always Show Status Bar": "Завжди показувати панель стану"
}
@@ -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"
}
@@ -359,5 +359,6 @@
"Bottom Margin (px)": "下边距",
"Right Margin (px)": "右边距",
"Left Margin (px)": "左边距",
"Column Gap (%)": "列间距"
"Column Gap (%)": "列间距",
"Always Show Status Bar": "始终显示状态栏"
}
@@ -359,5 +359,6 @@
"Bottom Margin (px)": "下邊距",
"Right Margin (px)": "右邊距",
"Left Margin (px)": "左邊距",
"Column Gap (%)": "欄間距"
"Column Gap (%)": "欄間距",
"Always Show Status Bar": "始終顯示狀態欄"
}
@@ -38,6 +38,7 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ 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<SettingsMenuProps> = ({ 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<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
onClick={toggleAlwaysOnTop}
/>
)}
{appService?.isMobileApp && (
<MenuItem
label={_('Always Show Status Bar')}
Icon={isAlwaysShowStatusBar ? MdCheck : undefined}
onClick={toggleAlwaysShowStatusBar}
/>
)}
<MenuItem
label={_('Keep Screen Awake')}
Icon={isScreenWakeLock ? MdCheck : undefined}
@@ -38,7 +38,7 @@ const Reader: React.FC<{ ids?: string }> = ({ 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();
+41 -19
View File
@@ -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 ?? [];
@@ -37,6 +37,7 @@ export const DEFAULT_SYSTEM_SETTINGS: Partial<SystemSettings> = {
keepLogin: false,
autoUpload: true,
alwaysOnTop: false,
alwaysShowStatusBar: false,
autoCheckUpdates: true,
screenWakeLock: false,
openLastBooks: false,
+1
View File
@@ -28,6 +28,7 @@ export interface SystemSettings {
alwaysOnTop: boolean;
autoCheckUpdates: boolean;
screenWakeLock: boolean;
alwaysShowStatusBar: boolean;
openLastBooks: boolean;
lastOpenBooks: string[];
autoImportBooksOnOpen: boolean;