Preload previous/next chapter in reader

This commit is contained in:
schroda
2025-02-10 01:05:35 +01:00
parent 16c1edaa52
commit 174d850093
14 changed files with 185 additions and 44 deletions

View File

@@ -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>

View File

@@ -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}

View File

@@ -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],

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,
}, },

View File

@@ -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,
}; };

View File

@@ -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,
],
); );
} }

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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,
}, },

View File

@@ -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}