diff --git a/CHANGELOG.md b/CHANGELOG.md index 651e6ae5..7654f327 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Reader**) Fix jumping back to the first page on window resize - (**Reader**) Fix chapter not getting marked as read in continuous reading mode in case the last page is not big enough to get marked as the current page - (**Reader**) Fix infinite scrolling sometimes not opening previous/next chapter +- (**Reader**) Fix infinite scroll immediately opening previous chapter with disabled transition page when opening reader - (**Reader**) Fix preserving scroll position with RTL reading direction and a language that is read RTL - (**Reader**) Fix missing gap between chapters in continuous vertical and horizontal reading modes with disabled transition page - (**Browse**) Fix showing only nsfw sources in the browse source page when the "show nsfw" setting is disabled diff --git a/src/features/reader/infinite-scroll/useReaderInfiniteScrollUpdateChapter.ts b/src/features/reader/infinite-scroll/useReaderInfiniteScrollUpdateChapter.ts index 6df9beb8..f301fa03 100644 --- a/src/features/reader/infinite-scroll/useReaderInfiniteScrollUpdateChapter.ts +++ b/src/features/reader/infinite-scroll/useReaderInfiniteScrollUpdateChapter.ts @@ -6,7 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; import { ReadingDirection, ReadingMode } from '@/features/reader/Reader.types.ts'; import { isContinuousReadingMode, @@ -17,6 +17,9 @@ import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts import { useIntersectionObserver } from '@/base/hooks/useIntersectionObserver.tsx'; import { getReaderScrollbarStore, useReaderSettingsStore } from '@/features/reader/stores/ReaderStore.ts'; import { ReaderControls } from '@/features/reader/services/ReaderControls.ts'; +import { d } from 'koration'; +import { maybeExecuteWithDelay } from '@/lib/HelperFunctions.ts'; +import { usePrevious } from '@mantine/hooks'; interface ElementIntersection { start: boolean; @@ -245,6 +248,10 @@ export const useReaderInfiniteScrollUpdateChapter = ( image: HTMLElement | null, scrollElement: HTMLElement | null, ) => { + const previousChapterId = usePrevious(chapterId); + const initialChapterIdRef = useRef(chapterId); + const eventListenerTimeoutRef = useRef(undefined); + const { readingMode, readingDirection, shouldUseInfiniteScroll, shouldShowTransitionPage } = useReaderSettingsStore( (state) => ({ readingMode: state.readingMode.value, @@ -259,6 +266,7 @@ export const useReaderInfiniteScrollUpdateChapter = ( const isContinuousVerticalReadingModeActive = isContinuousVerticalReadingMode(readingMode); if ( + !image || shouldShowTransitionPage || !scrollElement || !isContinuousReadingModeActive || @@ -297,7 +305,15 @@ export const useReaderInfiniteScrollUpdateChapter = ( } }; - scrollElement.addEventListener('scroll', onScroll, { passive: true }); + const isInitialChapterRender = + previousChapterId === undefined || + (initialChapterIdRef.current === chapterId && previousChapterId === chapterId); + clearTimeout(eventListenerTimeoutRef.current); + eventListenerTimeoutRef.current = maybeExecuteWithDelay( + () => scrollElement.addEventListener('scroll', onScroll, { passive: true }), + d(5).seconds.inWholeMilliseconds, + isInitialChapterRender, + ); return () => scrollElement.removeEventListener('scroll', onScroll); }, [ readingMode, @@ -307,6 +323,7 @@ export const useReaderInfiniteScrollUpdateChapter = ( isCurrentChapter, isChapterToOpenVisible, chapterToOpenId, + !!image, ]); useIntersectionObserver( diff --git a/src/lib/HelperFunctions.ts b/src/lib/HelperFunctions.ts index 92a4ec06..83e615d3 100644 --- a/src/lib/HelperFunctions.ts +++ b/src/lib/HelperFunctions.ts @@ -82,3 +82,16 @@ export const getNextRotationValue = ( return values[(indexOfValue + 1) % values.length]; }; + +export const maybeExecuteWithDelay = ( + action: () => void, + delay: number, + condition: boolean, +): NodeJS.Timeout | undefined => { + if (condition) { + return setTimeout(() => action(), delay); + } + + action(); + return undefined; +};