Fix infinite scroll intersection info calculation

Scrollbars need to be considered since they decrease the available viewport size in which the element can be visible
This commit is contained in:
schroda
2025-02-10 22:27:28 +01:00
parent eb7397e639
commit a45338647e
3 changed files with 24 additions and 5 deletions

View File

@@ -416,6 +416,8 @@ const BaseReaderChapterViewer = ({
isPreviousChapterVisible={isPreviousChapterVisible} isPreviousChapterVisible={isPreviousChapterVisible}
isNextChapterVisible={isNextChapterVisible} isNextChapterVisible={isNextChapterVisible}
imageWrapper={pagerRef.current} imageWrapper={pagerRef.current}
scrollbarXSize={scrollbarXSize}
scrollbarYSize={scrollbarYSize}
/> />
)} )}
{showPreviousTransitionPage && ( {showPreviousTransitionPage && (

View File

@@ -9,7 +9,7 @@
import { memo } from 'react'; import { memo } from 'react';
import { withPropsFrom } from '@/modules/core/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/modules/core/hoc/withPropsFrom.tsx';
import { useReaderInfiniteScrollUpdateChapter } from '@/modules/reader/hooks/useReaderInfiniteScrollUpdateChapter.ts'; import { useReaderInfiniteScrollUpdateChapter } from '@/modules/reader/hooks/useReaderInfiniteScrollUpdateChapter.ts';
import { ReadingDirection, ReadingMode } from '@/modules/reader/types/Reader.types.ts'; import { ReadingDirection, ReadingMode, TReaderScrollbarContext } from '@/modules/reader/types/Reader.types.ts';
import { ReaderControls } from '@/modules/reader/services/ReaderControls.ts'; import { ReaderControls } from '@/modules/reader/services/ReaderControls.ts';
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts'; import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
@@ -24,7 +24,9 @@ const BaseReaderInfiniteScrollUpdateChapter = ({
isNextChapterVisible, isNextChapterVisible,
imageWrapper, imageWrapper,
openChapter, openChapter,
}: { scrollbarXSize,
scrollbarYSize,
}: Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> & {
readingMode: ReadingMode; readingMode: ReadingMode;
readingDirection: ReadingDirection; readingDirection: ReadingDirection;
chapterId: ChapterIdInfo['id']; chapterId: ChapterIdInfo['id'];
@@ -46,6 +48,8 @@ const BaseReaderInfiniteScrollUpdateChapter = ({
readingDirection, readingDirection,
openChapter, openChapter,
imageWrapper, imageWrapper,
scrollbarXSize,
scrollbarYSize,
); );
useReaderInfiniteScrollUpdateChapter( useReaderInfiniteScrollUpdateChapter(
'last', 'last',
@@ -57,6 +61,8 @@ const BaseReaderInfiniteScrollUpdateChapter = ({
readingDirection, readingDirection,
openChapter, openChapter,
imageWrapper, imageWrapper,
scrollbarXSize,
scrollbarYSize,
); );
return null; return null;

View File

@@ -36,18 +36,23 @@ const OPEN_CHAPTER_INTERSECTION_RATIO = 0;
const getElementIntersectionInfo = ( const getElementIntersectionInfo = (
readingDirection: ReadingDirection, readingDirection: ReadingDirection,
{ top, right, bottom, left }: DOMRect, { top, right, bottom, left }: DOMRect,
scrollbarXSize: number,
scrollbarYSize: number,
): ElementIntersectionInfo => { ): ElementIntersectionInfo => {
const themeDirectionOfReadingDirection = READING_DIRECTION_TO_THEME_DIRECTION[readingDirection]; const themeDirectionOfReadingDirection = READING_DIRECTION_TO_THEME_DIRECTION[readingDirection];
const startOfViewportHorizontal = getOptionForDirection(0, window.innerWidth, themeDirectionOfReadingDirection); const viewportWidth = window.innerWidth - scrollbarYSize;
const endOfViewportHorizontal = getOptionForDirection(window.innerWidth, 0, themeDirectionOfReadingDirection); const viewportHeight = window.innerHeight - scrollbarXSize;
const startOfViewportHorizontal = getOptionForDirection(0, viewportWidth, themeDirectionOfReadingDirection);
const endOfViewportHorizontal = getOptionForDirection(viewportWidth, 0, themeDirectionOfReadingDirection);
const startOfElementHorizontal = getOptionForDirection(left, right, themeDirectionOfReadingDirection); const startOfElementHorizontal = getOptionForDirection(left, right, themeDirectionOfReadingDirection);
const endOfElementHorizontal = getOptionForDirection(right, left, themeDirectionOfReadingDirection); const endOfElementHorizontal = getOptionForDirection(right, left, themeDirectionOfReadingDirection);
return { return {
[ReadingMode.CONTINUOUS_VERTICAL]: { [ReadingMode.CONTINUOUS_VERTICAL]: {
start: bottom >= window.innerHeight, start: bottom >= viewportHeight,
end: top < 0, end: top < 0,
}, },
[ReadingMode.CONTINUOUS_HORIZONTAL]: { [ReadingMode.CONTINUOUS_HORIZONTAL]: {
@@ -188,6 +193,8 @@ export const useReaderInfiniteScrollUpdateChapter = (
readingDirection: ReadingDirection, readingDirection: ReadingDirection,
openChapter: ReturnType<typeof ReaderControls.useOpenChapter>, openChapter: ReturnType<typeof ReaderControls.useOpenChapter>,
image: HTMLElement | null, image: HTMLElement | null,
scrollbarXSize: number,
scrollbarYSize: number,
) => { ) => {
useIntersectionObserver( useIntersectionObserver(
image, image,
@@ -202,6 +209,8 @@ export const useReaderInfiniteScrollUpdateChapter = (
const elementIntersectionInfo = getElementIntersectionInfo( const elementIntersectionInfo = getElementIntersectionInfo(
readingDirection, readingDirection,
entry.target.getBoundingClientRect(), entry.target.getBoundingClientRect(),
scrollbarXSize,
scrollbarYSize,
); );
const { start: isStartIntersecting, end: isEndIntersecting } = getElementIntersection( const { start: isStartIntersecting, end: isEndIntersecting } = getElementIntersection(
elementIntersectionInfo, elementIntersectionInfo,
@@ -239,6 +248,8 @@ export const useReaderInfiniteScrollUpdateChapter = (
readingMode, readingMode,
readingDirection, readingDirection,
openChapter, openChapter,
scrollbarXSize,
scrollbarYSize,
], ],
), ),
useMemo( useMemo(