diff --git a/apps/readest-app/src/app/reader/components/footerbar/DesktopFooterBar.tsx b/apps/readest-app/src/app/reader/components/footerbar/DesktopFooterBar.tsx index f0397d59..aa713287 100644 --- a/apps/readest-app/src/app/reader/components/footerbar/DesktopFooterBar.tsx +++ b/apps/readest-app/src/app/reader/components/footerbar/DesktopFooterBar.tsx @@ -17,6 +17,7 @@ const DesktopFooterBar: React.FC = ({ progressValid, progressFraction, navigationHandlers, + isMobileLayout, onSpeakText, }) => { const _ = useTranslation(); @@ -67,7 +68,11 @@ const DesktopFooterBar: React.FC = ({ return (
= ({ const footerBarRef = useRef(null); useSpatialNavigation(footerBarRef, isVisible); + const isPortrait = window.innerWidth <= window.innerHeight; + const isMobile = appService?.isMobile || window.innerWidth < 640; + const isMobileLayout = isMobile || (!!appService?.isAndroidApp && isPortrait); + const commonProps: FooterBarChildProps = { bookKey, gridInsets, @@ -201,6 +205,7 @@ const FooterBar: React.FC = ({ progressValid, progressFraction, navigationHandlers, + isMobileLayout, onSetActionTab: handleSetActionTab, onSpeakText: handleSpeakText, }; @@ -210,21 +215,24 @@ const FooterBar: React.FC = ({ (bookData?.isFixedLayout && viewSettings?.zoomLevel && viewSettings.zoomLevel > 100); const containerClasses = clsx( - 'footer-bar shadow-xs bottom-0 left-0 z-10 flex w-full flex-col sm:h-[52px]', - 'sm:bg-base-100 border-base-300/50 border-t sm:border-none', + 'footer-bar shadow-xs bottom-0 left-0 z-10 flex w-full flex-col', + isMobileLayout ? '' : 'sm:h-[52px]', + isMobileLayout ? '' : 'sm:bg-base-100 sm:border-none', + 'border-base-300/50 border-t', 'transition-[opacity,transform] duration-300', - window.innerWidth < 640 ? 'fixed' : 'absolute', + isMobileLayout ? 'fixed' : window.innerWidth < 640 ? 'fixed' : 'absolute', appService?.hasRoundedWindow && 'rounded-window-bottom-right', !isSideBarVisible && appService?.hasRoundedWindow && 'rounded-window-bottom-left', isHoveredAnim && 'hover-bar-anim', - needHorizontalScroll ? 'sm:!bottom-3 sm:!h-10 sm:justify-end' : 'sm:justify-center', + !isMobileLayout && + (needHorizontalScroll ? 'sm:!bottom-3 sm:!h-10 sm:justify-end' : 'sm:justify-center'), isVisible ? 'pointer-events-auto translate-y-0 opacity-100' - : 'pointer-events-none translate-y-full opacity-0 sm:translate-y-0', + : isMobileLayout + ? 'pointer-events-none translate-y-full opacity-0' + : 'pointer-events-none translate-y-full opacity-0 sm:translate-y-0', ); - const isMobile = appService?.isMobile || window.innerWidth < 640; - return ( <> {/* Hover trigger area */} diff --git a/apps/readest-app/src/app/reader/components/footerbar/MobileFooterBar.tsx b/apps/readest-app/src/app/reader/components/footerbar/MobileFooterBar.tsx index 30d30b5a..93b37902 100644 --- a/apps/readest-app/src/app/reader/components/footerbar/MobileFooterBar.tsx +++ b/apps/readest-app/src/app/reader/components/footerbar/MobileFooterBar.tsx @@ -1,3 +1,4 @@ +import clsx from 'clsx'; import React from 'react'; import { useResponsiveSize } from '@/hooks/useResponsiveSize'; import { FooterBarChildProps } from './types'; @@ -13,15 +14,16 @@ const MobileFooterBar: React.FC = ({ progressValid, progressFraction, navigationHandlers, + isMobileLayout, onSetActionTab, }) => { - const isMobile = window.innerWidth < 640 || window.innerHeight < 640; + const isMobile = isMobileLayout || window.innerWidth < 640 || window.innerHeight < 640; const sliderHeight = useResponsiveSize(28); const marginIconSize = useResponsiveSize(20); const bottomOffset = isMobile ? `${gridInsets.bottom * 0.33 + 64}px` : '64px'; return ( - <> +
= ({ bookKey={bookKey} actionTab={actionTab} gridInsets={gridInsets} + isMobileLayout={isMobileLayout} onSetActionTab={onSetActionTab!} /> - +
); }; diff --git a/apps/readest-app/src/app/reader/components/footerbar/NavigationBar.tsx b/apps/readest-app/src/app/reader/components/footerbar/NavigationBar.tsx index fde96dcd..f95da81d 100644 --- a/apps/readest-app/src/app/reader/components/footerbar/NavigationBar.tsx +++ b/apps/readest-app/src/app/reader/components/footerbar/NavigationBar.tsx @@ -16,6 +16,7 @@ interface NavigationBarProps { bookKey: string; actionTab: string; gridInsets: Insets; + isMobileLayout: boolean; onSetActionTab: (tab: string) => void; } @@ -23,6 +24,7 @@ export const NavigationBar: React.FC = ({ bookKey, actionTab, gridInsets, + isMobileLayout, onSetActionTab, }) => { const isMobile = window.innerWidth < 640 || window.innerHeight < 640; @@ -36,7 +38,10 @@ export const NavigationBar: React.FC = ({ return (
void; onSpeakText: () => void; } diff --git a/apps/readest-app/src/styles/globals.css b/apps/readest-app/src/styles/globals.css index 0d799a1a..6994453f 100644 --- a/apps/readest-app/src/styles/globals.css +++ b/apps/readest-app/src/styles/globals.css @@ -441,6 +441,13 @@ foliate-fxl { mask: linear-gradient(180deg, black 0%, rgba(0, 0, 0, 0.9) 50%, rgba(0, 0, 0, 0.5) 100%); } +/* Force mobile footer bar layout on Android portrait (overrides sm:hidden breakpoint) */ +@media (min-width: 640px) { + .force-mobile-layout .sm\:hidden { + display: flex; + } +} + .visible-focus-inset-2:focus-visible { outline: none; box-shadow: