Files
suwayomi-material-you-webui/src/modules/reader/contexts/ReaderAutoScrollContextProvider.tsx
schroda da78ce3181 Add hotkeys to switch auto scroll direction
While auto scroll is active, the direction can be changed via the "scroll backward/forward" hotkeys
2025-07-04 18:43:32 +02:00

90 lines
3.5 KiB
TypeScript

/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { memo, ReactNode, useCallback, useMemo, useState } from 'react';
import { Direction, useTheme } from '@mui/material/styles';
import { useAutomaticScrolling } from '@/modules/core/hooks/useAutomaticScrolling.ts';
import {
IReaderSettings,
ReaderScrollAmount,
ReadingMode,
TReaderAutoScrollContext,
} from '@/modules/reader/types/Reader.types.ts';
import { ReaderAutoScrollContext } from '@/modules/reader/contexts/ReaderAutoScrollContext.tsx';
import { ReaderControls } from '@/modules/reader/services/ReaderControls';
import { isContinuousReadingMode } from '@/modules/reader/utils/ReaderSettings.utils.tsx';
import { withPropsFrom } from '@/modules/core/hoc/withPropsFrom.tsx';
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
import { CONTINUOUS_READING_MODE_TO_SCROLL_DIRECTION } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
import { ScrollOffset } from '@/modules/core/Core.types.ts';
import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
const BaseReaderAutoScrollContextProvider = ({
children,
openPage,
readingMode,
autoScroll,
themeDirection,
combinedDirection,
}: Pick<IReaderSettings, 'readingMode' | 'autoScroll'> & {
children: ReactNode;
openPage: ReturnType<typeof ReaderControls.useOpenPage>;
themeDirection: Direction;
combinedDirection: Direction;
}) => {
const [scrollRef, setScrollRef] = useState<TReaderAutoScrollContext['scrollRef']>();
const [direction, setDirection] = useState<ScrollOffset>(ScrollOffset.FORWARD);
const isScrollingInvertedBasedOnReadingDirection =
readingMode === ReadingMode.CONTINUOUS_HORIZONTAL && themeDirection !== combinedDirection;
const invertScrolling = isScrollingInvertedBasedOnReadingDirection
? getOptionForDirection(
direction === ScrollOffset.BACKWARD,
direction === ScrollOffset.FORWARD,
combinedDirection,
)
: direction === ScrollOffset.BACKWARD;
const isContinuousReadingModeActive = isContinuousReadingMode(readingMode);
const changePage = useCallback(() => {
openPage('next', 'ltr');
}, [openPage]);
const automaticScrolling = useAutomaticScrolling(
isContinuousReadingModeActive ? scrollRef : changePage,
autoScroll.value,
CONTINUOUS_READING_MODE_TO_SCROLL_DIRECTION[readingMode],
ReaderScrollAmount.MEDIUM,
invertScrolling,
autoScroll.smooth,
);
const value = useMemo(
() => ({
scrollRef,
setScrollRef,
setDirection,
...automaticScrolling,
}),
[scrollRef, automaticScrolling],
);
return <ReaderAutoScrollContext.Provider value={value}>{children}</ReaderAutoScrollContext.Provider>;
};
export const ReaderAutoScrollContextProvider = withPropsFrom(
memo(BaseReaderAutoScrollContextProvider),
[
ReaderService.useSettingsWithoutDefaultFlag,
() => ({ openPage: ReaderControls.useOpenPage() }),
() => ({ themeDirection: useTheme().direction }),
() => ({ combinedDirection: ReaderService.useGetThemeDirection() }),
],
['openPage', 'readingMode', 'themeDirection', 'combinedDirection', 'autoScroll'],
);