Add option to open specific chapter via "useOpenChapter"

This commit is contained in:
schroda
2025-01-28 01:30:05 +01:00
parent 45b4874348
commit 4789a74785
3 changed files with 96 additions and 49 deletions

View File

@@ -24,7 +24,6 @@ import { useReaderStateChaptersContext } from '@/modules/reader/contexts/state/R
import {
PageInViewportType,
ProgressBarPosition,
ReaderResumeMode,
ReaderTransitionPageMode,
ReadingDirection,
ReadingMode,
@@ -44,8 +43,12 @@ import { useReaderTapZoneContext } from '@/modules/reader/contexts/ReaderTapZone
import { TapZoneRegionType, TReaderTapZoneContext } from '@/modules/reader/types/TapZoneLayout.types.ts';
import { ReaderTapZoneService } from '@/modules/reader/services/ReaderTapZoneService.ts';
import { isContinuousReadingMode } from '@/modules/reader/utils/ReaderSettings.utils.tsx';
import { getReaderChapterFromCache } from '@/modules/reader/utils/Reader.utils.ts';
import { Chapters } from '@/modules/chapter/services/Chapters.ts';
import {
getReaderChapterFromCache,
getReaderOpenChapterResumeMode,
updateReaderStateVisibleChapters,
} from '@/modules/reader/utils/Reader.utils.ts';
import { ChapterIdInfo, Chapters } from '@/modules/chapter/services/Chapters.ts';
import { DirectionOffset, TranslationKey } from '@/Base.types.ts';
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { TChapterReader } from '@/modules/chapter/Chapter.types.ts';
@@ -166,51 +169,82 @@ export class ReaderControls {
}
}
static useOpenChapter(): (offset: 'previous' | 'next') => void {
static useOpenChapter(): (offset: 'previous' | 'next' | ChapterIdInfo['id'], doTransitionCheck?: boolean) => void {
const { t } = useTranslation();
const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } =
ReaderService.useSettings();
const { currentChapter, previousChapter, nextChapter } = useReaderStateChaptersContext();
const { currentChapter, previousChapter, nextChapter, chapters, setReaderStateChapters } =
useReaderStateChaptersContext();
const openPreviousChapter = ReaderService.useNavigateToChapter(previousChapter, ReaderResumeMode.END);
const openNextChapter = ReaderService.useNavigateToChapter(nextChapter, ReaderResumeMode.START);
const openChapter = ReaderService.useNavigateToChapter();
return useCallback(
(offset) => {
switch (offset) {
case 'previous':
ReaderControls.checkNextChapterConsistency(
t,
offset,
currentChapter,
previousChapter,
shouldInformAboutMissingChapter,
shouldInformAboutScanlatorChange,
)
.then(openPreviousChapter)
.catch(defaultPromiseErrorHandler('ReaderControls::checkNextChapterConsistency: previous'));
break;
case 'next':
ReaderControls.checkNextChapterConsistency(
t,
offset,
currentChapter,
nextChapter,
shouldInformAboutMissingChapter,
shouldInformAboutScanlatorChange,
)
.then(openNextChapter)
.catch(defaultPromiseErrorHandler('ReaderControls::checkNextChapterConsistency: next'));
break;
default:
throw new Error(`Unexpected "offset" (${offset})`);
(offset, doTransitionCheck = true) => {
if (!currentChapter) {
return;
}
const isSpecificChapterMode = typeof offset === 'number';
const isPreviousOffset = offset === 'previous';
const doesPreviousChapterExist = isPreviousOffset && !!previousChapter;
const doesNextChapterExist = !isPreviousOffset && !!nextChapter;
const canOpenNextChapter = isSpecificChapterMode || doesPreviousChapterExist || doesNextChapterExist;
if (!canOpenNextChapter) {
return;
}
const doOpenChapter = async () => {
const chapterToOpen = (() => {
if (isSpecificChapterMode) {
return chapters.find((chapter) => chapter.id === offset);
}
if (isPreviousOffset) {
return previousChapter;
}
return nextChapter;
})();
if (!chapterToOpen) {
return;
}
const isPreviousChapter = chapterToOpen.sourceOrder < currentChapter.sourceOrder;
try {
if (doTransitionCheck) {
await ReaderControls.checkNextChapterConsistency(
t,
isPreviousChapter ? 'previous' : 'next',
currentChapter,
chapterToOpen,
shouldInformAboutMissingChapter,
shouldInformAboutScanlatorChange,
);
}
setReaderStateChapters((prevState) =>
updateReaderStateVisibleChapters(isPreviousChapter, prevState, chapterToOpen.sourceOrder),
);
openChapter(
chapterToOpen,
getReaderOpenChapterResumeMode(isSpecificChapterMode, isPreviousChapter),
);
} catch (error) {
defaultPromiseErrorHandler('ReaderControls#useOpenChapter#doOpenChapter: ');
}
};
doOpenChapter().catch(defaultPromiseErrorHandler('ReaderControls#useOpenChapter'));
},
[
t,
currentChapter?.id,
openPreviousChapter,
openNextChapter,
openChapter,
readingMode.value,
shouldInformAboutMissingChapter,
shouldInformAboutScanlatorChange,

View File

@@ -75,19 +75,17 @@ export class ReaderService {
return ReaderService.chapterUpdateQueues.get(id)!;
}
static useNavigateToChapter(chapter?: TChapterReader, resumeMode?: ReaderResumeMode): () => void {
static useNavigateToChapter(): (chapter: TChapterReader, resumeMode?: ReaderResumeMode) => void {
const navigate = useNavigate();
return useCallback(
() =>
chapter &&
navigate(Chapters.getReaderUrl(chapter), {
replace: true,
state: {
resumeMode,
},
}),
[chapter],
);
return useCallback((chapter, resumeMode) => {
navigate(Chapters.getReaderUrl(chapter), {
replace: true,
state: {
resumeMode,
},
});
}, []);
}
static downloadAhead(

View File

@@ -165,3 +165,18 @@ export const createUpdateReaderPageLoadState =
return statePageLoadStates.toSpliced(index, 1, { url: pageLoadState.url, loaded: true });
});
};
export const getReaderOpenChapterResumeMode = (
isSpecificChapterMode: boolean,
isPreviousChapter: boolean,
): ReaderResumeMode | undefined => {
if (!isSpecificChapterMode) {
return undefined;
}
if (isPreviousChapter) {
return ReaderResumeMode.END;
}
return ReaderResumeMode.START;
};