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

View File

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

View File

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

View File

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

View File

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

View File

@@ -19,6 +19,7 @@ import {
} from '@/modules/reader/types/Reader.types.ts'; } from '@/modules/reader/types/Reader.types.ts';
import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts'; import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
import { import {
getSetReaderWidth,
isContinuousReadingMode, isContinuousReadingMode,
isContinuousVerticalReadingMode, isContinuousVerticalReadingMode,
shouldApplyReaderWidth, shouldApplyReaderWidth,
@@ -31,6 +32,7 @@ import { getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
import { DirectionOffset } from '@/Base.types.ts'; import { DirectionOffset } from '@/Base.types.ts';
import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts'; import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
import { READING_DIRECTION_TO_THEME_DIRECTION } from '@/modules/reader/constants/ReaderSettings.constants.tsx'; import { READING_DIRECTION_TO_THEME_DIRECTION } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
import { coerceIn } from '@/lib/HelperFunctions.ts';
type CSSObject = ReturnType<Theme['applyStyles']>; type CSSObject = ReturnType<Theme['applyStyles']>;
@@ -61,53 +63,69 @@ export const getImagePlaceholderStyling = (
shouldStretchPage: IReaderSettings['shouldStretchPage'], shouldStretchPage: IReaderSettings['shouldStretchPage'],
pageScaleMode: IReaderSettings['pageScaleMode'], pageScaleMode: IReaderSettings['pageScaleMode'],
readerWidth: IReaderSettings['readerWidth'], readerWidth: IReaderSettings['readerWidth'],
scrollbarXSize: number, widthOffset: number,
scrollbarYSize: number, heightOffset: number,
isDoublePage?: boolean, isDoublePage?: boolean,
isTabletWidth?: boolean, isTabletWidth?: boolean,
): CSSObject => { ): CSSObject => {
const DEFAULT_SINGLE_PAGE_WIDTH = isTabletWidth ? '100vw' : '40vw'; const OVER_9000 = 9000;
const DEFAULT_SINGLE_PAGE_HEIGHT = isTabletWidth ? '100vh' : '85vh';
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 }> = { 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.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]: { [ReadingMode.CONTINUOUS_VERTICAL]: {
minWidth: `calc(${DEFAULT_SINGLE_PAGE_WIDTH} - ${scrollbarYSize}px)`, minWidth: DEFAULT_SINGLE_PAGE_WIDTH,
minHeight: '100vh', minHeight: '100vh',
}, },
[ReadingMode.CONTINUOUS_HORIZONTAL]: { [ReadingMode.CONTINUOUS_HORIZONTAL]: {
minWidth: DEFAULT_SINGLE_PAGE_WIDTH, minWidth: DEFAULT_SINGLE_PAGE_WIDTH,
minHeight: `calc(${DEFAULT_SINGLE_PAGE_HEIGHT} - ${scrollbarXSize}px)`, minHeight: DEFAULT_SINGLE_PAGE_HEIGHT,
}, },
[ReadingMode.WEBTOON]: { [ReadingMode.WEBTOON]: {
minWidth: `calc(${DEFAULT_SINGLE_PAGE_WIDTH} - ${scrollbarYSize}px)`, minWidth: DEFAULT_SINGLE_PAGE_WIDTH,
minHeight: '100vh', minHeight: '100vh',
}, },
}; };
const defaultStyling = READING_MODE_TO_PLACEHOLDER_SIZE[readingMode]; const defaultStyling = {
const minWidthForStretch = isDoublePage ? '50%' : '100%'; ...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) { switch (pageScaleMode) {
case ReaderPageScaleMode.WIDTH: case ReaderPageScaleMode.WIDTH:
return { return {
...defaultStyling, ...defaultStyling,
...applyStyles(shouldApplyReaderWidth(readerWidth, pageScaleMode), {
minWidth: minWidthForStretch,
}),
...applyStyles(shouldStretchPage, { ...applyStyles(shouldStretchPage, {
minWidth: minWidthForStretch, 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: case ReaderPageScaleMode.HEIGHT:
return { return {
...defaultStyling, ...defaultStyling,
...applyStyles(shouldStretchPage, { ...applyStyles(shouldStretchPage, {
minHeight: `calc(100vh - ${scrollbarXSize}px)`, minHeight: fullHeight,
...applyStyles(isContinuousVerticalReadingMode(readingMode), { ...applyStyles(isContinuousVerticalReadingMode(readingMode), {
minHeight: '100vh', minHeight: '100vh',
}), }),
@@ -116,12 +134,9 @@ export const getImagePlaceholderStyling = (
case ReaderPageScaleMode.SCREEN: case ReaderPageScaleMode.SCREEN:
return { return {
...defaultStyling, ...defaultStyling,
...applyStyles(shouldApplyReaderWidth(readerWidth, pageScaleMode), {
minWidth: minWidthForStretch,
}),
...applyStyles(shouldStretchPage, { ...applyStyles(shouldStretchPage, {
minWidth: minWidthForStretch, minWidth: minWidthForStretch,
minHeight: `calc(100vh - ${scrollbarXSize}px)`, minHeight: fullHeight,
...applyStyles(isContinuousVerticalReadingMode(readingMode), { ...applyStyles(isContinuousVerticalReadingMode(readingMode), {
minHeight: '100vh', minHeight: '100vh',
}), }),
@@ -264,6 +279,7 @@ export const createReaderPage = (
{ primary: { index, alt, url } }: ReaderStatePages['pages'][number], { primary: { index, alt, url } }: ReaderStatePages['pages'][number],
pagesIndex: number, pagesIndex: number,
isPrimaryPage: boolean, isPrimaryPage: boolean,
isLoaded: boolean,
onLoad: ComponentProps<typeof ReaderPage>['onLoad'], onLoad: ComponentProps<typeof ReaderPage>['onLoad'],
onError: ComponentProps<typeof ReaderPage>['onError'], onError: ComponentProps<typeof ReaderPage>['onError'],
shouldLoad: boolean, shouldLoad: boolean,
@@ -293,6 +309,7 @@ export const createReaderPage = (
shouldLoad={shouldLoad} shouldLoad={shouldLoad}
retryKeyPrefix={retryKeyPrefix} retryKeyPrefix={retryKeyPrefix}
marginTop={marginTop} marginTop={marginTop}
isLoaded={isLoaded}
/> />
); );

View File

@@ -34,6 +34,17 @@ export const shouldApplyReaderWidth = (
pageScaleMode: IReaderSettings['pageScaleMode'], pageScaleMode: IReaderSettings['pageScaleMode'],
): boolean => !!readerWidth?.enabled && isReaderWidthEditable(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 => export const isContinuousReadingMode = (readingMode: IReaderSettings['readingMode']): boolean =>
[ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.CONTINUOUS_HORIZONTAL, ReadingMode.WEBTOON].includes(readingMode); [ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.CONTINUOUS_HORIZONTAL, ReadingMode.WEBTOON].includes(readingMode);