layout: remove unnecessary inset for header on landscape screen in iOS (#1425)

This commit is contained in:
Huang Xin
2025-06-19 18:01:42 +08:00
committed by GitHub
parent f0d3c9dd4e
commit 0f66ecbba1
5 changed files with 28 additions and 18 deletions
@@ -104,6 +104,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
isHoveredAnim={bookKeys.length > 2}
onCloseBook={onCloseBook}
onSetSettingsDialogOpen={setFontLayoutSettingsDialogOpen}
gridInsets={gridInsets}
/>
<FoliateViewer
bookKey={bookKey}
@@ -2,6 +2,7 @@ import clsx from 'clsx';
import React, { useEffect, useRef, useState } from 'react';
import { PiDotsThreeVerticalBold } from 'react-icons/pi';
import { Insets } from '@/types/misc';
import { useEnv } from '@/context/EnvContext';
import { useThemeStore } from '@/store/themeStore';
import { useReaderStore } from '@/store/readerStore';
@@ -22,6 +23,7 @@ interface HeaderBarProps {
bookTitle: string;
isTopLeft: boolean;
isHoveredAnim: boolean;
gridInsets: Insets;
onCloseBook: (bookKey: string) => void;
onSetSettingsDialogOpen: (open: boolean) => void;
}
@@ -31,6 +33,7 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
bookTitle,
isTopLeft,
isHoveredAnim,
gridInsets,
onCloseBook,
onSetSettingsDialogOpen,
}) => {
@@ -77,10 +80,10 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
return (
<div
className={clsx(
'bg-base-100 absolute top-0 w-full',
appService?.hasSafeAreaInset && 'pt-[env(safe-area-inset-top)]',
)}
className={clsx('bg-base-100 absolute top-0 w-full')}
style={{
paddingTop: appService?.hasSafeAreaInset ? `${gridInsets.top}px` : '0px',
}}
>
<div
className={clsx('absolute top-0 z-10 hidden h-11 w-full sm:flex')}
@@ -89,11 +92,11 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
/>
<div
className={clsx(
'bg-base-100 absolute left-0 right-0 top-0 z-10 h-[env(safe-area-inset-top)]',
'bg-base-100 absolute left-0 right-0 top-0 z-10',
isVisible ? 'visible' : 'hidden',
)}
style={{
height: systemUIVisible ? `max(env(safe-area-inset-top), ${statusBarHeight}px)` : '',
height: systemUIVisible ? `${Math.max(gridInsets.top, statusBarHeight)}px` : '0px',
}}
/>
<div
@@ -110,8 +113,8 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
)}
style={{
marginTop: systemUIVisible
? `max(env(safe-area-inset-top), ${statusBarHeight}px)`
: 'env(safe-area-inset-top)',
? `${Math.max(gridInsets.top, statusBarHeight)}px`
: `${gridInsets.top}px`,
}}
onMouseLeave={() => !appService?.isMobile && setHoveredBookKey('')}
>
@@ -33,7 +33,7 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => {
const { settings, setSettings } = useSettingsStore();
const { isSideBarVisible, setSideBarVisible } = useSidebarStore();
const { isNotebookVisible, setNotebookVisible } = useNotebookStore();
const { isDarkMode, showSystemUI, dismissSystemUI } = useThemeStore();
const { isDarkMode, systemUIAlwaysHidden, showSystemUI, dismissSystemUI } = useThemeStore();
const { acquireBackKeyInterception, releaseBackKeyInterception } = useDeviceControlStore();
const [libraryLoaded, setLibraryLoaded] = useState(false);
const isInitiating = useRef(false);
@@ -96,8 +96,9 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => {
useEffect(() => {
if (!appService?.isMobileApp) return;
const systemUIVisible = !!hoveredBookKey || settings.alwaysShowStatusBar;
setSystemUIVisibility({ visible: systemUIVisible, darkMode: isDarkMode });
if (systemUIVisible) {
const visible = systemUIVisible && !systemUIAlwaysHidden;
setSystemUIVisibility({ visible, darkMode: isDarkMode });
if (visible) {
showSystemUI();
} else {
dismissSystemUI();
+8 -7
View File
@@ -24,6 +24,8 @@ export const useTheme = ({
dismissSystemUI,
updateAppTheme,
setStatusBarHeight,
systemUIAlwaysHidden,
setSystemUIAlwaysHidden,
} = useThemeStore();
useEffect(() => {
@@ -41,12 +43,7 @@ export const useTheme = ({
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;
const visible = systemUIVisible && !systemUIAlwaysHidden;
if (visible) {
showSystemUI();
} else {
@@ -73,8 +70,12 @@ export const useTheme = ({
}
};
const handleOrientationChange = () => {
// Only handle orientation change for iPhone apps
if (appService?.isIOSApp && getOSPlatform() === 'ios') {
// FIXME: 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. Note that screen.orientation.type is not abailable in iOS before 16.4.
const systemUIAlwaysHidden = screen.orientation?.type.includes('landscape');
setSystemUIAlwaysHidden(systemUIAlwaysHidden);
handleSystemUIVisibility();
}
};
+4
View File
@@ -12,6 +12,8 @@ interface ThemeState {
isDarkMode: boolean;
systemUIVisible: boolean;
statusBarHeight: number;
systemUIAlwaysHidden: boolean;
setSystemUIAlwaysHidden: (hidden: boolean) => void;
setStatusBarHeight: (height: number) => void;
showSystemUI: () => void;
dismissSystemUI: () => void;
@@ -69,9 +71,11 @@ export const useThemeStore = create<ThemeState>((set, get) => {
themeCode,
systemUIVisible: false,
statusBarHeight: 24,
systemUIAlwaysHidden: false,
showSystemUI: () => set({ systemUIVisible: true }),
dismissSystemUI: () => set({ systemUIVisible: false }),
setStatusBarHeight: (height: number) => set({ statusBarHeight: height }),
setSystemUIAlwaysHidden: (hidden: boolean) => set({ systemUIAlwaysHidden: hidden }),
getIsDarkMode: () => get().isDarkMode,
setThemeMode: (mode) => {
if (typeof window !== 'undefined' && localStorage) {