Add option to disable "infinite chapter scroll"

This commit is contained in:
schroda
2025-04-26 23:19:01 +02:00
parent f9930b94ca
commit beda5096d1
10 changed files with 67 additions and 20 deletions

View File

@@ -946,6 +946,10 @@
"stretch_image": "Toggle stretch image" "stretch_image": "Toggle stretch image"
}, },
"image_preload_amount": "Preload images", "image_preload_amount": "Preload images",
"infinite_scroll": {
"description": "Keep previous and upcoming chapters visible while reading in continuous reading modes, allowing seamless scrolling between chapters.",
"title": "Continuous chapter display"
},
"label": { "label": {
"behaviour": "Behaviour", "behaviour": "Behaviour",
"fit_page_to_window": "Fit page to window", "fit_page_to_window": "Fit page to window",

View File

@@ -87,6 +87,7 @@ const APP_METADATA_OBJECT: Record<AppMetadataKeys, undefined> = {
showChapterNumber: undefined, showChapterNumber: undefined,
extensionLanguages: undefined, extensionLanguages: undefined,
showNsfw: undefined, showNsfw: undefined,
shouldUseInfiniteScroll: undefined,
}; };
export const VALID_APP_METADATA_KEYS = Object.keys(APP_METADATA_OBJECT); export const VALID_APP_METADATA_KEYS = Object.keys(APP_METADATA_OBJECT);

View File

@@ -54,6 +54,18 @@ export const ReaderBehaviourSettings = ({
onChange={(_, checked) => updateSetting('shouldOffsetDoubleSpreads', checked)} onChange={(_, checked) => updateSetting('shouldOffsetDoubleSpreads', checked)}
/> />
)} )}
<CheckboxInput
label={
<Box>
<Typography>{t('reader.settings.infinite_scroll.title')}</Typography>
<Typography variant="body2" color="textDisabled">
{t('reader.settings.infinite_scroll.description')}
</Typography>
</Box>
}
checked={settings.shouldUseInfiniteScroll}
onChange={(_, checked) => updateSetting('shouldUseInfiniteScroll', checked)}
/>
<CheckboxInput <CheckboxInput
label={ label={
<Box> <Box>

View File

@@ -64,6 +64,7 @@ const BaseReaderChapterViewer = ({
pageScaleMode, pageScaleMode,
shouldOffsetDoubleSpreads, shouldOffsetDoubleSpreads,
readingDirection, readingDirection,
shouldUseInfiniteScroll,
imagePreLoadAmount, imagePreLoadAmount,
pageGap, pageGap,
chapterId, chapterId,
@@ -107,7 +108,12 @@ const BaseReaderChapterViewer = ({
Omit<ReaderPagerProps, 'pages' | 'totalPages' | 'pageLoadStates' | 'handleAsInitialRender' | 'resumeMode'> & Omit<ReaderPagerProps, 'pages' | 'totalPages' | 'pageLoadStates' | 'handleAsInitialRender' | 'resumeMode'> &
Pick< Pick<
IReaderSettings, IReaderSettings,
'readingMode' | 'shouldOffsetDoubleSpreads' | 'readingDirection' | 'readerWidth' | 'pageScaleMode' | 'readingMode'
| 'shouldOffsetDoubleSpreads'
| 'readingDirection'
| 'readerWidth'
| 'pageScaleMode'
| 'shouldUseInfiniteScroll'
> & > &
Pick<ReaderStateChapters, 'setReaderStateChapters'> & { Pick<ReaderStateChapters, 'setReaderStateChapters'> & {
updateCurrentPageIndex: ReturnType<typeof ReaderControls.useUpdateCurrentPageIndex>; updateCurrentPageIndex: ReturnType<typeof ReaderControls.useUpdateCurrentPageIndex>;
@@ -412,6 +418,7 @@ const BaseReaderChapterViewer = ({
<ReaderInfiniteScrollUpdateChapter <ReaderInfiniteScrollUpdateChapter
readingMode={readingMode} readingMode={readingMode}
readingDirection={readingDirection} readingDirection={readingDirection}
shouldUseInfiniteScroll={shouldUseInfiniteScroll}
chapterId={chapterId} chapterId={chapterId}
previousChapterId={previousChapterId} previousChapterId={previousChapterId}
nextChapterId={nextChapterId} nextChapterId={nextChapterId}

View File

@@ -9,13 +9,14 @@
import { memo } from 'react'; import { memo } from 'react';
import { withPropsFrom } from '@/modules/core/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/modules/core/hoc/withPropsFrom.tsx';
import { useReaderInfiniteScrollUpdateChapter } from '@/modules/reader/hooks/useReaderInfiniteScrollUpdateChapter.ts'; import { useReaderInfiniteScrollUpdateChapter } from '@/modules/reader/hooks/useReaderInfiniteScrollUpdateChapter.ts';
import { ReadingDirection, ReadingMode, TReaderScrollbarContext } from '@/modules/reader/types/Reader.types.ts'; import { IReaderSettings, TReaderScrollbarContext } from '@/modules/reader/types/Reader.types.ts';
import { ReaderControls } from '@/modules/reader/services/ReaderControls.ts'; import { ReaderControls } from '@/modules/reader/services/ReaderControls.ts';
import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts'; import { ChapterIdInfo } from '@/modules/chapter/services/Chapters.ts';
const BaseReaderInfiniteScrollUpdateChapter = ({ const BaseReaderInfiniteScrollUpdateChapter = ({
readingMode, readingMode,
readingDirection, readingDirection,
shouldUseInfiniteScroll,
chapterId, chapterId,
previousChapterId, previousChapterId,
nextChapterId, nextChapterId,
@@ -27,9 +28,8 @@ const BaseReaderInfiniteScrollUpdateChapter = ({
scrollbarXSize, scrollbarXSize,
scrollbarYSize, scrollbarYSize,
scrollElement, scrollElement,
}: Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> & { }: Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> &
readingMode: ReadingMode; Pick<IReaderSettings, 'readingMode' | 'readingDirection' | 'shouldUseInfiniteScroll'> & {
readingDirection: ReadingDirection;
chapterId: ChapterIdInfo['id']; chapterId: ChapterIdInfo['id'];
previousChapterId?: ChapterIdInfo['id']; previousChapterId?: ChapterIdInfo['id'];
nextChapterId?: ChapterIdInfo['id']; nextChapterId?: ChapterIdInfo['id'];
@@ -48,6 +48,7 @@ const BaseReaderInfiniteScrollUpdateChapter = ({
isPreviousChapterVisible, isPreviousChapterVisible,
readingMode, readingMode,
readingDirection, readingDirection,
shouldUseInfiniteScroll,
openChapter, openChapter,
imageWrapper, imageWrapper,
scrollbarXSize, scrollbarXSize,
@@ -62,6 +63,7 @@ const BaseReaderInfiniteScrollUpdateChapter = ({
isNextChapterVisible, isNextChapterVisible,
readingMode, readingMode,
readingDirection, readingDirection,
shouldUseInfiniteScroll,
openChapter, openChapter,
imageWrapper, imageWrapper,
scrollbarXSize, scrollbarXSize,

View File

@@ -94,6 +94,7 @@ const BaseReaderViewer = forwardRef(
setTransitionPageMode, setTransitionPageMode,
readingMode, readingMode,
readingDirection, readingDirection,
shouldUseInfiniteScroll,
readerWidth, readerWidth,
pageScaleMode, pageScaleMode,
shouldOffsetDoubleSpreads, shouldOffsetDoubleSpreads,
@@ -134,6 +135,7 @@ const BaseReaderViewer = forwardRef(
IReaderSettings, IReaderSettings,
| 'readingMode' | 'readingMode'
| 'readingDirection' | 'readingDirection'
| 'shouldUseInfiniteScroll'
| 'readerWidth' | 'readerWidth'
| 'pageScaleMode' | 'pageScaleMode'
| 'shouldOffsetDoubleSpreads' | 'shouldOffsetDoubleSpreads'
@@ -408,6 +410,7 @@ const BaseReaderViewer = forwardRef(
pageScaleMode={pageScaleMode} pageScaleMode={pageScaleMode}
shouldOffsetDoubleSpreads={shouldOffsetDoubleSpreads} shouldOffsetDoubleSpreads={shouldOffsetDoubleSpreads}
readingDirection={readingDirection} readingDirection={readingDirection}
shouldUseInfiniteScroll={shouldUseInfiniteScroll}
updateCurrentPageIndex={isCurrentChapter ? updateCurrentPageIndex : noOp} updateCurrentPageIndex={isCurrentChapter ? updateCurrentPageIndex : noOp}
scrollIntoView={isCurrentChapter && visibleChapters.scrollIntoView} scrollIntoView={isCurrentChapter && visibleChapters.scrollIntoView}
resumeMode={getReaderChapterViewResumeMode( resumeMode={getReaderChapterViewResumeMode(
@@ -465,6 +468,7 @@ export const ReaderViewer = withPropsFrom(
'setTransitionPageMode', 'setTransitionPageMode',
'readingMode', 'readingMode',
'readingDirection', 'readingDirection',
'shouldUseInfiniteScroll',
'readerWidth', 'readerWidth',
'pageScaleMode', 'pageScaleMode',
'shouldOffsetDoubleSpreads', 'shouldOffsetDoubleSpreads',

View File

@@ -71,6 +71,7 @@ const GLOBAL_READER_SETTING_OBJECT: Record<keyof IReaderSettingsGlobal, undefine
shouldInformAboutMissingChapter: undefined, shouldInformAboutMissingChapter: undefined,
shouldInformAboutScanlatorChange: undefined, shouldInformAboutScanlatorChange: undefined,
scrollAmount: undefined, scrollAmount: undefined,
shouldUseInfiniteScroll: undefined,
}; };
export const GLOBAL_READER_SETTING_KEYS = Object.keys(GLOBAL_READER_SETTING_OBJECT); export const GLOBAL_READER_SETTING_KEYS = Object.keys(GLOBAL_READER_SETTING_OBJECT);
@@ -155,6 +156,7 @@ export const DEFAULT_READER_SETTINGS: IReaderSettings = {
shouldInformAboutMissingChapter: true, shouldInformAboutMissingChapter: true,
shouldInformAboutScanlatorChange: true, shouldInformAboutScanlatorChange: true,
scrollAmount: ReaderScrollAmount.LARGE, scrollAmount: ReaderScrollAmount.LARGE,
shouldUseInfiniteScroll: true,
}; };
export const READER_PROGRESS_BAR_POSITION_TO_PLACEMENT: Record<ProgressBarPosition, TooltipProps['placement']> = { export const READER_PROGRESS_BAR_POSITION_TO_PLACEMENT: Record<ProgressBarPosition, TooltipProps['placement']> = {

View File

@@ -240,6 +240,7 @@ export const useReaderInfiniteScrollUpdateChapter = (
isChapterToOpenVisible: boolean, isChapterToOpenVisible: boolean,
readingMode: ReadingMode, readingMode: ReadingMode,
readingDirection: ReadingDirection, readingDirection: ReadingDirection,
shouldUseInfiniteScroll: boolean,
openChapter: ReturnType<typeof ReaderControls.useOpenChapter>, openChapter: ReturnType<typeof ReaderControls.useOpenChapter>,
image: HTMLElement | null, image: HTMLElement | null,
scrollbarXSize: number, scrollbarXSize: number,
@@ -250,7 +251,11 @@ export const useReaderInfiniteScrollUpdateChapter = (
image, image,
useCallback( useCallback(
(entries) => { (entries) => {
if (!isContinuousReadingMode(readingMode) || chapterToOpenId === undefined) { if (
!shouldUseInfiniteScroll ||
!isContinuousReadingMode(readingMode) ||
chapterToOpenId === undefined
) {
return; return;
} }
@@ -297,6 +302,7 @@ export const useReaderInfiniteScrollUpdateChapter = (
isChapterToOpenVisible, isChapterToOpenVisible,
readingMode, readingMode,
readingDirection, readingDirection,
shouldUseInfiniteScroll,
openChapter, openChapter,
scrollbarXSize, scrollbarXSize,
scrollbarYSize, scrollbarYSize,

View File

@@ -175,8 +175,12 @@ export class ReaderControls {
scrollIntoView?: boolean, scrollIntoView?: boolean,
) => void { ) => void {
const { t } = useTranslation(); const { t } = useTranslation();
const { readingMode, shouldInformAboutMissingChapter, shouldInformAboutScanlatorChange } = const {
ReaderService.useSettings(); readingMode,
shouldInformAboutMissingChapter,
shouldInformAboutScanlatorChange,
shouldUseInfiniteScroll,
} = ReaderService.useSettings();
const { const {
currentChapter, currentChapter,
previousChapter, previousChapter,
@@ -239,7 +243,7 @@ export class ReaderControls {
const isAlreadyLoaded = const isAlreadyLoaded =
lastLeadingChapterSourceOrder <= chapterToOpen.sourceOrder && lastLeadingChapterSourceOrder <= chapterToOpen.sourceOrder &&
lastTrailingChapterSourceOrder >= chapterToOpen.sourceOrder; lastTrailingChapterSourceOrder >= chapterToOpen.sourceOrder;
const keepRenderedChapters = !scrollIntoView || isAlreadyLoaded; const keepRenderedChapters = shouldUseInfiniteScroll && (!scrollIntoView || isAlreadyLoaded);
if (keepRenderedChapters) { if (keepRenderedChapters) {
setReaderStateChapters((prevState) => setReaderStateChapters((prevState) =>
@@ -255,7 +259,10 @@ export class ReaderControls {
} }
openChapter(chapterToOpen, { openChapter(chapterToOpen, {
resumeMode: getReaderOpenChapterResumeMode(isSpecificChapterMode, isPreviousChapter), resumeMode: getReaderOpenChapterResumeMode(
isSpecificChapterMode || !keepRenderedChapters,
isPreviousChapter,
),
updateInitialChapter: !keepRenderedChapters, updateInitialChapter: !keepRenderedChapters,
}); });
} catch (error) { } catch (error) {
@@ -274,6 +281,7 @@ export class ReaderControls {
shouldInformAboutScanlatorChange, shouldInformAboutScanlatorChange,
lastLeadingChapterSourceOrder, lastLeadingChapterSourceOrder,
lastTrailingChapterSourceOrder, lastTrailingChapterSourceOrder,
shouldUseInfiniteScroll,
], ],
); );
} }

View File

@@ -160,6 +160,7 @@ export interface IReaderSettingsGlobal {
shouldInformAboutMissingChapter: boolean; shouldInformAboutMissingChapter: boolean;
shouldInformAboutScanlatorChange: boolean; shouldInformAboutScanlatorChange: boolean;
scrollAmount: ReaderScrollAmount; scrollAmount: ReaderScrollAmount;
shouldUseInfiniteScroll: boolean;
} }
export interface IReaderSettingsManga { export interface IReaderSettingsManga {