From 9ab6ec89c7c0f7d346190a7ad6fd27efcd898ca1 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Tue, 31 Dec 2024 04:01:42 +0100 Subject: [PATCH] Fix page resume in continuous pagers The image refs weren't always set by the time the last read page got resumed. Thus, the last read page never got scrolled into view --- src/modules/reader/utils/Reader.utils.ts | 62 ++++++++++++++---------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/modules/reader/utils/Reader.utils.ts b/src/modules/reader/utils/Reader.utils.ts index 7ad7f012..5701875a 100644 --- a/src/modules/reader/utils/Reader.utils.ts +++ b/src/modules/reader/utils/Reader.utils.ts @@ -6,7 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { MutableRefObject, useEffect, useLayoutEffect, useRef, useState } from 'react'; +import { MutableRefObject, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { Direction } from '@mui/material/styles'; import { ReaderPageSpreadState, @@ -33,6 +33,7 @@ import { ReaderStatePages } from '@/modules/reader/types/ReaderProgressBar.types import { ReaderControls } from '@/modules/reader/services/ReaderControls.ts'; import { coerceIn } from '@/lib/HelperFunctions.ts'; import { TReaderTapZoneContext } from '@/modules/reader/types/TapZoneLayout.types.ts'; +import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx'; export const getInitialReaderPageIndex = ( resumeMode: ReaderResumeMode, @@ -231,37 +232,46 @@ export const useReaderHandlePageSelection = ( readingDirection: ReadingDirection, scrollElementRef: MutableRefObject, ) => { - useLayoutEffect(() => { - if (pageToScrollToIndex == null) { - return; - } + const pageToScrollTo = useMemo(() => getPage(pageToScrollToIndex ?? 0, pages), [pageToScrollToIndex, pages]); - const pageToScrollTo = getPage(pageToScrollToIndex, pages); + const imageRef = imageRefs.current[pageToScrollTo.pagesIndex]; + const ref = isContinuousReadingModeActive ? imageRef : scrollElementRef; - if (isContinuousReadingModeActive) { - const directionOffset = - pageToScrollToIndex > currentPageIndex ? DirectionOffset.PREVIOUS : DirectionOffset.NEXT; - const imageRef = imageRefs.current[pageToScrollTo.pagesIndex]; + useResizeObserver( + ref, + useCallback( + (entries, observer) => { + if (pageToScrollToIndex == null) { + return; + } - imageRef?.scrollIntoView({ - block: 'start', - inline: getScrollIntoViewInlineOption(directionOffset, themeDirection, readingDirection), - }); - } + const element = entries[0].target as HTMLElement; - if (!isContinuousReadingModeActive) { - scrollElementRef.current?.scrollTo( - getScrollToXForReadingDirection(scrollElementRef.current, themeDirection, readingDirection), - 0, - ); - } + if (isContinuousReadingModeActive) { + const directionOffset = + pageToScrollToIndex > currentPageIndex ? DirectionOffset.PREVIOUS : DirectionOffset.NEXT; - const newPageIndex = getNextIndexFromPage(pageToScrollTo); - const isLastPage = newPageIndex === totalPages - 1; + element.scrollIntoView({ + block: 'start', + inline: getScrollIntoViewInlineOption(directionOffset, themeDirection, readingDirection), + }); + } - setPageToScrollToIndex(null); - updateCurrentPageIndex(newPageIndex, !isLastPage); - }, [pageToScrollToIndex]); + if (!isContinuousReadingModeActive) { + element.scrollTo(getScrollToXForReadingDirection(element, themeDirection, readingDirection), 0); + } + + const newPageIndex = getNextIndexFromPage(pageToScrollTo); + const isLastPage = newPageIndex === totalPages - 1; + + setPageToScrollToIndex(null); + updateCurrentPageIndex(newPageIndex, !isLastPage); + + observer.disconnect(); + }, + [pageToScrollToIndex], + ), + ); }; export const useReaderHideCursorOnInactivity = (scrollElementRef: MutableRefObject) => {