Preload previous/next chapter in reader
This commit is contained in:
@@ -78,6 +78,7 @@ const BaseReaderChapterViewer = ({
|
|||||||
isNextChapter,
|
isNextChapter,
|
||||||
isLeadingChapter,
|
isLeadingChapter,
|
||||||
isTrailingChapter,
|
isTrailingChapter,
|
||||||
|
isPreloadMode,
|
||||||
imageRefs: globalImageRefs,
|
imageRefs: globalImageRefs,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
setReaderStateChapters,
|
setReaderStateChapters,
|
||||||
@@ -172,7 +173,15 @@ const BaseReaderChapterViewer = ({
|
|||||||
const Pager = useMemo(() => getPagerForReadingMode(readingMode), [readingMode]);
|
const Pager = useMemo(() => getPagerForReadingMode(readingMode), [readingMode]);
|
||||||
const isLtrReadingDirection = readingDirection === ReadingDirection.LTR;
|
const isLtrReadingDirection = readingDirection === ReadingDirection.LTR;
|
||||||
const isContinuousReadingModeActive = isContinuousReadingMode(readingMode);
|
const isContinuousReadingModeActive = isContinuousReadingMode(readingMode);
|
||||||
const shouldHideChapter = !isContinuousReadingModeActive && !isCurrentChapter;
|
const shouldHideChapter = (!isContinuousReadingModeActive && !isCurrentChapter) || isPreloadMode;
|
||||||
|
|
||||||
|
const isCurrentChapterInSinglePager = !isContinuousReadingModeActive && isCurrentChapter;
|
||||||
|
const showPreviousTransitionPage =
|
||||||
|
!shouldHideChapter &&
|
||||||
|
(isCurrentChapterInSinglePager || (isContinuousReadingModeActive && (isInitialChapter || isLeadingChapter)));
|
||||||
|
const showNextTransitionPage =
|
||||||
|
!shouldHideChapter &&
|
||||||
|
(isCurrentChapterInSinglePager || (isContinuousReadingModeActive && (isInitialChapter || isTrailingChapter)));
|
||||||
|
|
||||||
isCurrentChapterRef.current = isCurrentChapter;
|
isCurrentChapterRef.current = isCurrentChapter;
|
||||||
if (isCurrentChapter) {
|
if (isCurrentChapter) {
|
||||||
@@ -240,7 +249,7 @@ const BaseReaderChapterViewer = ({
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const updatePageState = <T,>(
|
const updateState = <T,>(
|
||||||
value: T,
|
value: T,
|
||||||
setLocalState: (value: T) => void,
|
setLocalState: (value: T) => void,
|
||||||
setGlobalState: (value: T) => void,
|
setGlobalState: (value: T) => void,
|
||||||
@@ -264,13 +273,13 @@ const BaseReaderChapterViewer = ({
|
|||||||
pagesToSpreadState,
|
pagesToSpreadState,
|
||||||
arePagesFetched,
|
arePagesFetched,
|
||||||
setArePagesFetched,
|
setArePagesFetched,
|
||||||
setReaderStateChapters,
|
(value) => updateState(value, noOp, setReaderStateChapters),
|
||||||
(value) => updatePageState(value, setTotalPages, setContextTotalPages),
|
(value) => updateState(value, setTotalPages, setContextTotalPages),
|
||||||
(value) => updatePageState(value, setPages, setContextPages),
|
(value) => updateState(value, setPages, setContextPages),
|
||||||
(value) => updatePageState(value, setPageUrls, noOp),
|
(value) => updateState(value, setPageUrls, noOp),
|
||||||
(value) => updatePageState(value, setPageLoadStates, setContextPageLoadStates),
|
(value) => updateState(value, setPageLoadStates, setContextPageLoadStates),
|
||||||
(value) => updatePageState(value, setPagesToSpreadState, noOp),
|
(value) => updateState(value, setPagesToSpreadState, noOp),
|
||||||
(value) => updatePageState(value, noOp, setContextCurrentPageIndex),
|
(value) => updateState(value, noOp, setContextCurrentPageIndex),
|
||||||
(value) => {
|
(value) => {
|
||||||
if ((isInitialChapter && !arePagesFetched) || scrollIntoView) {
|
if ((isInitialChapter && !arePagesFetched) || scrollIntoView) {
|
||||||
setPageToScrollToIndex(value);
|
setPageToScrollToIndex(value);
|
||||||
@@ -280,16 +289,16 @@ const BaseReaderChapterViewer = ({
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(value) => updatePageState(value, noOp, setTransitionPageMode),
|
(value) => updateState(value, noOp, setTransitionPageMode),
|
||||||
);
|
);
|
||||||
|
|
||||||
useReaderConvertPagesForReadingMode(
|
useReaderConvertPagesForReadingMode(
|
||||||
currentPageIndex,
|
currentPageIndex,
|
||||||
actualPages,
|
actualPages,
|
||||||
pageUrls,
|
pageUrls,
|
||||||
(value) => updatePageState(value, setPages, setContextPages, true),
|
(value) => updateState(value, setPages, setContextPages, true),
|
||||||
(value) => updatePageState(value, setPagesToSpreadState, noOp, true),
|
(value) => updateState(value, setPagesToSpreadState, noOp, true),
|
||||||
(value) => updatePageState(value, noOp, updateCurrentPageIndex),
|
(value) => updateState(value, noOp, updateCurrentPageIndex),
|
||||||
readingMode,
|
readingMode,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -396,19 +405,20 @@ const BaseReaderChapterViewer = ({
|
|||||||
}),
|
}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ReaderInfiniteScrollUpdateChapter
|
{!isPreloadMode && (
|
||||||
readingMode={readingMode}
|
<ReaderInfiniteScrollUpdateChapter
|
||||||
readingDirection={readingDirection}
|
readingMode={readingMode}
|
||||||
chapterId={chapterId}
|
readingDirection={readingDirection}
|
||||||
previousChapterId={previousChapterId}
|
chapterId={chapterId}
|
||||||
nextChapterId={nextChapterId}
|
previousChapterId={previousChapterId}
|
||||||
isCurrentChapter={isCurrentChapter}
|
nextChapterId={nextChapterId}
|
||||||
isPreviousChapterVisible={isPreviousChapterVisible}
|
isCurrentChapter={isCurrentChapter}
|
||||||
isNextChapterVisible={isNextChapterVisible}
|
isPreviousChapterVisible={isPreviousChapterVisible}
|
||||||
imageWrapper={pagerRef.current}
|
isNextChapterVisible={isNextChapterVisible}
|
||||||
/>
|
imageWrapper={pagerRef.current}
|
||||||
{((!isContinuousReadingModeActive && isCurrentChapter) ||
|
/>
|
||||||
(isContinuousReadingModeActive && (isInitialChapter || isLeadingChapter))) && (
|
)}
|
||||||
|
{showPreviousTransitionPage && (
|
||||||
<ReaderTransitionPage chapterId={chapterId} type={ReaderTransitionPageMode.PREVIOUS} />
|
<ReaderTransitionPage chapterId={chapterId} type={ReaderTransitionPageMode.PREVIOUS} />
|
||||||
)}
|
)}
|
||||||
<Pager
|
<Pager
|
||||||
@@ -436,9 +446,9 @@ const BaseReaderChapterViewer = ({
|
|||||||
scrollbarXSize={scrollbarXSize}
|
scrollbarXSize={scrollbarXSize}
|
||||||
scrollbarYSize={scrollbarYSize}
|
scrollbarYSize={scrollbarYSize}
|
||||||
readerNavBarWidth={readerNavBarWidth}
|
readerNavBarWidth={readerNavBarWidth}
|
||||||
|
isPreloadMode={isPreloadMode}
|
||||||
/>
|
/>
|
||||||
{((!isContinuousReadingModeActive && isCurrentChapter) ||
|
{showNextTransitionPage && (
|
||||||
(isContinuousReadingModeActive && (isInitialChapter || isTrailingChapter))) && (
|
|
||||||
<ReaderTransitionPage chapterId={chapterId} type={ReaderTransitionPageMode.NEXT} />
|
<ReaderTransitionPage chapterId={chapterId} type={ReaderTransitionPageMode.NEXT} />
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -314,6 +314,24 @@ const BaseReaderViewer = forwardRef(
|
|||||||
const isNextChapter = chapter.id === chaptersToRender[currentChapterIndex - 1]?.id;
|
const isNextChapter = chapter.id === chaptersToRender[currentChapterIndex - 1]?.id;
|
||||||
const isLeadingChapter = initialChapter.sourceOrder > chapter.sourceOrder;
|
const isLeadingChapter = initialChapter.sourceOrder > chapter.sourceOrder;
|
||||||
const isTrailingChapter = initialChapter.sourceOrder < chapter.sourceOrder;
|
const isTrailingChapter = initialChapter.sourceOrder < chapter.sourceOrder;
|
||||||
|
const isLastLeadingChapter = visibleChapters.lastLeadingChapterSourceOrder === chapter.sourceOrder;
|
||||||
|
const isLastTrailingChapter =
|
||||||
|
visibleChapters.lastTrailingChapterSourceOrder === chapter.sourceOrder;
|
||||||
|
const isPreloadMode =
|
||||||
|
(isLastLeadingChapter && visibleChapters.isLeadingChapterPreloadMode) ||
|
||||||
|
(isLastTrailingChapter && visibleChapters.isTrailingChapterPreloadMode);
|
||||||
|
|
||||||
|
const isPreviousChapterLoaded = !!chaptersToRender[currentChapterIndex + 1];
|
||||||
|
const isPreviousChapterLastLeadingChapter = chapterIndex + 1 >= chaptersToRender.length - 1;
|
||||||
|
const isPreviousChapterPreloading =
|
||||||
|
isPreviousChapterLastLeadingChapter && visibleChapters.isLeadingChapterPreloadMode;
|
||||||
|
const isPreviousChapterVisible = isPreviousChapterLoaded && !isPreviousChapterPreloading;
|
||||||
|
|
||||||
|
const isNextChapterLoaded = !!chaptersToRender[chapterIndex - 1];
|
||||||
|
const isNextChapterLastTrailingChapter = chapterIndex - 1 < 0;
|
||||||
|
const isNextChapterPreloading =
|
||||||
|
isNextChapterLastTrailingChapter && visibleChapters.isTrailingChapterPreloadMode;
|
||||||
|
const isNextChapterVisible = isNextChapterLoaded && !isNextChapterPreloading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReaderChapterViewer
|
<ReaderChapterViewer
|
||||||
@@ -321,8 +339,8 @@ const BaseReaderViewer = forwardRef(
|
|||||||
chapterId={chapter.id}
|
chapterId={chapter.id}
|
||||||
previousChapterId={previousChapter?.id}
|
previousChapterId={previousChapter?.id}
|
||||||
nextChapterId={nextChapter?.id}
|
nextChapterId={nextChapter?.id}
|
||||||
isPreviousChapterVisible={!!chaptersToRender[chapterIndex + 1]}
|
isPreviousChapterVisible={isPreviousChapterVisible}
|
||||||
isNextChapterVisible={!!chaptersToRender[chapterIndex - 1]}
|
isNextChapterVisible={isNextChapterVisible}
|
||||||
lastPageRead={chapter.lastPageRead}
|
lastPageRead={chapter.lastPageRead}
|
||||||
currentPageIndex={getReaderChapterViewerCurrentPageIndex(
|
currentPageIndex={getReaderChapterViewerCurrentPageIndex(
|
||||||
currentPageIndex,
|
currentPageIndex,
|
||||||
@@ -340,6 +358,7 @@ const BaseReaderViewer = forwardRef(
|
|||||||
isNextChapter={isNextChapter}
|
isNextChapter={isNextChapter}
|
||||||
isLeadingChapter={isLeadingChapter}
|
isLeadingChapter={isLeadingChapter}
|
||||||
isTrailingChapter={isTrailingChapter}
|
isTrailingChapter={isTrailingChapter}
|
||||||
|
isPreloadMode={isPreloadMode}
|
||||||
imageRefs={imageRefs}
|
imageRefs={imageRefs}
|
||||||
setPages={setPages}
|
setPages={setPages}
|
||||||
setPageLoadStates={setPageLoadStates}
|
setPageLoadStates={setPageLoadStates}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { isContinuousReadingMode } from '@/modules/reader/utils/ReaderSettings.u
|
|||||||
|
|
||||||
const BaseBasePager = forwardRef<
|
const BaseBasePager = forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
Omit<ReaderPagerProps, 'pageLoadStates' | 'retryFailedPagesKeyPrefix'> &
|
Omit<ReaderPagerProps, 'pageLoadStates' | 'retryFailedPagesKeyPrefix' | 'isPreloadMode'> &
|
||||||
Pick<IReaderSettings, 'readingMode' | 'imagePreLoadAmount'> & {
|
Pick<IReaderSettings, 'readingMode' | 'imagePreLoadAmount'> & {
|
||||||
createPage: (
|
createPage: (
|
||||||
page: ReaderStatePages['pages'][number],
|
page: ReaderStatePages['pages'][number],
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const getPagePosition = (
|
|||||||
const BaseReaderDoublePagedPager = forwardRef<
|
const BaseReaderDoublePagedPager = forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
ReaderPagerProps & Pick<IReaderSettings, 'readingDirection' | 'pageScaleMode'>
|
ReaderPagerProps & Pick<IReaderSettings, 'readingDirection' | 'pageScaleMode'>
|
||||||
>(({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, ...props }, ref) => {
|
>(({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, isPreloadMode, ...props }, ref) => {
|
||||||
const { currentPageIndex, pages, totalPages, readingDirection, pageScaleMode } = props;
|
const { currentPageIndex, pages, totalPages, readingDirection, pageScaleMode } = props;
|
||||||
|
|
||||||
const { direction: themeDirection } = useTheme();
|
const { direction: themeDirection } = useTheme();
|
||||||
@@ -72,6 +72,7 @@ const BaseReaderDoublePagedPager = forwardRef<
|
|||||||
pagesIndex,
|
pagesIndex,
|
||||||
true,
|
true,
|
||||||
pageLoadStates[primary.index].loaded,
|
pageLoadStates[primary.index].loaded,
|
||||||
|
isPreloadMode,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
shouldLoad,
|
shouldLoad,
|
||||||
@@ -89,6 +90,7 @@ const BaseReaderDoublePagedPager = forwardRef<
|
|||||||
pagesIndex,
|
pagesIndex,
|
||||||
false,
|
false,
|
||||||
pageLoadStates[secondary.index].loaded,
|
pageLoadStates[secondary.index].loaded,
|
||||||
|
isPreloadMode,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
shouldLoad,
|
shouldLoad,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { createReaderPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
|||||||
const BaseReaderHorizontalPager = forwardRef<
|
const BaseReaderHorizontalPager = forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
ReaderPagerProps & Pick<IReaderSettings, 'pageGap' | 'readingDirection'>
|
ReaderPagerProps & Pick<IReaderSettings, 'pageGap' | 'readingDirection'>
|
||||||
>(({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, ...props }, ref) => {
|
>(({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, isPreloadMode, ...props }, ref) => {
|
||||||
const { currentPageIndex, totalPages, pageGap, readingDirection } = props;
|
const { currentPageIndex, totalPages, pageGap, readingDirection } = props;
|
||||||
|
|
||||||
const { direction: themeDirection } = useTheme();
|
const { direction: themeDirection } = useTheme();
|
||||||
@@ -33,10 +33,11 @@ const BaseReaderHorizontalPager = forwardRef<
|
|||||||
pagesIndex,
|
pagesIndex,
|
||||||
true,
|
true,
|
||||||
pageLoadStates[page.primary.index].loaded,
|
pageLoadStates[page.primary.index].loaded,
|
||||||
|
isPreloadMode,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
shouldLoad,
|
shouldLoad,
|
||||||
true,
|
!isPreloadMode,
|
||||||
currentPageIndex,
|
currentPageIndex,
|
||||||
totalPages,
|
totalPages,
|
||||||
...baseProps,
|
...baseProps,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { ReaderPagerProps } from '@/modules/reader/types/Reader.types.ts';
|
|||||||
import { createReaderPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
import { createReaderPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
||||||
|
|
||||||
const BaseReaderPagedPager = forwardRef<HTMLDivElement, ReaderPagerProps>(
|
const BaseReaderPagedPager = forwardRef<HTMLDivElement, ReaderPagerProps>(
|
||||||
({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, ...props }, ref) => {
|
({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, isPreloadMode, ...props }, ref) => {
|
||||||
const { currentPageIndex, totalPages } = props;
|
const { currentPageIndex, totalPages } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -25,6 +25,7 @@ const BaseReaderPagedPager = forwardRef<HTMLDivElement, ReaderPagerProps>(
|
|||||||
pagesIndex,
|
pagesIndex,
|
||||||
true,
|
true,
|
||||||
pageLoadStates[page.primary.index].loaded,
|
pageLoadStates[page.primary.index].loaded,
|
||||||
|
isPreloadMode,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
shouldLoad,
|
shouldLoad,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { ReaderPagerProps, ReadingMode } from '@/modules/reader/types/Reader.typ
|
|||||||
import { createReaderPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
import { createReaderPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
||||||
|
|
||||||
const BaseReaderVerticalPager = forwardRef<HTMLDivElement, ReaderPagerProps>(
|
const BaseReaderVerticalPager = forwardRef<HTMLDivElement, ReaderPagerProps>(
|
||||||
({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, ...props }, ref) => {
|
({ onLoad, onError, pageLoadStates, retryFailedPagesKeyPrefix, isPreloadMode, ...props }, ref) => {
|
||||||
const { currentPageIndex, totalPages, readingMode, pageGap } = props;
|
const { currentPageIndex, totalPages, readingMode, pageGap } = props;
|
||||||
|
|
||||||
const isWebtoonMode = readingMode === ReadingMode.WEBTOON;
|
const isWebtoonMode = readingMode === ReadingMode.WEBTOON;
|
||||||
@@ -28,10 +28,11 @@ const BaseReaderVerticalPager = forwardRef<HTMLDivElement, ReaderPagerProps>(
|
|||||||
pagesIndex,
|
pagesIndex,
|
||||||
true,
|
true,
|
||||||
pageLoadStates[page.primary.index].loaded,
|
pageLoadStates[page.primary.index].loaded,
|
||||||
|
isPreloadMode,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
shouldLoad,
|
shouldLoad,
|
||||||
true,
|
!isPreloadMode,
|
||||||
currentPageIndex,
|
currentPageIndex,
|
||||||
totalPages,
|
totalPages,
|
||||||
...baseProps,
|
...baseProps,
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ export const READER_STATE_CHAPTERS_DEFAULTS: Omit<ReaderStateChapters, 'setReade
|
|||||||
trailing: 0,
|
trailing: 0,
|
||||||
lastLeadingChapterSourceOrder: 99999,
|
lastLeadingChapterSourceOrder: 99999,
|
||||||
lastTrailingChapterSourceOrder: -1,
|
lastTrailingChapterSourceOrder: -1,
|
||||||
|
isLeadingChapterPreloadMode: true,
|
||||||
|
isTrailingChapterPreloadMode: true,
|
||||||
scrollIntoView: false,
|
scrollIntoView: false,
|
||||||
resumeMode: undefined,
|
resumeMode: undefined,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ export const useReaderSetChaptersState = (
|
|||||||
lastTrailingChapterSourceOrder:
|
lastTrailingChapterSourceOrder:
|
||||||
newInitialChapter?.sourceOrder ??
|
newInitialChapter?.sourceOrder ??
|
||||||
READER_STATE_CHAPTERS_DEFAULTS.visibleChapters.lastTrailingChapterSourceOrder,
|
READER_STATE_CHAPTERS_DEFAULTS.visibleChapters.lastTrailingChapterSourceOrder,
|
||||||
|
isLeadingChapterPreloadMode: false,
|
||||||
|
isTrailingChapterPreloadMode: false,
|
||||||
}
|
}
|
||||||
: prevState.visibleChapters,
|
: prevState.visibleChapters,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -236,6 +236,8 @@ export class ReaderControls {
|
|||||||
prevState,
|
prevState,
|
||||||
chapterToOpen.sourceOrder,
|
chapterToOpen.sourceOrder,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
|
isPreviousChapter ? false : undefined,
|
||||||
|
!isPreviousChapter ? false : undefined,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -448,8 +450,15 @@ export class ReaderControls {
|
|||||||
endReached?: boolean,
|
endReached?: boolean,
|
||||||
) => void {
|
) => void {
|
||||||
const { currentPageIndex, setCurrentPageIndex } = userReaderStatePagesContext();
|
const { currentPageIndex, setCurrentPageIndex } = userReaderStatePagesContext();
|
||||||
const { chapterForDuplicatesHandling, currentChapter, nextChapter, mangaChapters } =
|
const {
|
||||||
useReaderStateChaptersContext();
|
chapterForDuplicatesHandling,
|
||||||
|
currentChapter,
|
||||||
|
previousChapter,
|
||||||
|
nextChapter,
|
||||||
|
mangaChapters,
|
||||||
|
visibleChapters,
|
||||||
|
setReaderStateChapters,
|
||||||
|
} = useReaderStateChaptersContext();
|
||||||
const updateChapter = ReaderService.useUpdateChapter();
|
const updateChapter = ReaderService.useUpdateChapter();
|
||||||
const { shouldSkipDupChapters } = ReaderService.useSettings();
|
const { shouldSkipDupChapters } = ReaderService.useSettings();
|
||||||
const {
|
const {
|
||||||
@@ -470,13 +479,28 @@ export class ReaderControls {
|
|||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(pageIndex, debounceChapterUpdate = true, endReached = false) => {
|
(pageIndex, debounceChapterUpdate = true, endReached = false) => {
|
||||||
|
if (pageIndex === currentPageIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setCurrentPageIndex(pageIndex);
|
setCurrentPageIndex(pageIndex);
|
||||||
|
|
||||||
if (!currentChapter) {
|
if (!currentChapter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const direction = currentPageIndex > pageIndex ? DirectionOffset.PREVIOUS : DirectionOffset.NEXT;
|
||||||
|
|
||||||
ReaderService.downloadAhead(currentChapter, nextChapter, nextChapters, pageIndex, downloadAheadLimit);
|
ReaderService.downloadAhead(currentChapter, nextChapter, nextChapters, pageIndex, downloadAheadLimit);
|
||||||
|
ReaderService.preloadChapter(
|
||||||
|
pageIndex,
|
||||||
|
currentChapter.pageCount,
|
||||||
|
direction === DirectionOffset.NEXT ? nextChapter : previousChapter,
|
||||||
|
visibleChapters.lastLeadingChapterSourceOrder,
|
||||||
|
visibleChapters.lastTrailingChapterSourceOrder,
|
||||||
|
setReaderStateChapters,
|
||||||
|
direction,
|
||||||
|
);
|
||||||
|
|
||||||
const handleCurrentPageIndexChange = () => {
|
const handleCurrentPageIndexChange = () => {
|
||||||
const currentChapterUpToDate = getReaderChapterFromCache(currentChapter.id);
|
const currentChapterUpToDate = getReaderChapterFromCache(currentChapter.id);
|
||||||
@@ -501,7 +525,15 @@ export class ReaderControls {
|
|||||||
|
|
||||||
handleCurrentPageIndexChange();
|
handleCurrentPageIndexChange();
|
||||||
},
|
},
|
||||||
[currentChapter?.id, nextChapter?.id, nextChapters, currentPageIndex, downloadAheadLimit],
|
[
|
||||||
|
currentChapter?.id,
|
||||||
|
previousChapter?.id,
|
||||||
|
nextChapter?.id,
|
||||||
|
nextChapters,
|
||||||
|
currentPageIndex,
|
||||||
|
downloadAheadLimit,
|
||||||
|
visibleChapters,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
ReaderExitMode,
|
ReaderExitMode,
|
||||||
ReaderOverlayMode,
|
ReaderOverlayMode,
|
||||||
ReaderResumeMode,
|
ReaderResumeMode,
|
||||||
|
ReaderStateChapters,
|
||||||
ReadingDirection,
|
ReadingDirection,
|
||||||
ReadingMode,
|
ReadingMode,
|
||||||
} from '@/modules/reader/types/Reader.types.ts';
|
} from '@/modules/reader/types/Reader.types.ts';
|
||||||
@@ -44,6 +45,8 @@ import {
|
|||||||
getChapterIdsForDownloadAhead,
|
getChapterIdsForDownloadAhead,
|
||||||
getChapterIdsToDeleteForChapterUpdate,
|
getChapterIdsToDeleteForChapterUpdate,
|
||||||
getReaderChapterFromCache,
|
getReaderChapterFromCache,
|
||||||
|
isInDownloadAheadRange,
|
||||||
|
updateReaderStateVisibleChapters,
|
||||||
} from '@/modules/reader/utils/Reader.utils.ts';
|
} from '@/modules/reader/utils/Reader.utils.ts';
|
||||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
import { Queue } from '@/lib/Queue.ts';
|
import { Queue } from '@/lib/Queue.ts';
|
||||||
@@ -118,6 +121,42 @@ export class ReaderService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static preloadChapter(
|
||||||
|
pageIndex: number,
|
||||||
|
pageCount: number,
|
||||||
|
chapter: TChapterReader | undefined | null,
|
||||||
|
lastLeadingChapterSourceOrder: number,
|
||||||
|
lastTrailingChapterSourceOrder: number,
|
||||||
|
setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'],
|
||||||
|
direction: DirectionOffset,
|
||||||
|
): void {
|
||||||
|
if (!chapter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isPreviousChapter = direction === DirectionOffset.PREVIOUS;
|
||||||
|
const isNextChapter = direction === DirectionOffset.NEXT;
|
||||||
|
|
||||||
|
const isAlreadyPreloaded =
|
||||||
|
(isPreviousChapter && lastLeadingChapterSourceOrder <= chapter.sourceOrder) ||
|
||||||
|
(isNextChapter && lastTrailingChapterSourceOrder >= chapter.sourceOrder);
|
||||||
|
const shouldPreload = !isAlreadyPreloaded && isInDownloadAheadRange(pageIndex, pageCount, direction);
|
||||||
|
if (!shouldPreload) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setReaderStateChapters((state) =>
|
||||||
|
updateReaderStateVisibleChapters(
|
||||||
|
isPreviousChapter,
|
||||||
|
state,
|
||||||
|
chapter.sourceOrder,
|
||||||
|
false,
|
||||||
|
isPreviousChapter ? true : undefined,
|
||||||
|
isNextChapter ? true : undefined,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static useUpdateChapter(): (patch: UpdateChapterPatchInput) => void {
|
static useUpdateChapter(): (patch: UpdateChapterPatchInput) => void {
|
||||||
const { manga } = useReaderStateMangaContext();
|
const { manga } = useReaderStateMangaContext();
|
||||||
const { chapterForDuplicatesHandling, currentChapter, mangaChapters } = useReaderStateChaptersContext();
|
const { chapterForDuplicatesHandling, currentChapter, mangaChapters } = useReaderStateChaptersContext();
|
||||||
|
|||||||
@@ -213,6 +213,8 @@ export interface ReaderStateChapters {
|
|||||||
trailing: number;
|
trailing: number;
|
||||||
lastLeadingChapterSourceOrder: number;
|
lastLeadingChapterSourceOrder: number;
|
||||||
lastTrailingChapterSourceOrder: number;
|
lastTrailingChapterSourceOrder: number;
|
||||||
|
isLeadingChapterPreloadMode: boolean;
|
||||||
|
isTrailingChapterPreloadMode: boolean;
|
||||||
scrollIntoView: boolean;
|
scrollIntoView: boolean;
|
||||||
resumeMode?: ReaderResumeMode;
|
resumeMode?: ReaderResumeMode;
|
||||||
};
|
};
|
||||||
@@ -289,6 +291,7 @@ export interface ReaderPagerProps
|
|||||||
isCurrentChapter: boolean;
|
isCurrentChapter: boolean;
|
||||||
isPreviousChapter: boolean;
|
isPreviousChapter: boolean;
|
||||||
isNextChapter: boolean;
|
isNextChapter: boolean;
|
||||||
|
isPreloadMode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PageInViewportType {
|
export enum PageInViewportType {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { CHAPTER_READER_FIELDS } from '@/lib/graphql/fragments/ChapterFragments.
|
|||||||
import { isPageOfOutdatedPageLoadStates, isSpreadPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
import { isPageOfOutdatedPageLoadStates, isSpreadPage } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
||||||
import { ReaderStatePages } from '@/modules/reader/types/ReaderProgressBar.types.ts';
|
import { ReaderStatePages } from '@/modules/reader/types/ReaderProgressBar.types.ts';
|
||||||
import { coerceIn } from '@/lib/HelperFunctions.ts';
|
import { coerceIn } from '@/lib/HelperFunctions.ts';
|
||||||
|
import { DirectionOffset } from '@/Base.types.ts';
|
||||||
|
|
||||||
export const getInitialReaderPageIndex = (
|
export const getInitialReaderPageIndex = (
|
||||||
resumeMode: ReaderResumeMode,
|
resumeMode: ReaderResumeMode,
|
||||||
@@ -76,6 +77,20 @@ export const getChapterIdsToDeleteForChapterUpdate = (
|
|||||||
return Chapters.getIds(Chapters.addDuplicates([chapterToDelete], chapters));
|
return Chapters.getIds(Chapters.addDuplicates([chapterToDelete], chapters));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isInDownloadAheadRange = (
|
||||||
|
currentPageIndex: number,
|
||||||
|
pageCount: number,
|
||||||
|
direction: DirectionOffset = DirectionOffset.NEXT,
|
||||||
|
): boolean => {
|
||||||
|
const progress = (currentPageIndex + 1) / pageCount;
|
||||||
|
|
||||||
|
if (direction === DirectionOffset.PREVIOUS) {
|
||||||
|
return progress < 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
return progress > 0.25;
|
||||||
|
};
|
||||||
|
|
||||||
export const getChapterIdsForDownloadAhead = (
|
export const getChapterIdsForDownloadAhead = (
|
||||||
chapter: TChapterReader,
|
chapter: TChapterReader,
|
||||||
nextChapter: TChapterReader | undefined,
|
nextChapter: TChapterReader | undefined,
|
||||||
@@ -89,8 +104,10 @@ export const getChapterIdsForDownloadAhead = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isDownloadAheadEnabled = !!downloadAheadLimit;
|
const isDownloadAheadEnabled = !!downloadAheadLimit;
|
||||||
const inDownloadRange = (currentPageIndex + 1) / chapterUpToDateData.pageCount > 0.25;
|
const shouldCheckDownloadAhead =
|
||||||
const shouldCheckDownloadAhead = isDownloadAheadEnabled && chapterUpToDateData.isDownloaded && inDownloadRange;
|
isDownloadAheadEnabled &&
|
||||||
|
chapterUpToDateData.isDownloaded &&
|
||||||
|
isInDownloadAheadRange(currentPageIndex, chapterUpToDateData.pageCount);
|
||||||
if (!shouldCheckDownloadAhead) {
|
if (!shouldCheckDownloadAhead) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -208,6 +225,8 @@ export const updateReaderStateVisibleChapters = (
|
|||||||
state: Omit<ReaderStateChapters, 'setReaderStateChapters'>,
|
state: Omit<ReaderStateChapters, 'setReaderStateChapters'>,
|
||||||
chapterToOpenSourceOrder: TChapterReader['sourceOrder'],
|
chapterToOpenSourceOrder: TChapterReader['sourceOrder'],
|
||||||
scrollIntoView: boolean,
|
scrollIntoView: boolean,
|
||||||
|
isLeadingChapterPreloadMode?: boolean,
|
||||||
|
isTrailingChapterPreloadMode?: boolean,
|
||||||
): Omit<ReaderStateChapters, 'setReaderStateChapters'> => {
|
): Omit<ReaderStateChapters, 'setReaderStateChapters'> => {
|
||||||
const { leading, trailing, lastLeadingChapterSourceOrder, lastTrailingChapterSourceOrder } = state.visibleChapters;
|
const { leading, trailing, lastLeadingChapterSourceOrder, lastTrailingChapterSourceOrder } = state.visibleChapters;
|
||||||
|
|
||||||
@@ -226,6 +245,14 @@ export const updateReaderStateVisibleChapters = (
|
|||||||
lastTrailingChapterSourceOrder: isNewTrailingChapter
|
lastTrailingChapterSourceOrder: isNewTrailingChapter
|
||||||
? chapterToOpenSourceOrder
|
? chapterToOpenSourceOrder
|
||||||
: lastTrailingChapterSourceOrder,
|
: lastTrailingChapterSourceOrder,
|
||||||
|
isLeadingChapterPreloadMode:
|
||||||
|
isLeadingChapterPreloadMode !== undefined
|
||||||
|
? isLeadingChapterPreloadMode
|
||||||
|
: state.visibleChapters.isLeadingChapterPreloadMode,
|
||||||
|
isTrailingChapterPreloadMode:
|
||||||
|
isTrailingChapterPreloadMode !== undefined
|
||||||
|
? isTrailingChapterPreloadMode
|
||||||
|
: state.visibleChapters.isTrailingChapterPreloadMode,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
resumeMode: isPreviousChapter ? ReaderResumeMode.END : ReaderResumeMode.START,
|
resumeMode: isPreviousChapter ? ReaderResumeMode.END : ReaderResumeMode.START,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -267,8 +267,9 @@ const getPageDownloadPriority = (
|
|||||||
pageIndex: number,
|
pageIndex: number,
|
||||||
totalPages: number,
|
totalPages: number,
|
||||||
shouldLoad: boolean,
|
shouldLoad: boolean,
|
||||||
|
isPreloadMode: boolean,
|
||||||
): number => {
|
): number => {
|
||||||
if (!shouldLoad) {
|
if (!shouldLoad || isPreloadMode) {
|
||||||
return Number.MAX_SAFE_INTEGER;
|
return Number.MAX_SAFE_INTEGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,6 +289,7 @@ export const createReaderPage = (
|
|||||||
pagesIndex: number,
|
pagesIndex: number,
|
||||||
isPrimaryPage: boolean,
|
isPrimaryPage: boolean,
|
||||||
isLoaded: boolean,
|
isLoaded: boolean,
|
||||||
|
isPreloadMode: boolean,
|
||||||
onLoad: ComponentProps<typeof ReaderPage>['onLoad'],
|
onLoad: ComponentProps<typeof ReaderPage>['onLoad'],
|
||||||
onError: ComponentProps<typeof ReaderPage>['onError'],
|
onError: ComponentProps<typeof ReaderPage>['onError'],
|
||||||
shouldLoad: boolean,
|
shouldLoad: boolean,
|
||||||
@@ -317,7 +319,7 @@ export const createReaderPage = (
|
|||||||
src={url}
|
src={url}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
display={display}
|
display={display}
|
||||||
priority={getPageDownloadPriority(currentPageIndex, index, totalPages, shouldLoad)}
|
priority={getPageDownloadPriority(currentPageIndex, index, totalPages, shouldLoad, isPreloadMode)}
|
||||||
position={position}
|
position={position}
|
||||||
onLoad={onLoad}
|
onLoad={onLoad}
|
||||||
onError={onError}
|
onError={onError}
|
||||||
|
|||||||
Reference in New Issue
Block a user