Convert reader image placeholder styling to vw/vh

This commit is contained in:
schroda
2025-01-20 01:29:04 +01:00
parent 7fad96dab7
commit db7aad58ec
7 changed files with 65 additions and 27 deletions

View File

@@ -76,6 +76,7 @@ const BaseReaderPage = ({
onError,
setRef,
readerNavBarWidth,
isLoaded,
...props
}: Omit<ComponentProps<typeof SpinnerImage>, 'ref' | 'spinnerStyle' | 'imgStyle' | 'onLoad' | 'onError'> &
Pick<IReaderSettings, 'readingMode' | 'customFilter' | 'pageScaleMode' | 'shouldStretchPage' | 'readerWidth'> &
@@ -91,6 +92,7 @@ const BaseReaderPage = ({
onLoad: ReaderPagerProps['onLoad'];
onError: ReaderPagerProps['onError'];
setRef?: (pagesIndex: number, ref: HTMLElement | null) => void;
isLoaded?: boolean;
}) => {
const { src } = props;
@@ -122,8 +124,8 @@ const BaseReaderPage = ({
shouldStretchPage,
pageScaleMode,
readerWidth,
readerNavBarWidth + scrollbarYSize,
scrollbarXSize,
scrollbarYSize,
doublePage,
isTabletWidth,
),
@@ -142,10 +144,6 @@ const BaseReaderPage = ({
readerNavBarWidth + scrollbarYSize,
scrollbarXSize,
),
display: 'block',
...applyStyles(!display, {
display: 'none',
}),
filter: getCustomFilterString(customFilter),
objectFit: 'contain',
objectPosition: position,
@@ -154,6 +152,13 @@ const BaseReaderPage = ({
...applyStyles(marginTop !== undefined, {
mt: `${marginTop}px`,
}),
display: 'block',
...applyStyles(!display, {
display: 'none',
}),
...applyStyles(!isLoaded, {
margin: 'unset',
}),
}}
hideImgStyle={{
visibility: 'hidden',

View File

@@ -77,6 +77,7 @@ const BaseReaderDoublePagedPager = ({
page,
pagesIndex,
true,
pageLoadStates[primary.index].loaded,
onLoad,
onError,
shouldLoad,
@@ -92,6 +93,7 @@ const BaseReaderDoublePagedPager = ({
{ ...page, primary: { ...page.secondary! } },
pagesIndex,
false,
pageLoadStates[secondary.index].loaded,
onLoad,
onError,
shouldLoad,

View File

@@ -38,6 +38,7 @@ const BaseReaderHorizontalPager = ({
page,
pagesIndex,
true,
pageLoadStates[page.primary.index].loaded,
onLoad,
onError,
shouldLoad,

View File

@@ -29,6 +29,7 @@ const BaseReaderPagedPager = ({
page,
pagesIndex,
true,
pageLoadStates[page.primary.index].loaded,
onLoad,
onError,
shouldLoad,

View File

@@ -35,6 +35,7 @@ const BaseReaderVerticalPager = ({
page,
pagesIndex,
true,
pageLoadStates[page.primary.index].loaded,
onLoad,
onError,
shouldLoad,

View File

@@ -19,6 +19,7 @@ import {
} from '@/modules/reader/types/Reader.types.ts';
import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
import {
getSetReaderWidth,
isContinuousReadingMode,
isContinuousVerticalReadingMode,
shouldApplyReaderWidth,
@@ -31,6 +32,7 @@ import { getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
import { DirectionOffset } from '@/Base.types.ts';
import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
import { READING_DIRECTION_TO_THEME_DIRECTION } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
import { coerceIn } from '@/lib/HelperFunctions.ts';
type CSSObject = ReturnType<Theme['applyStyles']>;
@@ -61,53 +63,69 @@ export const getImagePlaceholderStyling = (
shouldStretchPage: IReaderSettings['shouldStretchPage'],
pageScaleMode: IReaderSettings['pageScaleMode'],
readerWidth: IReaderSettings['readerWidth'],
scrollbarXSize: number,
scrollbarYSize: number,
widthOffset: number,
heightOffset: number,
isDoublePage?: boolean,
isTabletWidth?: boolean,
): CSSObject => {
const DEFAULT_SINGLE_PAGE_WIDTH = isTabletWidth ? '100vw' : '40vw';
const DEFAULT_SINGLE_PAGE_HEIGHT = isTabletWidth ? '100vh' : '85vh';
const OVER_9000 = 9000;
const getMaxWidth = (width: string) => {
if (width === '100vw') {
return `calc(${width} - ${widthOffset}px)`;
}
return width;
};
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 DEFAULT_SINGLE_PAGE_WIDTH = isTabletWidth ? fullWidth : getDesktopWidth(40, setReaderWidth);
const DEFAULT_SINGLE_PAGE_HEIGHT = isTabletWidth ? fullHeight : '85vh';
const READING_MODE_TO_PLACEHOLDER_SIZE: Record<ReadingMode, { minWidth: string; minHeight: string }> = {
[ReadingMode.SINGLE_PAGE]: { minWidth: DEFAULT_SINGLE_PAGE_WIDTH, minHeight: DEFAULT_SINGLE_PAGE_HEIGHT },
[ReadingMode.DOUBLE_PAGE]: { minWidth: isTabletWidth ? '50vw' : '35vw', minHeight: DEFAULT_SINGLE_PAGE_HEIGHT },
[ReadingMode.DOUBLE_PAGE]: {
minWidth: isTabletWidth ? '50vw' : getDesktopWidth(35, setReaderWidth ? setReaderWidth / 2 : undefined),
minHeight: DEFAULT_SINGLE_PAGE_HEIGHT,
},
[ReadingMode.CONTINUOUS_VERTICAL]: {
minWidth: `calc(${DEFAULT_SINGLE_PAGE_WIDTH} - ${scrollbarYSize}px)`,
minWidth: DEFAULT_SINGLE_PAGE_WIDTH,
minHeight: '100vh',
},
[ReadingMode.CONTINUOUS_HORIZONTAL]: {
minWidth: DEFAULT_SINGLE_PAGE_WIDTH,
minHeight: `calc(${DEFAULT_SINGLE_PAGE_HEIGHT} - ${scrollbarXSize}px)`,
minHeight: DEFAULT_SINGLE_PAGE_HEIGHT,
},
[ReadingMode.WEBTOON]: {
minWidth: `calc(${DEFAULT_SINGLE_PAGE_WIDTH} - ${scrollbarYSize}px)`,
minWidth: DEFAULT_SINGLE_PAGE_WIDTH,
minHeight: '100vh',
},
};
const defaultStyling = READING_MODE_TO_PLACEHOLDER_SIZE[readingMode];
const minWidthForStretch = isDoublePage ? '50%' : '100%';
const defaultStyling = {
...READING_MODE_TO_PLACEHOLDER_SIZE[readingMode],
// the SpinnerImage placeholder has a default height of 100%, this causes the placeholder to take always take up 100% of the viewport
height: 'unset',
};
const minWidthForStretch = isDoublePage ? `calc(${getMaxWidth(`${setReaderWidth ?? 100}vw`)} / 2)` : fullWidth;
switch (pageScaleMode) {
case ReaderPageScaleMode.WIDTH:
return {
...defaultStyling,
...applyStyles(shouldApplyReaderWidth(readerWidth, pageScaleMode), {
minWidth: minWidthForStretch,
}),
...applyStyles(shouldStretchPage, {
minWidth: minWidthForStretch,
}),
// the SpinnerImage placeholder has a default height of 100%, this caused the placeholder due take up 100% of the readers full scrollable height instead of only 100% of the viewport
...applyStyles(isContinuousVerticalReadingMode(readingMode), {
height: 'unset',
}),
};
case ReaderPageScaleMode.HEIGHT:
return {
...defaultStyling,
...applyStyles(shouldStretchPage, {
minHeight: `calc(100vh - ${scrollbarXSize}px)`,
minHeight: fullHeight,
...applyStyles(isContinuousVerticalReadingMode(readingMode), {
minHeight: '100vh',
}),
@@ -116,12 +134,9 @@ export const getImagePlaceholderStyling = (
case ReaderPageScaleMode.SCREEN:
return {
...defaultStyling,
...applyStyles(shouldApplyReaderWidth(readerWidth, pageScaleMode), {
minWidth: minWidthForStretch,
}),
...applyStyles(shouldStretchPage, {
minWidth: minWidthForStretch,
minHeight: `calc(100vh - ${scrollbarXSize}px)`,
minHeight: fullHeight,
...applyStyles(isContinuousVerticalReadingMode(readingMode), {
minHeight: '100vh',
}),
@@ -264,6 +279,7 @@ export const createReaderPage = (
{ primary: { index, alt, url } }: ReaderStatePages['pages'][number],
pagesIndex: number,
isPrimaryPage: boolean,
isLoaded: boolean,
onLoad: ComponentProps<typeof ReaderPage>['onLoad'],
onError: ComponentProps<typeof ReaderPage>['onError'],
shouldLoad: boolean,
@@ -293,6 +309,7 @@ export const createReaderPage = (
shouldLoad={shouldLoad}
retryKeyPrefix={retryKeyPrefix}
marginTop={marginTop}
isLoaded={isLoaded}
/>
);

View File

@@ -34,6 +34,17 @@ export const shouldApplyReaderWidth = (
pageScaleMode: IReaderSettings['pageScaleMode'],
): boolean => !!readerWidth?.enabled && isReaderWidthEditable(pageScaleMode);
export const getSetReaderWidth = (
readerWidth: IReaderSettings['readerWidth'] | undefined,
pageScaleMode: IReaderSettings['pageScaleMode'],
): number | undefined => {
if (!shouldApplyReaderWidth(readerWidth, pageScaleMode)) {
return undefined;
}
return readerWidth?.value;
};
export const isContinuousReadingMode = (readingMode: IReaderSettings['readingMode']): boolean =>
[ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.CONTINUOUS_HORIZONTAL, ReadingMode.WEBTOON].includes(readingMode);