@@ -528,19 +528,25 @@ class ReaderControlsClass {
|
|||||||
(image) =>
|
(image) =>
|
||||||
image &&
|
image &&
|
||||||
isPageInViewport(image, type, {
|
isPageInViewport(image, type, {
|
||||||
thresholds: {
|
bounds: {
|
||||||
bottom: 1,
|
bottom: {
|
||||||
left: getOptionForDirection(
|
min: 1,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
min: getOptionForDirection(
|
||||||
0,
|
0,
|
||||||
pageHorizontalEndInViewportThreshold,
|
pageHorizontalEndInViewportThreshold,
|
||||||
themeDirectionOfReadingDirection,
|
themeDirectionOfReadingDirection,
|
||||||
),
|
),
|
||||||
right: getOptionForDirection(
|
},
|
||||||
|
right: {
|
||||||
|
min: getOptionForDirection(
|
||||||
pageHorizontalEndInViewportThreshold,
|
pageHorizontalEndInViewportThreshold,
|
||||||
0,
|
0,
|
||||||
themeDirectionOfReadingDirection,
|
themeDirectionOfReadingDirection,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const lastPage = imageRefs.current?.[imageRefs.current.length - 1];
|
const lastPage = imageRefs.current?.[imageRefs.current.length - 1];
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts
|
|||||||
import { READING_DIRECTION_TO_THEME_DIRECTION } from '@/features/reader/settings/ReaderSettings.constants.tsx';
|
import { READING_DIRECTION_TO_THEME_DIRECTION } from '@/features/reader/settings/ReaderSettings.constants.tsx';
|
||||||
import { coerceIn } from '@/lib/HelperFunctions.ts';
|
import { coerceIn } from '@/lib/HelperFunctions.ts';
|
||||||
import type { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
|
import type { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||||
|
import merge from 'lodash/fp/merge';
|
||||||
|
|
||||||
type CSSObject = ReturnType<Theme['applyStyles']>;
|
type CSSObject = ReturnType<Theme['applyStyles']>;
|
||||||
|
|
||||||
@@ -331,11 +332,17 @@ export const createReaderPage = (
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
type InViewportThresholds = {
|
type InViewportBound = {
|
||||||
top?: number;
|
min?: number;
|
||||||
bottom?: number;
|
max?: number;
|
||||||
left?: number;
|
threshold?: number;
|
||||||
right?: number;
|
};
|
||||||
|
|
||||||
|
type InViewportBounds = {
|
||||||
|
top?: InViewportBound;
|
||||||
|
bottom?: InViewportBound;
|
||||||
|
left?: InViewportBound;
|
||||||
|
right?: InViewportBound;
|
||||||
};
|
};
|
||||||
type InViewportOptions = {
|
type InViewportOptions = {
|
||||||
/**
|
/**
|
||||||
@@ -344,14 +351,14 @@ type InViewportOptions = {
|
|||||||
*/
|
*/
|
||||||
truncateValues?: boolean;
|
truncateValues?: boolean;
|
||||||
/**
|
/**
|
||||||
* Thresholds are not considered for the detection of an image filling the whole viewport.
|
* Bounds are not considered for the detection of an image filling the whole viewport.
|
||||||
* They are only used for detecting if a specific side of an image is inside the viewport
|
* They are only used for detecting if a specific side of an image is inside the viewport
|
||||||
*/
|
*/
|
||||||
thresholds?: InViewportThresholds;
|
bounds?: InViewportBounds;
|
||||||
};
|
};
|
||||||
const getIsPageInViewportInfo = (
|
const getIsPageInViewportInfo = (
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
{ truncateValues, thresholds: argThresholds }: InViewportOptions = { truncateValues: true, thresholds: {} },
|
{ truncateValues, bounds: argBounds }: InViewportOptions = { truncateValues: true, bounds: {} },
|
||||||
): {
|
): {
|
||||||
isLeftInViewport: boolean;
|
isLeftInViewport: boolean;
|
||||||
isRightInViewport: boolean;
|
isRightInViewport: boolean;
|
||||||
@@ -368,20 +375,27 @@ const getIsPageInViewportInfo = (
|
|||||||
const left = maybeTruncateValue(leftRaw);
|
const left = maybeTruncateValue(leftRaw);
|
||||||
const right = maybeTruncateValue(rightRaw);
|
const right = maybeTruncateValue(rightRaw);
|
||||||
|
|
||||||
const thresholds = {
|
const THRESHOLD = 1;
|
||||||
top: 0,
|
const bounds = merge(
|
||||||
bottom: 0,
|
{
|
||||||
left: 0,
|
top: { min: 0, max: window.innerHeight + THRESHOLD, threshold: THRESHOLD },
|
||||||
right: 0,
|
bottom: { min: 0, max: window.innerHeight + THRESHOLD, threshold: THRESHOLD },
|
||||||
...argThresholds,
|
left: { min: 0, max: window.innerWidth + THRESHOLD, threshold: THRESHOLD },
|
||||||
};
|
right: { min: 0, max: window.innerWidth + THRESHOLD, threshold: THRESHOLD },
|
||||||
|
} satisfies InViewportBounds,
|
||||||
|
argBounds,
|
||||||
|
);
|
||||||
|
|
||||||
const isLeftInViewport = left >= thresholds.left && left <= window.innerWidth;
|
// oxlint-disable-next-line unicorn/consistent-function-scoping
|
||||||
const isRightInViewport = right >= thresholds.right && right <= window.innerWidth;
|
const meetsBounds = (value: number, viewportValue: number, { min, max, threshold }: Required<InViewportBound>) =>
|
||||||
|
value >= min && value <= max && value <= viewportValue + threshold;
|
||||||
|
|
||||||
|
const isLeftInViewport = meetsBounds(left, window.innerWidth, bounds.left);
|
||||||
|
const isRightInViewport = meetsBounds(right, window.innerWidth, bounds.right);
|
||||||
const isFillingWidthViewportCompletely = left <= 0 && right >= window.innerWidth;
|
const isFillingWidthViewportCompletely = left <= 0 && right >= window.innerWidth;
|
||||||
|
|
||||||
const isTopInViewport = top >= thresholds.top && top <= window.innerHeight;
|
const isTopInViewport = meetsBounds(top, window.innerHeight, bounds.top);
|
||||||
const isBottomInViewport = bottom >= thresholds.bottom && bottom <= window.innerHeight;
|
const isBottomInViewport = meetsBounds(bottom, window.innerHeight, bounds.bottom);
|
||||||
const isFillingHeightViewportCompletely = top <= 0 && bottom >= window.innerHeight;
|
const isFillingHeightViewportCompletely = top <= 0 && bottom >= window.innerHeight;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user