Fix reader page scaling with applied safe area inset
The safe area inset wasn't applied everywhere, which potentially caused the scrollbar to appear while the pages should be fitting the screen fixes #1102
This commit is contained in:
@@ -350,6 +350,7 @@ export interface ReaderPagerProps
|
||||
| 'customFilter'
|
||||
| 'shouldStretchPage'
|
||||
| 'readerWidth'
|
||||
| 'safeAreaInset'
|
||||
>,
|
||||
Pick<NavbarContextType, 'readerNavBarWidth'> {
|
||||
onLoad?: (pagesIndex: number, url: string, isPrimary?: boolean) => void;
|
||||
|
||||
@@ -17,6 +17,7 @@ const BaseReaderRGBAFilter = ({ readerNavBarWidth }: Pick<NavbarContextType, 're
|
||||
value: { red, green, blue, alpha, blendMode },
|
||||
enabled,
|
||||
} = useReaderSettingsStore((state) => state.customFilter.rgba);
|
||||
const safeAreaInset = useReaderSettingsStore('safeAreaInset');
|
||||
|
||||
if (!enabled) {
|
||||
return null;
|
||||
@@ -26,10 +27,10 @@ const BaseReaderRGBAFilter = ({ readerNavBarWidth }: Pick<NavbarContextType, 're
|
||||
<Box
|
||||
sx={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: readerNavBarWidth,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
top: safeAreaInset.top ? 'env(safe-area-inset-top)' : 0,
|
||||
left: `calc(${readerNavBarWidth}px - ${safeAreaInset.left ? 'env(safe-area-inset-left)' : '0px'})`,
|
||||
right: safeAreaInset.right ? 'env(safe-area-inset-right)' : 0,
|
||||
bottom: safeAreaInset.bottom ? 'env(safe-area-inset-bottom)' : 0,
|
||||
pointerEvents: 'none',
|
||||
background: `rgba(${red} ${green} ${blue} / ${alpha}%)`,
|
||||
mixBlendMode: `${blendMode}`,
|
||||
|
||||
@@ -12,6 +12,7 @@ import type {
|
||||
IReaderSettingsWithDefaultFlag,
|
||||
ProgressBarPositionAutoVertical,
|
||||
ReaderPagerProps,
|
||||
SafeAreaInset,
|
||||
} from '@/features/reader/Reader.types.ts';
|
||||
import { ProgressBarPosition, ReaderPageScaleMode, ReadingMode } from '@/features/reader/Reader.types.ts';
|
||||
import type { MangaGenreInfo, MangaSourceNameInfo } from '@/features/manga/Manga.types.ts';
|
||||
@@ -20,6 +21,7 @@ import { ReaderPagedPager } from '@/features/reader/viewer/pager/components/Read
|
||||
import { ReaderDoublePagedPager } from '@/features/reader/viewer/pager/components/ReaderDoublePagedPager.tsx';
|
||||
import { ReaderVerticalPager } from '@/features/reader/viewer/pager/components/ReaderVerticalPager.tsx';
|
||||
import { ReaderHorizontalPager } from '@/features/reader/viewer/pager/components/ReaderHorizontalPager.tsx';
|
||||
import { ScrollDirection } from '@/base/Base.types.ts';
|
||||
|
||||
export const isOffsetDoubleSpreadPagesEditable = (readingMode: IReaderSettings['readingMode']): boolean =>
|
||||
readingMode === ReadingMode.DOUBLE_PAGE;
|
||||
@@ -96,3 +98,13 @@ export const getProgressBarPosition = (
|
||||
|
||||
return ProgressBarPosition.BOTTOM;
|
||||
};
|
||||
|
||||
export const getSafeAreaInsets = (
|
||||
safeAreaInset: SafeAreaInset,
|
||||
direction: Exclude<ScrollDirection, ScrollDirection.XY>,
|
||||
): string[] => [
|
||||
...(direction === ScrollDirection.Y && safeAreaInset.top ? ['env(safe-area-inset-top)'] : []),
|
||||
...(direction === ScrollDirection.X && safeAreaInset.right ? ['env(safe-area-inset-right)'] : []),
|
||||
...(direction === ScrollDirection.Y && safeAreaInset.bottom ? ['env(safe-area-inset-bottom)'] : []),
|
||||
...(direction === ScrollDirection.X && safeAreaInset.left ? ['env(safe-area-inset-left)'] : []),
|
||||
];
|
||||
|
||||
@@ -52,6 +52,7 @@ const BaseReaderChapterViewer = ({
|
||||
retryFailedPagesKeyPrefix,
|
||||
readingMode,
|
||||
readerWidth,
|
||||
safeAreaInset,
|
||||
pageScaleMode,
|
||||
shouldOffsetDoubleSpreads,
|
||||
readingDirection,
|
||||
@@ -427,6 +428,7 @@ const BaseReaderChapterViewer = ({
|
||||
customFilter={customFilter}
|
||||
shouldStretchPage={shouldStretchPage}
|
||||
readerWidth={readerWidth}
|
||||
safeAreaInset={safeAreaInset}
|
||||
readerNavBarWidth={readerNavBarWidth}
|
||||
isPreloadMode={isPreloadMode}
|
||||
resumeMode={resumeMode}
|
||||
|
||||
@@ -108,6 +108,7 @@ const BaseReaderViewer = ({
|
||||
shouldStretchPage: state.shouldStretchPage.value,
|
||||
isStaticNav: state.isStaticNav,
|
||||
}));
|
||||
const safeAreaInset = useReaderSettingsStore('safeAreaInset');
|
||||
const { resumeMode = ReaderResumeMode.START } = useLocation<ReaderOpenChapterLocationState>().state ?? {
|
||||
resumeMode: ReaderResumeMode.START,
|
||||
};
|
||||
@@ -337,6 +338,7 @@ const BaseReaderViewer = ({
|
||||
retryFailedPagesKeyPrefix={retryFailedPagesKeyPrefix}
|
||||
readingMode={readingMode}
|
||||
readerWidth={readerWidth}
|
||||
safeAreaInset={safeAreaInset}
|
||||
pageScaleMode={pageScaleMode}
|
||||
shouldOffsetDoubleSpreads={shouldOffsetDoubleSpreads}
|
||||
readingDirection={readingDirection}
|
||||
|
||||
@@ -19,6 +19,8 @@ import { applyStyles } from '@/base/utils/ApplyStyles.ts';
|
||||
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
|
||||
import type { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||
import { useReaderScrollbarStore } from '@/features/reader/stores/ReaderStore.ts';
|
||||
import { ScrollDirection } from '@/base/Base.types.ts';
|
||||
import { getSafeAreaInsets } from '@/features/reader/settings/ReaderSettings.utils.tsx';
|
||||
|
||||
const getCustomFilterString = (customFilter: ReaderCustomFilter): string =>
|
||||
Object.keys(customFilter)
|
||||
@@ -63,6 +65,7 @@ const BaseReaderPage = ({
|
||||
pageScaleMode,
|
||||
shouldStretchPage,
|
||||
readerWidth,
|
||||
safeAreaInset,
|
||||
onLoad,
|
||||
onError,
|
||||
setRef,
|
||||
@@ -70,7 +73,10 @@ const BaseReaderPage = ({
|
||||
isLoaded,
|
||||
...props
|
||||
}: Omit<SpinnerImageProps, 'spinnerStyle' | 'imgStyle' | 'onLoad' | 'onError'> &
|
||||
Pick<IReaderSettings, 'readingMode' | 'customFilter' | 'pageScaleMode' | 'shouldStretchPage' | 'readerWidth'> &
|
||||
Pick<
|
||||
IReaderSettings,
|
||||
'readingMode' | 'customFilter' | 'pageScaleMode' | 'shouldStretchPage' | 'readerWidth' | 'safeAreaInset'
|
||||
> &
|
||||
Pick<NavbarContextType, 'readerNavBarWidth'> & {
|
||||
pageIndex: number;
|
||||
pagesIndex: number;
|
||||
@@ -115,8 +121,8 @@ const BaseReaderPage = ({
|
||||
shouldStretchPage,
|
||||
pageScaleMode,
|
||||
readerWidth,
|
||||
readerNavBarWidth + scrollbar.ySize,
|
||||
scrollbar.xSize,
|
||||
[readerNavBarWidth, scrollbar.ySize, ...getSafeAreaInsets(safeAreaInset, ScrollDirection.X)],
|
||||
[scrollbar.xSize, ...getSafeAreaInsets(safeAreaInset, ScrollDirection.Y)],
|
||||
doublePage,
|
||||
isTabletWidth,
|
||||
),
|
||||
@@ -132,8 +138,8 @@ const BaseReaderPage = ({
|
||||
pageScaleMode,
|
||||
doublePage,
|
||||
readerWidth,
|
||||
readerNavBarWidth + scrollbar.ySize,
|
||||
scrollbar.xSize,
|
||||
[readerNavBarWidth, scrollbar.ySize, ...getSafeAreaInsets(safeAreaInset, ScrollDirection.X)],
|
||||
[scrollbar.xSize, ...getSafeAreaInsets(safeAreaInset, ScrollDirection.Y)],
|
||||
),
|
||||
filter: getCustomFilterString(customFilter),
|
||||
objectFit: 'contain',
|
||||
|
||||
@@ -56,25 +56,28 @@ const getPageWidthPercentage = (
|
||||
return 1;
|
||||
};
|
||||
|
||||
const joinOffsetsForCssCalc = (offsets: (number | string)[], operator: '-' | '+' = '-'): string =>
|
||||
offsets.map((offset) => (typeof offset === 'number' ? `${offset}px` : offset)).join(` ${operator} `);
|
||||
|
||||
export const getImagePlaceholderStyling = (
|
||||
readingMode: IReaderSettings['readingMode'],
|
||||
shouldStretchPage: IReaderSettings['shouldStretchPage'],
|
||||
pageScaleMode: IReaderSettings['pageScaleMode'],
|
||||
readerWidth: IReaderSettings['readerWidth'],
|
||||
widthOffset: number,
|
||||
heightOffset: number,
|
||||
widthOffset: (number | string)[],
|
||||
heightOffset: (number | string)[],
|
||||
isDoublePage?: boolean,
|
||||
isTabletWidth?: boolean,
|
||||
): CSSObject => {
|
||||
const OVER_9000 = 9000;
|
||||
|
||||
const getMaxWidth = (width: string) => `calc(${width} - ${widthOffset}px)`;
|
||||
const getMaxWidth = (width: string) => `calc(${width} - ${joinOffsetsForCssCalc(widthOffset)})`;
|
||||
const getDesktopWidth = (width: number, readerWidthValue?: number) =>
|
||||
getMaxWidth(`${coerceIn(readerWidthValue ?? width, Math.min(width, readerWidthValue ?? OVER_9000), width)}vw`);
|
||||
|
||||
const setReaderWidth = getSetReaderWidth(readerWidth, pageScaleMode);
|
||||
const fullWidth = getMaxWidth(`${Math.min(100, setReaderWidth ?? OVER_9000)}vw`);
|
||||
const fullHeight = `calc(100vh - ${heightOffset}px)`;
|
||||
const fullHeight = `calc(100vh - ${joinOffsetsForCssCalc(heightOffset)})`;
|
||||
|
||||
const DEFAULT_SINGLE_PAGE_WIDTH = isTabletWidth ? fullWidth : getDesktopWidth(40, setReaderWidth);
|
||||
const DEFAULT_SINGLE_PAGE_HEIGHT = isTabletWidth ? fullHeight : '85vh';
|
||||
@@ -151,11 +154,11 @@ const getReaderDimensionStyling = (
|
||||
readingMode: IReaderSettings['readingMode'],
|
||||
shouldStretchPage: IReaderSettings['shouldStretchPage'],
|
||||
pageScaleMode: IReaderSettings['pageScaleMode'],
|
||||
widthOffset: number,
|
||||
heightOffset: number,
|
||||
widthOffset: (number | string)[],
|
||||
heightOffset: (number | string)[],
|
||||
): CSSObject => {
|
||||
const fullWidth = `calc((100vw - ${widthOffset}px) * ${widthPercentage})`;
|
||||
const fullHeight = `calc(100vh - ${heightOffset}px)`;
|
||||
const fullWidth = `calc((100vw - ${joinOffsetsForCssCalc(widthOffset)}) * ${widthPercentage})`;
|
||||
const fullHeight = `calc(100vh - ${joinOffsetsForCssCalc(heightOffset)})`;
|
||||
|
||||
switch (pageScaleMode) {
|
||||
case ReaderPageScaleMode.WIDTH:
|
||||
@@ -216,8 +219,8 @@ export const getReaderImageStyling = (
|
||||
pageScaleMode: IReaderSettings['pageScaleMode'],
|
||||
isDoublePage: boolean,
|
||||
readerWidth: IReaderSettings['readerWidth'],
|
||||
widthOffset: number,
|
||||
heightOffset: number,
|
||||
widthOffset: (number | string)[],
|
||||
heightOffset: (number | string)[],
|
||||
): CSSObject => {
|
||||
const widthPercentage = getPageWidthPercentage(pageScaleMode, isDoublePage, readerWidth, true);
|
||||
return getReaderDimensionStyling(
|
||||
@@ -292,6 +295,7 @@ export const createReaderPage = (
|
||||
pageScaleMode: IReaderSettings['pageScaleMode'],
|
||||
shouldStretchPage: IReaderSettings['shouldStretchPage'],
|
||||
readerWidth: IReaderSettings['readerWidth'],
|
||||
safeAreaInset: IReaderSettings['safeAreaInset'],
|
||||
readerNavBarWidth: NavbarContextType['readerNavBarWidth'],
|
||||
retryKeyPrefix?: string,
|
||||
position?: 'left' | 'right',
|
||||
@@ -322,6 +326,7 @@ export const createReaderPage = (
|
||||
pageScaleMode={pageScaleMode}
|
||||
shouldStretchPage={shouldStretchPage}
|
||||
readerWidth={readerWidth}
|
||||
safeAreaInset={safeAreaInset}
|
||||
readerNavBarWidth={readerNavBarWidth}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -35,6 +35,7 @@ const BaseBasePager = ({
|
||||
pageScaleMode,
|
||||
shouldStretchPage,
|
||||
readerWidth,
|
||||
safeAreaInset,
|
||||
readerNavBarWidth,
|
||||
resumeMode,
|
||||
handleAsInitialRender,
|
||||
@@ -52,6 +53,7 @@ const BaseBasePager = ({
|
||||
pageScaleMode: ReaderPagerProps['pageScaleMode'],
|
||||
shouldStretchPage: ReaderPagerProps['shouldStretchPage'],
|
||||
readerWidth: ReaderPagerProps['readerWidth'],
|
||||
safeAreaInset: ReaderPagerProps['safeAreaInset'],
|
||||
readerNavBarWidth: ReaderPagerProps['readerNavBarWidth'],
|
||||
) => ReactNode;
|
||||
slots?: { boxProps?: BoxProps };
|
||||
@@ -125,6 +127,7 @@ const BaseBasePager = ({
|
||||
pageScaleMode,
|
||||
shouldStretchPage,
|
||||
readerWidth,
|
||||
safeAreaInset,
|
||||
readerNavBarWidth,
|
||||
),
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user