diff --git a/src/modules/reader/components/viewer/ReaderChapterViewer.tsx b/src/modules/reader/components/viewer/ReaderChapterViewer.tsx index 01a21070..9c8bbdf5 100644 --- a/src/modules/reader/components/viewer/ReaderChapterViewer.tsx +++ b/src/modules/reader/components/viewer/ReaderChapterViewer.tsx @@ -125,7 +125,7 @@ const BaseReaderChapterViewer = ({ imageRefs: MutableRefObject<(HTMLElement | null)[]>; scrollIntoView: boolean; resumeMode: ReaderResumeMode; - onSizeChange: (width: number, height: number) => void; + onSizeChange: (width: number, height: number, chapterId: ChapterIdInfo['id']) => void; minWidth: number; minHeight: number; }) => { @@ -243,9 +243,9 @@ const BaseReaderChapterViewer = ({ useCallback( (entries) => { const { clientWidth, clientHeight } = entries[0].target; - onSizeChange(clientWidth, clientHeight); + onSizeChange(clientWidth, clientHeight, chapterId); }, - [onSizeChange, ref.current], + [onSizeChange, ref.current, chapterId], ), ); @@ -376,14 +376,14 @@ const BaseReaderChapterViewer = ({ sx={{ width: 'fit-content', height: 'fit-content', + margin: 'auto', + flexWrap: 'nowrap', ...applyStyles(readingMode === ReadingMode.CONTINUOUS_HORIZONTAL, { minHeight, }), ...applyStyles(isContinuousVerticalReadingMode(readingMode), { minWidth, }), - margin: 'auto', - flexWrap: 'nowrap', ...applyStyles(shouldHideChapter, { maxWidth: 0, maxHeight: 0, diff --git a/src/modules/reader/components/viewer/ReaderViewer.tsx b/src/modules/reader/components/viewer/ReaderViewer.tsx index 042a5d90..9dae69a0 100644 --- a/src/modules/reader/components/viewer/ReaderViewer.tsx +++ b/src/modules/reader/components/viewer/ReaderViewer.tsx @@ -67,6 +67,7 @@ import { coerceIn, noOp } from '@/lib/HelperFunctions.ts'; import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx'; import { NavbarContextType } from '@/modules/navigation-bar/NavigationBar.types.ts'; import { useReaderPreserveScrollPosition } from '@/modules/reader/hooks/useReaderPreserveScrollPosition.ts'; +import { ChapterIdInfo } from '@/modules/chapter/services/Chapters'; const READING_MODE_TO_IN_VIEWPORT_TYPE: Record = { [ReadingMode.SINGLE_PAGE]: PageInViewportType.X, @@ -184,8 +185,12 @@ const BaseReaderViewer = forwardRef( const handleClick = ReaderControls.useHandleClick(scrollElementRef.current); const imageRefs = useRef<(HTMLElement | null)[]>(pages.map(() => null)); - const chapterViewerSize = useRef({ minChapterViewWidth: 0, minChapterViewHeight: 0 }); - const { minChapterViewWidth, minChapterViewHeight } = chapterViewerSize.current; + const [{ minChapterViewWidth, minChapterViewHeight, minChapterSizeSourceChapterId }, setChapterViewerSize] = + useState({ + minChapterViewWidth: 0, + minChapterViewHeight: 0, + minChapterSizeSourceChapterId: -1, + }); const [, setTriggerReRender] = useState({}); @@ -209,22 +214,41 @@ const BaseReaderViewer = forwardRef( ); const onChapterViewSizeChange = useCallback( - (width: number, height: number) => { + (width: number, height: number, chapterId: ChapterIdInfo['id']) => { if (!isContinuousReadingModeActive) { return; } - if (isContinuousVerticalReadingModeActive && minChapterViewWidth < width) { - chapterViewerSize.current.minChapterViewWidth = width; - setTriggerReRender({}); + const isSameChapterId = chapterId === minChapterSizeSourceChapterId; + + if (isContinuousVerticalReadingModeActive) { + if (!isSameChapterId && minChapterViewWidth >= width) { + return; + } + + setChapterViewerSize({ + minChapterViewWidth: width, + minChapterViewHeight: 0, + minChapterSizeSourceChapterId: chapterId, + }); + return; } - if (minChapterViewHeight < height) { - chapterViewerSize.current.minChapterViewHeight = height; - setTriggerReRender({}); + if (isSameChapterId || minChapterViewHeight < height) { + setChapterViewerSize({ + minChapterViewWidth: 0, + minChapterViewHeight: height, + minChapterSizeSourceChapterId: chapterId, + }); } }, - [isContinuousReadingModeActive, isContinuousVerticalReadingModeActive], + [ + isContinuousReadingModeActive, + isContinuousVerticalReadingModeActive, + minChapterViewWidth, + minChapterViewHeight, + minChapterSizeSourceChapterId, + ], ); useReaderHandlePageSelection( @@ -266,11 +290,16 @@ const BaseReaderViewer = forwardRef( readingMode, isContinuousReadingModeActive, readingDirection, + readerNavBarWidth, setPageToScrollToIndex, ); useLayoutEffect(() => { - chapterViewerSize.current = { minChapterViewWidth: 0, minChapterViewHeight: 0 }; + setChapterViewerSize({ + minChapterViewWidth: 0, + minChapterViewHeight: 0, + minChapterSizeSourceChapterId: -1, + }); setTriggerReRender({}); }, [readingMode]); @@ -341,6 +370,8 @@ const BaseReaderViewer = forwardRef( visibleChapters, ); + const isChapterSizeSourceChapter = chapter.id === minChapterSizeSourceChapterId; + return ( ); })} diff --git a/src/modules/reader/hooks/useReaderPreserveScrollPosition.ts b/src/modules/reader/hooks/useReaderPreserveScrollPosition.ts index 9a21775a..471a0ca1 100644 --- a/src/modules/reader/hooks/useReaderPreserveScrollPosition.ts +++ b/src/modules/reader/hooks/useReaderPreserveScrollPosition.ts @@ -6,7 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { RefObject, useEffect, useLayoutEffect, useRef } from 'react'; +import { RefObject, useCallback, useEffect, useLayoutEffect, useRef } from 'react'; import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts'; import { ReaderStateChapters, ReadingDirection, ReadingMode } from '@/modules/reader/types/Reader.types.ts'; import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts'; @@ -19,15 +19,17 @@ export const useReaderPreserveScrollPosition = ( scrollElementRef: RefObject, currentChapterId: ChapterIdInfo['id'] | undefined, chapterIndex: number, - currentPageIndex: number, + pageIndex: number, chaptersToRender: TChapterReader[], visibleChapters: ReaderStateChapters['visibleChapters'], readingMode: ReadingMode, isContinuousReadingModeActive: boolean, readingDirection: ReadingDirection, + readerNavBarWidth: number, setPageToScrollToIndex: ReaderStatePages['setPageToScrollToIndex'], ) => { const scrollPosition = useRef({ left: 0, top: 0, scrollWidth: 0, scrollHeight: 0 }); + const readerNavBarWidthRef = useRef(readerNavBarWidth); useEffect(() => { const element = scrollElementRef.current; @@ -96,7 +98,23 @@ export const useReaderPreserveScrollPosition = ( scrollElement.scrollTo(newLeft, newTop); }, [currentChapterId]); + const onSizeReset = useCallback(() => { + if (!isContinuousReadingModeActive) return; + setPageToScrollToIndex(pageIndex); + }, [isContinuousReadingModeActive, pageIndex]); + + useEffect(() => { + window.addEventListener('resize', onSizeReset); + return () => window.removeEventListener('resize', onSizeReset); + }, [onSizeReset]); + + useEffect(() => { + if (readerNavBarWidthRef.current === readerNavBarWidth) return; + onSizeReset(); + readerNavBarWidthRef.current = readerNavBarWidth; + }, [onSizeReset, readerNavBarWidth]); + useLayoutEffect(() => { - setPageToScrollToIndex(currentPageIndex); + setPageToScrollToIndex(pageIndex); }, [readingMode]); };