Add option to open specific chapter via "useOpenChapter"
This commit is contained in:
@@ -24,7 +24,6 @@ import { useReaderStateChaptersContext } from '@/modules/reader/contexts/state/R
|
|||||||
import {
|
import {
|
||||||
PageInViewportType,
|
PageInViewportType,
|
||||||
ProgressBarPosition,
|
ProgressBarPosition,
|
||||||
ReaderResumeMode,
|
|
||||||
ReaderTransitionPageMode,
|
ReaderTransitionPageMode,
|
||||||
ReadingDirection,
|
ReadingDirection,
|
||||||
ReadingMode,
|
ReadingMode,
|
||||||
@@ -44,8 +43,12 @@ import { useReaderTapZoneContext } from '@/modules/reader/contexts/ReaderTapZone
|
|||||||
import { TapZoneRegionType, TReaderTapZoneContext } from '@/modules/reader/types/TapZoneLayout.types.ts';
|
import { TapZoneRegionType, TReaderTapZoneContext } from '@/modules/reader/types/TapZoneLayout.types.ts';
|
||||||
import { ReaderTapZoneService } from '@/modules/reader/services/ReaderTapZoneService.ts';
|
import { ReaderTapZoneService } from '@/modules/reader/services/ReaderTapZoneService.ts';
|
||||||
import { isContinuousReadingMode } from '@/modules/reader/utils/ReaderSettings.utils.tsx';
|
import { isContinuousReadingMode } from '@/modules/reader/utils/ReaderSettings.utils.tsx';
|
||||||
import { getReaderChapterFromCache } from '@/modules/reader/utils/Reader.utils.ts';
|
import {
|
||||||
import { Chapters } from '@/modules/chapter/services/Chapters.ts';
|
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 { DirectionOffset, TranslationKey } from '@/Base.types.ts';
|
||||||
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||||
import { TChapterReader } from '@/modules/chapter/Chapter.types.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 { t } = useTranslation();
|
||||||
const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } =
|
const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } =
|
||||||
ReaderService.useSettings();
|
ReaderService.useSettings();
|
||||||
const { currentChapter, previousChapter, nextChapter } = useReaderStateChaptersContext();
|
const { currentChapter, previousChapter, nextChapter, chapters, setReaderStateChapters } =
|
||||||
|
useReaderStateChaptersContext();
|
||||||
|
|
||||||
const openPreviousChapter = ReaderService.useNavigateToChapter(previousChapter, ReaderResumeMode.END);
|
const openChapter = ReaderService.useNavigateToChapter();
|
||||||
const openNextChapter = ReaderService.useNavigateToChapter(nextChapter, ReaderResumeMode.START);
|
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(offset) => {
|
(offset, doTransitionCheck = true) => {
|
||||||
switch (offset) {
|
if (!currentChapter) {
|
||||||
case 'previous':
|
return;
|
||||||
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})`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
t,
|
||||||
currentChapter?.id,
|
currentChapter?.id,
|
||||||
openPreviousChapter,
|
openChapter,
|
||||||
openNextChapter,
|
|
||||||
readingMode.value,
|
readingMode.value,
|
||||||
shouldInformAboutMissingChapter,
|
shouldInformAboutMissingChapter,
|
||||||
shouldInformAboutScanlatorChange,
|
shouldInformAboutScanlatorChange,
|
||||||
|
|||||||
@@ -75,19 +75,17 @@ export class ReaderService {
|
|||||||
return ReaderService.chapterUpdateQueues.get(id)!;
|
return ReaderService.chapterUpdateQueues.get(id)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static useNavigateToChapter(chapter?: TChapterReader, resumeMode?: ReaderResumeMode): () => void {
|
static useNavigateToChapter(): (chapter: TChapterReader, resumeMode?: ReaderResumeMode) => void {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
return useCallback(
|
|
||||||
() =>
|
return useCallback((chapter, resumeMode) => {
|
||||||
chapter &&
|
|
||||||
navigate(Chapters.getReaderUrl(chapter), {
|
navigate(Chapters.getReaderUrl(chapter), {
|
||||||
replace: true,
|
replace: true,
|
||||||
state: {
|
state: {
|
||||||
resumeMode,
|
resumeMode,
|
||||||
},
|
},
|
||||||
}),
|
});
|
||||||
[chapter],
|
}, []);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static downloadAhead(
|
static downloadAhead(
|
||||||
|
|||||||
@@ -165,3 +165,18 @@ export const createUpdateReaderPageLoadState =
|
|||||||
return statePageLoadStates.toSpliced(index, 1, { url: pageLoadState.url, loaded: true });
|
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;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user