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.
This commit is contained in:
schroda
2025-04-02 02:27:01 +02:00
parent 7a7a0dfa9c
commit 642708b8b3
5 changed files with 37 additions and 25 deletions

View File

@@ -161,7 +161,7 @@ const BaseReaderViewer = forwardRef(
ref: ForwardedRef<HTMLDivElement | null>, ref: ForwardedRef<HTMLDivElement | null>,
) => { ) => {
const { direction: themeDirection } = useTheme(); const { direction: themeDirection } = useTheme();
const { resumeMode } = useLocation<ReaderOpenChapterLocationState>().state ?? { const { resumeMode = ReaderResumeMode.START } = useLocation<ReaderOpenChapterLocationState>().state ?? {
resumeMode: ReaderResumeMode.START, resumeMode: ReaderResumeMode.START,
}; };

View File

@@ -177,8 +177,14 @@ export class ReaderControls {
const { t } = useTranslation(); const { t } = useTranslation();
const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } = const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } =
ReaderService.useSettings(); ReaderService.useSettings();
const { currentChapter, previousChapter, nextChapter, chapters, setReaderStateChapters } = const {
useReaderStateChaptersContext(); currentChapter,
previousChapter,
nextChapter,
chapters,
visibleChapters: { lastLeadingChapterSourceOrder, lastTrailingChapterSourceOrder },
setReaderStateChapters,
} = useReaderStateChaptersContext();
const openChapter = ReaderService.useNavigateToChapter(); const openChapter = ReaderService.useNavigateToChapter();
@@ -230,21 +236,27 @@ export class ReaderControls {
); );
} }
setReaderStateChapters((prevState) => const isAlreadyLoaded =
updateReaderStateVisibleChapters( lastLeadingChapterSourceOrder <= chapterToOpen.sourceOrder &&
isPreviousChapter, lastTrailingChapterSourceOrder >= chapterToOpen.sourceOrder;
prevState,
chapterToOpen.sourceOrder,
scrollIntoView,
isPreviousChapter ? false : undefined,
!isPreviousChapter ? false : undefined,
),
);
openChapter( if (isAlreadyLoaded) {
chapterToOpen, setReaderStateChapters((prevState) =>
getReaderOpenChapterResumeMode(isSpecificChapterMode, isPreviousChapter), updateReaderStateVisibleChapters(
); isPreviousChapter,
prevState,
chapterToOpen.sourceOrder,
scrollIntoView,
isPreviousChapter ? false : undefined,
!isPreviousChapter ? false : undefined,
),
);
}
openChapter(chapterToOpen, {
resumeMode: getReaderOpenChapterResumeMode(isSpecificChapterMode, isPreviousChapter),
updateInitialChapter: !isAlreadyLoaded,
});
} catch (error) { } catch (error) {
defaultPromiseErrorHandler('ReaderControls#useOpenChapter#doOpenChapter:')(error); defaultPromiseErrorHandler('ReaderControls#useOpenChapter#doOpenChapter:')(error);
} }
@@ -259,6 +271,8 @@ export class ReaderControls {
readingMode.value, readingMode.value,
shouldInformAboutMissingChapter, shouldInformAboutMissingChapter,
shouldInformAboutScanlatorChange, shouldInformAboutScanlatorChange,
lastLeadingChapterSourceOrder,
lastTrailingChapterSourceOrder,
], ],
); );
} }

View File

@@ -16,8 +16,8 @@ import {
IReaderSettings, IReaderSettings,
IReaderSettingsWithDefaultFlag, IReaderSettingsWithDefaultFlag,
ReaderExitMode, ReaderExitMode,
ReaderOpenChapterLocationState,
ReaderOverlayMode, ReaderOverlayMode,
ReaderResumeMode,
ReaderStateChapters, ReaderStateChapters,
ReadingDirection, ReadingDirection,
ReadingMode, ReadingMode,
@@ -78,15 +78,13 @@ export class ReaderService {
return ReaderService.chapterUpdateQueues.get(id)!; return ReaderService.chapterUpdateQueues.get(id)!;
} }
static useNavigateToChapter(): (chapter: TChapterReader, resumeMode?: ReaderResumeMode) => void { static useNavigateToChapter(): (chapter: TChapterReader, state?: ReaderOpenChapterLocationState) => void {
const navigate = useNavigate(); const navigate = useNavigate();
return useCallback((chapter, resumeMode) => { return useCallback((chapter, state) => {
navigate(Chapters.getReaderUrl(chapter), { navigate(Chapters.getReaderUrl(chapter), {
replace: true, replace: true,
state: { state,
resumeMode,
},
}); });
}, []); }, []);
} }

View File

@@ -318,7 +318,7 @@ export enum ReaderResumeMode {
} }
export interface ReaderOpenChapterLocationState { export interface ReaderOpenChapterLocationState {
resumeMode: ReaderResumeMode; resumeMode?: ReaderResumeMode;
updateInitialChapter?: boolean; updateInitialChapter?: boolean;
} }

View File

@@ -301,7 +301,7 @@ export const getReaderChapterViewResumeMode = (
isLeadingChapter: boolean, isLeadingChapter: boolean,
isTrailingChapter: boolean, isTrailingChapter: boolean,
forcedResumeMode: ReaderResumeMode | undefined, forcedResumeMode: ReaderResumeMode | undefined,
resumeMode: ReaderResumeMode = ReaderResumeMode.START, resumeMode: ReaderResumeMode,
): ReaderResumeMode => { ): ReaderResumeMode => {
if (isCurrentChapter && forcedResumeMode !== undefined) { if (isCurrentChapter && forcedResumeMode !== undefined) {
return forcedResumeMode; return forcedResumeMode;