From 642708b8b3476bd0b25c57a7af12df54361b0bc8 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Wed, 2 Apr 2025 02:27:01 +0200 Subject: [PATCH] Immediately open previous/next chapter on reader nav bar button click The logic didn't handle cases were the next/previous chapter wasn't loaded yet, which lead to the load happening in the background without any user feedback. --- .../reader/components/viewer/ReaderViewer.tsx | 2 +- src/modules/reader/services/ReaderControls.ts | 46 ++++++++++++------- src/modules/reader/services/ReaderService.ts | 10 ++-- src/modules/reader/types/Reader.types.ts | 2 +- src/modules/reader/utils/Reader.utils.ts | 2 +- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/modules/reader/components/viewer/ReaderViewer.tsx b/src/modules/reader/components/viewer/ReaderViewer.tsx index ed4b73be..83d7d475 100644 --- a/src/modules/reader/components/viewer/ReaderViewer.tsx +++ b/src/modules/reader/components/viewer/ReaderViewer.tsx @@ -161,7 +161,7 @@ const BaseReaderViewer = forwardRef( ref: ForwardedRef, ) => { const { direction: themeDirection } = useTheme(); - const { resumeMode } = useLocation().state ?? { + const { resumeMode = ReaderResumeMode.START } = useLocation().state ?? { resumeMode: ReaderResumeMode.START, }; diff --git a/src/modules/reader/services/ReaderControls.ts b/src/modules/reader/services/ReaderControls.ts index 7e880af9..c7482af6 100644 --- a/src/modules/reader/services/ReaderControls.ts +++ b/src/modules/reader/services/ReaderControls.ts @@ -177,8 +177,14 @@ export class ReaderControls { const { t } = useTranslation(); const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } = ReaderService.useSettings(); - const { currentChapter, previousChapter, nextChapter, chapters, setReaderStateChapters } = - useReaderStateChaptersContext(); + const { + currentChapter, + previousChapter, + nextChapter, + chapters, + visibleChapters: { lastLeadingChapterSourceOrder, lastTrailingChapterSourceOrder }, + setReaderStateChapters, + } = useReaderStateChaptersContext(); const openChapter = ReaderService.useNavigateToChapter(); @@ -230,21 +236,27 @@ export class ReaderControls { ); } - setReaderStateChapters((prevState) => - updateReaderStateVisibleChapters( - isPreviousChapter, - prevState, - chapterToOpen.sourceOrder, - scrollIntoView, - isPreviousChapter ? false : undefined, - !isPreviousChapter ? false : undefined, - ), - ); + const isAlreadyLoaded = + lastLeadingChapterSourceOrder <= chapterToOpen.sourceOrder && + lastTrailingChapterSourceOrder >= chapterToOpen.sourceOrder; - openChapter( - chapterToOpen, - getReaderOpenChapterResumeMode(isSpecificChapterMode, isPreviousChapter), - ); + if (isAlreadyLoaded) { + setReaderStateChapters((prevState) => + updateReaderStateVisibleChapters( + isPreviousChapter, + prevState, + chapterToOpen.sourceOrder, + scrollIntoView, + isPreviousChapter ? false : undefined, + !isPreviousChapter ? false : undefined, + ), + ); + } + + openChapter(chapterToOpen, { + resumeMode: getReaderOpenChapterResumeMode(isSpecificChapterMode, isPreviousChapter), + updateInitialChapter: !isAlreadyLoaded, + }); } catch (error) { defaultPromiseErrorHandler('ReaderControls#useOpenChapter#doOpenChapter:')(error); } @@ -259,6 +271,8 @@ export class ReaderControls { readingMode.value, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange, + lastLeadingChapterSourceOrder, + lastTrailingChapterSourceOrder, ], ); } diff --git a/src/modules/reader/services/ReaderService.ts b/src/modules/reader/services/ReaderService.ts index 1ff50e95..73d54374 100644 --- a/src/modules/reader/services/ReaderService.ts +++ b/src/modules/reader/services/ReaderService.ts @@ -16,8 +16,8 @@ import { IReaderSettings, IReaderSettingsWithDefaultFlag, ReaderExitMode, + ReaderOpenChapterLocationState, ReaderOverlayMode, - ReaderResumeMode, ReaderStateChapters, ReadingDirection, ReadingMode, @@ -78,15 +78,13 @@ export class ReaderService { return ReaderService.chapterUpdateQueues.get(id)!; } - static useNavigateToChapter(): (chapter: TChapterReader, resumeMode?: ReaderResumeMode) => void { + static useNavigateToChapter(): (chapter: TChapterReader, state?: ReaderOpenChapterLocationState) => void { const navigate = useNavigate(); - return useCallback((chapter, resumeMode) => { + return useCallback((chapter, state) => { navigate(Chapters.getReaderUrl(chapter), { replace: true, - state: { - resumeMode, - }, + state, }); }, []); } diff --git a/src/modules/reader/types/Reader.types.ts b/src/modules/reader/types/Reader.types.ts index 83a1db7f..6d033e66 100644 --- a/src/modules/reader/types/Reader.types.ts +++ b/src/modules/reader/types/Reader.types.ts @@ -318,7 +318,7 @@ export enum ReaderResumeMode { } export interface ReaderOpenChapterLocationState { - resumeMode: ReaderResumeMode; + resumeMode?: ReaderResumeMode; updateInitialChapter?: boolean; } diff --git a/src/modules/reader/utils/Reader.utils.ts b/src/modules/reader/utils/Reader.utils.ts index 2a282df3..e933afce 100644 --- a/src/modules/reader/utils/Reader.utils.ts +++ b/src/modules/reader/utils/Reader.utils.ts @@ -301,7 +301,7 @@ export const getReaderChapterViewResumeMode = ( isLeadingChapter: boolean, isTrailingChapter: boolean, forcedResumeMode: ReaderResumeMode | undefined, - resumeMode: ReaderResumeMode = ReaderResumeMode.START, + resumeMode: ReaderResumeMode, ): ReaderResumeMode => { if (isCurrentChapter && forcedResumeMode !== undefined) { return forcedResumeMode;