Move reader "progress bar state" to "reader store"

This commit is contained in:
schroda
2025-09-20 14:29:48 +02:00
parent 98ec5257b9
commit f60b537115
8 changed files with 76 additions and 72 deletions

View File

@@ -26,6 +26,10 @@ import {
import { ImmerStateCreator } from '@/lib/zustand/Zustand.types.ts'; import { ImmerStateCreator } from '@/lib/zustand/Zustand.types.ts';
import { READER_DEFAULT_CHAPTERS_STATE, READER_DEFAULT_PAGES_STATE } from '@/features/reader/ReaderStore.constants.ts'; import { READER_DEFAULT_CHAPTERS_STATE, READER_DEFAULT_PAGES_STATE } from '@/features/reader/ReaderStore.constants.ts';
import { DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG } from '@/features/reader/settings/ReaderSettingsMetadata.ts'; import { DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG } from '@/features/reader/settings/ReaderSettingsMetadata.ts';
import {
createReaderProgressBarStoreSlice,
ReaderProgressBarStoreSlice,
} from '@/features/reader/overlay/progress-bar/ReaderProgressBarStore.tsx';
interface ReaderPagesStoreSlice { interface ReaderPagesStoreSlice {
pages: ReaderStatePages & { pages: ReaderStatePages & {
@@ -43,7 +47,8 @@ interface ReaderStore
extends ReaderOverlayStoreSlice, extends ReaderOverlayStoreSlice,
ReaderAutoScrollStoreSlice, ReaderAutoScrollStoreSlice,
ReaderPagesStoreSlice, ReaderPagesStoreSlice,
ReaderChaptersStoreSlice { ReaderChaptersStoreSlice,
ReaderProgressBarStoreSlice {
reset: () => void; reset: () => void;
manga: TMangaReader | undefined; manga: TMangaReader | undefined;
setManga: (manga: TMangaReader | undefined) => void; setManga: (manga: TMangaReader | undefined) => void;
@@ -151,6 +156,7 @@ export const useReaderStore = create<ReaderStore>()(
...get().settings, ...get().settings,
...DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG, ...DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG,
}; };
get().progressBar.reset();
}), }),
setManga: (manga) => setManga: (manga) =>
set((draft) => { set((draft) => {
@@ -181,6 +187,7 @@ export const useReaderStore = create<ReaderStore>()(
...createReaderAutoScrollStoreSlice(set, get, store), ...createReaderAutoScrollStoreSlice(set, get, store),
...createReaderPagesStoreSlice(set, get, store), ...createReaderPagesStoreSlice(set, get, store),
...createReaderChaptersStoreSlice(set, get, store), ...createReaderChaptersStoreSlice(set, get, store),
...createReaderProgressBarStoreSlice(set, get, store),
})), })),
); );
export const useReaderStoreShallow = <T>(selector: (state: ReaderStore) => T): T => export const useReaderStoreShallow = <T>(selector: (state: ReaderStore) => T): T =>

View File

@@ -7,11 +7,8 @@
*/ */
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { ReaderProgressBarContextProvider } from '@/features/reader/overlay/progress-bar/ReaderProgressBarContext.tsx';
import { ReaderTapZoneContextProvider } from '@/features/reader/tap-zones/ReaderTapZoneContext.tsx'; import { ReaderTapZoneContextProvider } from '@/features/reader/tap-zones/ReaderTapZoneContext.tsx';
export const ReaderContextProvider = ({ children }: { children?: ReactNode }) => ( export const ReaderContextProvider = ({ children }: { children?: ReactNode }) => (
<ReaderTapZoneContextProvider> <ReaderTapZoneContextProvider>{children}</ReaderTapZoneContextProvider>
<ReaderProgressBarContextProvider>{children}</ReaderProgressBarContextProvider>
</ReaderTapZoneContextProvider>
); );

View File

@@ -14,20 +14,16 @@ import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { ProgressBarType, ReadingDirection } from '@/features/reader/Reader.types.ts'; import { ProgressBarType, ReadingDirection } from '@/features/reader/Reader.types.ts';
import { getPage } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx'; import { getPage } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx';
import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx'; import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
import { useReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBarContext.tsx';
import { reverseString } from '@/base/utils/Strings.ts'; import { reverseString } from '@/base/utils/Strings.ts';
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts'; import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts'; import { useReaderStore, useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const BaseReaderPageNumber = ({ const BaseReaderPageNumber = ({
isDesktop, isDesktop,
readerNavBarWidth, readerNavBarWidth,
isMaximized,
}: Pick<ReturnType<typeof ReaderService.useOverlayMode>, 'isDesktop'> & }: Pick<ReturnType<typeof ReaderService.useOverlayMode>, 'isDesktop'> &
Pick<NavbarContextType, 'readerNavBarWidth'> & Pick<NavbarContextType, 'readerNavBarWidth'>) => {
Pick<TReaderProgressBarContext, 'isMaximized'>) => {
const scrollbar = useReaderStoreShallow((state) => state.scrollbar); const scrollbar = useReaderStoreShallow((state) => state.scrollbar);
const { currentPageIndex, pages, totalPages } = useReaderStoreShallow((state) => ({ const { currentPageIndex, pages, totalPages } = useReaderStoreShallow((state) => ({
currentPageIndex: state.pages.currentPageIndex, currentPageIndex: state.pages.currentPageIndex,
@@ -39,6 +35,7 @@ const BaseReaderPageNumber = ({
shouldShowPageNumber: state.settings.shouldShowPageNumber, shouldShowPageNumber: state.settings.shouldShowPageNumber,
progressBarType: state.settings.progressBarType, progressBarType: state.settings.progressBarType,
})); }));
const isMaximized = useReaderStore((state) => state.progressBar.isMaximized);
const pageName = useMemo(() => { const pageName = useMemo(() => {
const currentPageName = getPage(currentPageIndex, pages).name; const currentPageName = getPage(currentPageIndex, pages).name;
@@ -90,6 +87,6 @@ const BaseReaderPageNumber = ({
export const ReaderPageNumber = withPropsFrom( export const ReaderPageNumber = withPropsFrom(
BaseReaderPageNumber, BaseReaderPageNumber,
[ReaderService.useOverlayMode, useNavBarContext, useReaderProgressBarContext], [ReaderService.useOverlayMode, useNavBarContext],
['isDesktop', 'readerNavBarWidth', 'isMaximized'], ['isDesktop', 'readerNavBarWidth'],
); );

View File

@@ -11,10 +11,7 @@ import { ComponentProps, memo, ReactNode, useCallback, useMemo, useRef, useState
import ClickAwayListener from '@mui/material/ClickAwayListener'; import ClickAwayListener from '@mui/material/ClickAwayListener';
import { TypographyProps } from '@mui/material/Typography'; import { TypographyProps } from '@mui/material/Typography';
import { StackProps } from '@mui/material/Stack'; import { StackProps } from '@mui/material/Stack';
import { import { ReaderProgressBarProps } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
ReaderProgressBarProps,
TReaderProgressBarContext,
} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { ReaderProgressBarPageNumber } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarPageNumber.tsx'; import { ReaderProgressBarPageNumber } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarPageNumber.tsx';
import { ReaderProgressBarContainer } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarContainer.tsx'; import { ReaderProgressBarContainer } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarContainer.tsx';
import { ReaderProgressBarRoot } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarRoot.tsx'; import { ReaderProgressBarRoot } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarRoot.tsx';
@@ -32,7 +29,6 @@ import { ReaderProgressBarSlotsActionArea } from '@/features/reader/overlay/prog
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { ReaderControls } from '@/features/reader/services/ReaderControls.ts'; import { ReaderControls } from '@/features/reader/services/ReaderControls.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBarContext.tsx';
import { ReaderProgressBarSlotWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarSlotWrapper.tsx'; import { ReaderProgressBarSlotWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarSlotWrapper.tsx';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { ReadingMode } from '@/features/reader/Reader.types.ts'; import { ReadingMode } from '@/features/reader/Reader.types.ts';
@@ -43,13 +39,10 @@ const BaseReaderProgressBar = ({
slots, slots,
createProgressBarSlot, createProgressBarSlot,
progressBarPosition, progressBarPosition,
isDragging,
setIsDragging,
openPage, openPage,
direction, direction,
fullSegmentClicks, fullSegmentClicks,
}: ReaderProgressBarProps & }: ReaderProgressBarProps &
Pick<TReaderProgressBarContext, 'isDragging' | 'setIsDragging'> &
Pick<ComponentProps<typeof ReaderProgressBarSlotWrapper>, 'createProgressBarSlot'> & { Pick<ComponentProps<typeof ReaderProgressBarSlotWrapper>, 'createProgressBarSlot'> & {
slotProps?: { slotProps?: {
container?: StackProps; container?: StackProps;
@@ -79,6 +72,10 @@ const BaseReaderProgressBar = ({
currentPageIndex: state.pages.currentPageIndex, currentPageIndex: state.pages.currentPageIndex,
})); }));
const readingMode = useReaderStore((state) => state.settings.readingMode.value); const readingMode = useReaderStore((state) => state.settings.readingMode.value);
const { isDragging, setIsDragging } = useReaderStoreShallow((state) => ({
isDragging: state.progressBar.isDragging,
setIsDragging: state.progressBar.setIsDragging,
}));
const progressBarRef = useRef<HTMLDivElement | null>(null); const progressBarRef = useRef<HTMLDivElement | null>(null);
const draggingDetectionTimeout = useRef<NodeJS.Timeout>(undefined); const draggingDetectionTimeout = useRef<NodeJS.Timeout>(undefined);
@@ -249,6 +246,6 @@ const BaseReaderProgressBar = ({
export const ReaderProgressBar = withPropsFrom( export const ReaderProgressBar = withPropsFrom(
memo(BaseReaderProgressBar), memo(BaseReaderProgressBar),
[useReaderProgressBarContext, () => ({ openPage: ReaderControls.useOpenPage() })], [() => ({ openPage: ReaderControls.useOpenPage() })],
['isDragging', 'setIsDragging', 'openPage'], ['openPage'],
); );

View File

@@ -1,31 +0,0 @@
/*
* 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 { createContext, useContext, ReactNode, useMemo, useState } from 'react';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
export const ReaderProgressBarContext = createContext<TReaderProgressBarContext>({
isMaximized: false,
setIsMaximized: () => undefined,
isDragging: false,
setIsDragging: () => undefined,
});
export const useReaderProgressBarContext = () => useContext(ReaderProgressBarContext);
export const ReaderProgressBarContextProvider = ({ children }: { children: ReactNode }) => {
const [isMaximized, setIsMaximized] = useState(false);
const [isDragging, setIsDragging] = useState(false);
const value = useMemo(
() => ({ isMaximized, setIsMaximized, isDragging, setIsDragging }),
[isMaximized, isDragging],
);
return <ReaderProgressBarContext.Provider value={value}>{children}</ReaderProgressBarContext.Provider>;
};

View File

@@ -0,0 +1,38 @@
/*
* 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 { ImmerStateCreator } from '@/lib/zustand/Zustand.types.ts';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
export interface ReaderProgressBarStoreSlice {
progressBar: TReaderProgressBarContext & {
reset: () => void;
};
}
const DEFAULT_STATE = {
isMaximized: false,
isDragging: false,
} satisfies Pick<ReaderProgressBarStoreSlice['progressBar'], 'isDragging' | 'isMaximized'>;
export const createReaderProgressBarStoreSlice = <T extends ReaderProgressBarStoreSlice>(
...[set, get]: Parameters<ImmerStateCreator<T>>
): ReaderProgressBarStoreSlice => ({
progressBar: {
...DEFAULT_STATE,
setIsMaximized: (maximized) =>
set((draft) => {
draft.progressBar.isMaximized = maximized;
}),
setIsDragging: (dragging) =>
set((draft) => {
draft.progressBar.isDragging = dragging;
}),
reset: () => set(() => ({ progressBar: { ...get().progressBar, ...DEFAULT_STATE } })),
},
});

View File

@@ -14,11 +14,9 @@ import { ProgressBarType } from '@/features/reader/Reader.types.ts';
import { applyStyles } from '@/base/utils/ApplyStyles.ts'; import { applyStyles } from '@/base/utils/ApplyStyles.ts';
import { getProgressBarPositionInfo } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx'; import { getProgressBarPositionInfo } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx';
import { ReaderProgressBarDirectionWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarDirectionWrapper.tsx'; import { ReaderProgressBarDirectionWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarDirectionWrapper.tsx';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts'; import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx'; import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
import { useReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBarContext.tsx';
import { ReaderProgressBarSlotDesktop } from '@/features/reader/overlay/progress-bar/desktop/components/ReaderProgressBarSlotDesktop.tsx'; import { ReaderProgressBarSlotDesktop } from '@/features/reader/overlay/progress-bar/desktop/components/ReaderProgressBarSlotDesktop.tsx';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { getProgressBarPosition } from '@/features/reader/settings/ReaderSettings.utils.tsx'; import { getProgressBarPosition } from '@/features/reader/settings/ReaderSettings.utils.tsx';
@@ -26,14 +24,10 @@ import { useReaderStore, useReaderStoreShallow } from '@/features/reader/ReaderS
const BaseStandardReaderProgressBar = ({ const BaseStandardReaderProgressBar = ({
readerNavBarWidth, readerNavBarWidth,
isMaximized,
setIsMaximized,
isDragging,
readerDirection, readerDirection,
}: Pick<NavbarContextType, 'readerNavBarWidth'> & }: Pick<NavbarContextType, 'readerNavBarWidth'> & {
Pick<TReaderProgressBarContext, 'isMaximized' | 'setIsMaximized' | 'isDragging'> & { readerDirection: ReturnType<typeof ReaderService.useGetThemeDirection>;
readerDirection: ReturnType<typeof ReaderService.useGetThemeDirection>; }) => {
}) => {
const theme = useTheme(); const theme = useTheme();
const scrollbar = useReaderStoreShallow((state) => state.scrollbar); const scrollbar = useReaderStoreShallow((state) => state.scrollbar);
@@ -45,6 +39,11 @@ const BaseStandardReaderProgressBar = ({
progressBarPosition: state.settings.progressBarPosition, progressBarPosition: state.settings.progressBarPosition,
progressBarPositionAutoVertical: state.settings.progressBarPositionAutoVertical, progressBarPositionAutoVertical: state.settings.progressBarPositionAutoVertical,
})); }));
const { isMaximized, setIsMaximized, isDragging } = useReaderStoreShallow((state) => ({
isMaximized: state.progressBar.isMaximized,
setIsMaximized: state.progressBar.setIsMaximized,
isDragging: state.progressBar.isDragging,
}));
const [, setRefreshProgressBarPosition] = useState({}); const [, setRefreshProgressBarPosition] = useState({});
useResizeObserver( useResizeObserver(
@@ -243,6 +242,6 @@ const BaseStandardReaderProgressBar = ({
export const StandardReaderProgressBar = withPropsFrom( export const StandardReaderProgressBar = withPropsFrom(
memo(BaseStandardReaderProgressBar), memo(BaseStandardReaderProgressBar),
[useNavBarContext, useReaderProgressBarContext, () => ({ readerDirection: ReaderService.useGetThemeDirection() })], [useNavBarContext, () => ({ readerDirection: ReaderService.useGetThemeDirection() })],
['readerNavBarWidth', 'isMaximized', 'setIsMaximized', 'isDragging', 'readerDirection'], ['readerNavBarWidth', 'readerDirection'],
); );

View File

@@ -23,9 +23,7 @@ import {
import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts'; import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts';
import { ProgressBarPosition } from '@/features/reader/Reader.types.ts'; import { ProgressBarPosition } from '@/features/reader/Reader.types.ts';
import { ReaderProgressBarDirectionWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarDirectionWrapper.tsx'; import { ReaderProgressBarDirectionWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarDirectionWrapper.tsx';
import { useReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBarContext.tsx';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { ReaderProgressBarSlotMobile } from '@/features/reader/overlay/progress-bar/mobile/components/ReaderProgressBarSlotMobile.tsx'; import { ReaderProgressBarSlotMobile } from '@/features/reader/overlay/progress-bar/mobile/components/ReaderProgressBarSlotMobile.tsx';
import { applyStyles } from '@/base/utils/ApplyStyles.ts'; import { applyStyles } from '@/base/utils/ApplyStyles.ts';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
@@ -42,12 +40,10 @@ const PROGRESS_BAR_POSITION_TO_SLIDE_DIRECTION: Record<ProgressBarPosition, Slid
}; };
const BaseMobileReaderProgressBar = ({ const BaseMobileReaderProgressBar = ({
setIsMaximized,
isDragging,
direction: readerDirection, direction: readerDirection,
topOffset = 0, topOffset = 0,
bottomOffset = 0, bottomOffset = 0,
}: Pick<TReaderProgressBarContext, 'setIsMaximized' | 'isDragging'> & { }: {
direction: ReturnType<typeof ReaderService.useGetThemeDirection>; direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
topOffset?: number; topOffset?: number;
bottomOffset?: number; bottomOffset?: number;
@@ -67,6 +63,10 @@ const BaseMobileReaderProgressBar = ({
progressBarPosition: state.settings.progressBarPosition, progressBarPosition: state.settings.progressBarPosition,
progressBarPositionAutoVertical: state.settings.progressBarPositionAutoVertical, progressBarPositionAutoVertical: state.settings.progressBarPositionAutoVertical,
})); }));
const { setIsMaximized, isDragging } = useReaderStoreShallow((state) => ({
setIsMaximized: state.progressBar.setIsMaximized,
isDragging: state.progressBar.isDragging,
}));
const [, setRefreshProgressBarPosition] = useState({}); const [, setRefreshProgressBarPosition] = useState({});
useResizeObserver( useResizeObserver(
@@ -354,6 +354,6 @@ const BaseMobileReaderProgressBar = ({
export const MobileReaderProgressBar = withPropsFrom( export const MobileReaderProgressBar = withPropsFrom(
memo(BaseMobileReaderProgressBar), memo(BaseMobileReaderProgressBar),
[useReaderProgressBarContext, () => ({ direction: ReaderService.useGetThemeDirection() })], [() => ({ direction: ReaderService.useGetThemeDirection() })],
['setIsMaximized', 'isDragging', 'direction'], ['direction'],
); );