Move reader "pages state" to "reader store"

This commit is contained in:
schroda
2025-09-19 17:01:20 +02:00
parent dabe50754f
commit bada26ead6
22 changed files with 232 additions and 406 deletions

View File

@@ -11,13 +11,7 @@ import Typography from '@mui/material/Typography';
import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import {
IReaderSettings,
ProgressBarType,
ReaderStatePages,
ReadingDirection,
} from '@/features/reader/Reader.types.ts';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { IReaderSettings, ProgressBarType, ReadingDirection } from '@/features/reader/Reader.types.ts';
import { getPage } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx';
import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
import { useReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBarContext.tsx';
@@ -31,18 +25,19 @@ const BaseReaderPageNumber = ({
isDesktop,
readerNavBarWidth,
isMaximized,
currentPageIndex,
pages,
totalPages,
progressBarType,
shouldShowPageNumber,
readingDirection,
}: Pick<ReturnType<typeof ReaderService.useOverlayMode>, 'isDesktop'> &
Pick<NavbarContextType, 'readerNavBarWidth'> &
Pick<TReaderProgressBarContext, 'isMaximized'> &
Pick<ReaderStatePages, 'currentPageIndex' | 'pages' | 'totalPages'> &
Pick<IReaderSettings, 'progressBarType' | 'shouldShowPageNumber' | 'readingDirection'>) => {
const scrollbar = useReaderStoreShallow((state) => state.scrollbar);
const { currentPageIndex, pages, totalPages } = useReaderStoreShallow((state) => ({
currentPageIndex: state.pages.currentPageIndex,
pages: state.pages.pages,
totalPages: state.pages.totalPages,
}));
const pageName = useMemo(() => {
const currentPageName = getPage(currentPageIndex, pages).name;
@@ -98,18 +93,7 @@ export const ReaderPageNumber = withPropsFrom(
ReaderService.useOverlayMode,
useNavBarContext,
useReaderProgressBarContext,
userReaderStatePagesContext,
ReaderService.useSettingsWithoutDefaultFlag,
],
[
'isDesktop',
'readerNavBarWidth',
'isMaximized',
'currentPageIndex',
'pages',
'totalPages',
'progressBarType',
'shouldShowPageNumber',
'readingDirection',
],
['isDesktop', 'readerNavBarWidth', 'isMaximized', 'progressBarType', 'shouldShowPageNumber', 'readingDirection'],
);

View File

@@ -24,7 +24,6 @@ import { ReaderNavBarDesktopQuickSettings } from '@/features/reader/overlay/navi
import { ReaderNavBarDesktopActions } from '@/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx';
import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
@@ -147,11 +146,6 @@ const BaseReaderNavBarDesktop = ({
export const ReaderNavBarDesktop = withPropsFrom(
memo(BaseReaderNavBarDesktop),
[
useNavBarContext,
useReaderStateChaptersContext,
userReaderStatePagesContext,
ReaderService.useSettingsWithoutDefaultFlag,
],
[useNavBarContext, useReaderStateChaptersContext, ReaderService.useSettingsWithoutDefaultFlag],
['setReaderNavBarWidth', 'chapters', 'currentChapter', 'previousChapter', 'nextChapter', 'isStaticNav'],
);

View File

@@ -15,17 +15,17 @@ import { memo, useMemo, useRef } from 'react';
import DeleteIcon from '@mui/icons-material/Delete';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
import { Chapters } from '@/features/chapter/services/Chapters.ts';
import { ReaderStateChapters, ReaderStatePages } from '@/features/reader/Reader.types.ts';
import { ReaderStateChapters } from '@/features/reader/Reader.types.ts';
import { DownloadStateIndicator } from '@/base/components/downloads/DownloadStateIndicator.tsx';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { ReaderLibraryButton } from '@/features/reader/overlay/navigation/components/ReaderLibraryButton.tsx';
import { ReaderBookmarkButton } from '@/features/reader/overlay/navigation/components/ReaderBookmarkButton.tsx';
import { CHAPTER_ACTION_TO_TRANSLATION, FALLBACK_CHAPTER } from '@/features/chapter/Chapter.constants.ts';
import { IconBrowser } from '@/assets/icons/IconBrowser.tsx';
import { IconWebView } from '@/assets/icons/IconWebView.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const DownloadButton = ({ currentChapter }: Required<Pick<ReaderStateChapters, 'currentChapter'>>) => {
const { t } = useTranslation();
@@ -60,16 +60,15 @@ const DownloadButton = ({ currentChapter }: Required<Pick<ReaderStateChapters, '
};
const BaseReaderNavBarDesktopActions = memo(
({
currentChapter,
pageLoadStates,
setPageLoadStates,
setRetryFailedPagesKeyPrefix,
}: Required<Pick<ReaderStateChapters, 'currentChapter'>> &
Pick<ReaderStatePages, 'pageLoadStates' | 'setPageLoadStates' | 'setRetryFailedPagesKeyPrefix'>) => {
({ currentChapter }: Required<Pick<ReaderStateChapters, 'currentChapter'>>) => {
const { id, isBookmarked, realUrl } = currentChapter ?? FALLBACK_CHAPTER;
const { t } = useTranslation();
const { pageLoadStates, setPageLoadStates, setRetryFailedPagesKeyPrefix } = useReaderStoreShallow((state) => ({
pageLoadStates: state.pages.pageLoadStates,
setPageLoadStates: state.pages.setPageLoadStates,
setRetryFailedPagesKeyPrefix: state.pages.setRetryFailedPagesKeyPrefix,
}));
const pageRetryKeyPrefix = useRef<number>(0);
@@ -130,6 +129,6 @@ const BaseReaderNavBarDesktopActions = memo(
export const ReaderNavBarDesktopActions = withPropsFrom(
BaseReaderNavBarDesktopActions,
[useReaderStateChaptersContext, userReaderStatePagesContext],
['currentChapter', 'pageLoadStates', 'setPageLoadStates', 'setRetryFailedPagesKeyPrefix'],
[useReaderStateChaptersContext],
['currentChapter'],
);

View File

@@ -19,23 +19,24 @@ import { useGetOptionForDirection } from '@/features/theme/services/ThemeCreator
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { ReaderNavBarDesktopNextPreviousButton } from '@/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopNextPreviousButton.tsx';
import { READING_DIRECTION_TO_THEME_DIRECTION } from '@/features/reader/settings/ReaderSettings.constants.tsx';
import { IReaderSettings, ReaderStatePages } from '@/features/reader/Reader.types.ts';
import { IReaderSettings } from '@/features/reader/Reader.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const BaseReaderNavBarDesktopPageNavigation = ({
currentPageIndex,
pages,
readingDirection,
openPage,
}: Pick<ReaderStatePages, 'currentPageIndex' | 'pages'> &
Pick<IReaderSettings, 'readingDirection'> & {
openPage: ReturnType<typeof ReaderControls.useOpenPage>;
}) => {
}: Pick<IReaderSettings, 'readingDirection'> & {
openPage: ReturnType<typeof ReaderControls.useOpenPage>;
}) => {
const { t } = useTranslation();
const getOptionForDirection = useGetOptionForDirection();
const currentPage = useMemo(() => getPage(currentPageIndex, pages), [currentPageIndex, pages]);
const { currentPageIndex, pages } = useReaderStoreShallow((state) => ({
currentPageIndex: state.pages.currentPageIndex,
pages: state.pages.pages,
}));
const currentPage = useMemo(() => getPage(currentPageIndex, pages), [currentPageIndex, pages]);
const direction = READING_DIRECTION_TO_THEME_DIRECTION[readingDirection];
return (
@@ -81,10 +82,6 @@ const BaseReaderNavBarDesktopPageNavigation = ({
export const ReaderNavBarDesktopPageNavigation = withPropsFrom(
memo(BaseReaderNavBarDesktopPageNavigation),
[
userReaderStatePagesContext,
() => ({ openPage: ReaderControls.useOpenPage() }),
ReaderService.useSettingsWithoutDefaultFlag,
],
['currentPageIndex', 'pages', 'readingDirection', 'openPage'],
[() => ({ openPage: ReaderControls.useOpenPage() }), ReaderService.useSettingsWithoutDefaultFlag],
['readingDirection', 'openPage'],
);

View File

@@ -34,15 +34,11 @@ import { ReaderControls } from '@/features/reader/services/ReaderControls.ts';
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 { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { IReaderSettings, ReadingMode } from '@/features/reader/Reader.types.ts';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const BaseReaderProgressBar = ({
totalPages,
pages,
pageLoadStates,
currentPageIndex,
slotProps,
slots,
createProgressBarSlot,
@@ -78,6 +74,13 @@ const BaseReaderProgressBar = ({
direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
fullSegmentClicks: boolean;
}) => {
const { pages, pageLoadStates, totalPages, currentPageIndex } = useReaderStoreShallow((state) => ({
pages: state.pages.pages,
pageLoadStates: state.pages.pageLoadStates,
totalPages: state.pages.totalPages,
currentPageIndex: state.pages.currentPageIndex,
}));
const progressBarRef = useRef<HTMLDivElement | null>(null);
const draggingDetectionTimeout = useRef<NodeJS.Timeout>(undefined);
@@ -250,17 +253,7 @@ export const ReaderProgressBar = withPropsFrom(
[
useReaderProgressBarContext,
() => ({ openPage: ReaderControls.useOpenPage() }),
userReaderStatePagesContext,
ReaderService.useSettingsWithoutDefaultFlag,
],
[
'isDragging',
'setIsDragging',
'openPage',
'pages',
'pageLoadStates',
'totalPages',
'currentPageIndex',
'readingMode',
],
['isDragging', 'setIsDragging', 'openPage', 'readingMode'],
);

View File

@@ -8,11 +8,9 @@
import { BoxProps } from '@mui/material/Box';
import { TooltipProps } from '@mui/material/Tooltip';
import { IReaderSettings, PageData, ReaderStatePages } from '@/features/reader/Reader.types.ts';
import { IReaderSettings, PageData } from '@/features/reader/Reader.types.ts';
export interface ReaderProgressBarProps
extends Pick<ReaderStatePages, 'totalPages' | 'pages' | 'pageLoadStates' | 'currentPageIndex'>,
Pick<IReaderSettings, 'progressBarPosition'> {}
export interface ReaderProgressBarProps extends Pick<IReaderSettings, 'progressBarPosition'> {}
export interface TReaderProgressCurrentPage extends PageData {
pagesIndex: number;

View File

@@ -6,15 +6,12 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import {
ReaderProgressBarProps,
TReaderProgressCurrentPage,
} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { TReaderProgressCurrentPage } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { getOptionForDirection as getOptionForDirectionImpl } from '@/features/theme/services/ThemeCreator.ts';
import { ProgressBarPosition } from '@/features/reader/Reader.types.ts';
import { ProgressBarPosition, ReaderStatePages } from '@/features/reader/Reader.types.ts';
import { coerceIn } from '@/lib/HelperFunctions.ts';
export const getPage = (pageIndex: number, pages: ReaderProgressBarProps['pages']): TReaderProgressCurrentPage => {
export const getPage = (pageIndex: number, pages: ReaderStatePages['pages']): TReaderProgressCurrentPage => {
const pagesIndex = pages.findIndex(({ primary, secondary }) =>
[primary.index, secondary?.index].includes(pageIndex),
);
@@ -29,13 +26,13 @@ export const getPage = (pageIndex: number, pages: ReaderProgressBarProps['pages'
* for the double page mode the secondary page index has to be used to be able to correctly detect if the last page is visible
*
*/
export const getNextIndexFromPage = (page: ReaderProgressBarProps['pages'][number]) =>
export const getNextIndexFromPage = (page: ReaderStatePages['pages'][number]) =>
page.secondary?.index ?? page.primary.index;
export const getNextPageIndex = (
offset: 'previous' | 'next',
pagesIndex: number,
pages: ReaderProgressBarProps['pages'],
pages: ReaderStatePages['pages'],
): number => {
switch (offset) {
case 'previous':
@@ -50,11 +47,11 @@ export const getNextPageIndex = (
export const getPageForMousePos = (
coordinates: { clientX: number; clientY: number },
element: HTMLElement,
pages: ReaderProgressBarProps['pages'],
pages: ReaderStatePages['pages'],
isHorizontalPosition: boolean,
fullSegmentClicks: boolean,
getOptionForDirection: typeof getOptionForDirectionImpl,
): ReaderProgressBarProps['pages'][number] => {
): ReaderStatePages['pages'][number] => {
const pos = isHorizontalPosition ? coordinates.clientX : coordinates.clientY;
const { paddingTop, paddingBottom, paddingLeft, paddingRight } = getComputedStyle(element);

View File

@@ -9,8 +9,8 @@
import Box, { BoxProps } from '@mui/material/Box';
import { memo, ReactNode, useMemo } from 'react';
import { styled } from '@mui/material/styles';
import { ReaderProgressBarProps } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { shouldForwardProp } from '@/base/utils/ShouldForwardProp.ts';
import { ReaderStatePages } from '@/features/reader/Reader.types.ts';
type StyledWrapperProps = {
isFirstPage: boolean;
@@ -42,20 +42,20 @@ export const ReaderProgressBarSlotWrapper = memo(
createProgressBarSlot,
...boxProps
}: {
page: ReaderProgressBarProps['pages'][number];
page: ReaderStatePages['pages'][number];
pagesIndex: number;
isCurrentPage: boolean;
isLeadingPage: boolean;
isTrailingPage: boolean;
totalPages: number;
showDraggingStyle: boolean;
primaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'];
secondaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'] | undefined;
primaryPageLoadState: ReaderStatePages['pageLoadStates'][number]['loaded'];
secondaryPageLoadState: ReaderStatePages['pageLoadStates'][number]['loaded'] | undefined;
createProgressBarSlot: (
page: ReaderProgressBarProps['pages'][number],
page: ReaderStatePages['pages'][number],
pagesIndex: number,
primaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'],
secondaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'] | undefined,
primaryPageLoadState: ReaderStatePages['pageLoadStates'][number]['loaded'],
secondaryPageLoadState: ReaderStatePages['pageLoadStates'][number]['loaded'] | undefined,
isCurrentPage: boolean,
isLeadingPage: boolean,
isTrailingPage: boolean,

View File

@@ -9,16 +9,12 @@
import { useTheme } from '@mui/material/styles';
import { memo, useCallback, useState } from 'react';
import { ReaderProgressBar } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.tsx';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { IReaderSettings, ProgressBarType } from '@/features/reader/Reader.types.ts';
import { applyStyles } from '@/base/utils/ApplyStyles.ts';
import { getProgressBarPositionInfo } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx';
import { ReaderProgressBarDirectionWrapper } from '@/features/reader/overlay/progress-bar/components/ReaderProgressBarDirectionWrapper.tsx';
import {
ReaderProgressBarProps,
TReaderProgressBarContext,
} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
@@ -26,7 +22,7 @@ import { useReaderProgressBarContext } from '@/features/reader/overlay/progress-
import { ReaderProgressBarSlotDesktop } from '@/features/reader/overlay/progress-bar/desktop/components/ReaderProgressBarSlotDesktop.tsx';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { getProgressBarPosition } from '@/features/reader/settings/ReaderSettings.utils.tsx';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
import { useReaderStore, useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const BaseStandardReaderProgressBar = ({
readerNavBarWidth,
@@ -38,19 +34,18 @@ const BaseStandardReaderProgressBar = ({
progressBarPosition,
progressBarPositionAutoVertical,
readerDirection,
totalPages,
}: Pick<NavbarContextType, 'readerNavBarWidth'> &
Pick<TReaderProgressBarContext, 'isMaximized' | 'setIsMaximized' | 'isDragging'> &
Pick<
IReaderSettings,
'progressBarType' | 'progressBarSize' | 'progressBarPosition' | 'progressBarPositionAutoVertical'
> &
Pick<ReaderProgressBarProps, 'totalPages'> & {
> & {
readerDirection: ReturnType<typeof ReaderService.useGetThemeDirection>;
}) => {
const theme = useTheme();
const scrollbar = useReaderStoreShallow((state) => state.scrollbar);
const totalPages = useReaderStore((state) => state.pages.totalPages);
const [, setRefreshProgressBarPosition] = useState({});
useResizeObserver(
@@ -254,7 +249,6 @@ export const StandardReaderProgressBar = withPropsFrom(
useReaderProgressBarContext,
ReaderService.useSettingsWithoutDefaultFlag,
() => ({ readerDirection: ReaderService.useGetThemeDirection() }),
userReaderStatePagesContext,
],
[
'readerNavBarWidth',
@@ -266,6 +260,5 @@ export const StandardReaderProgressBar = withPropsFrom(
'progressBarPosition',
'progressBarPositionAutoVertical',
'readerDirection',
'totalPages',
],
);

View File

@@ -26,12 +26,8 @@ import { IReaderSettings, ProgressBarPosition, ReaderStateChapters } from '@/fea
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 {
ReaderProgressBarProps,
TReaderProgressBarContext,
} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { TReaderProgressBarContext } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts';
import { ReaderProgressBarSlotMobile } from '@/features/reader/overlay/progress-bar/mobile/components/ReaderProgressBarSlotMobile.tsx';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { applyStyles } from '@/base/utils/ApplyStyles.ts';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { getProgressBarPosition } from '@/features/reader/settings/ReaderSettings.utils.tsx';
@@ -51,8 +47,6 @@ const BaseMobileReaderProgressBar = ({
nextChapter,
setIsMaximized,
isDragging,
currentPageIndex,
pages,
direction: readerDirection,
progressBarPosition,
progressBarPositionAutoVertical,
@@ -60,7 +54,6 @@ const BaseMobileReaderProgressBar = ({
bottomOffset = 0,
}: Pick<ReaderStateChapters, 'previousChapter' | 'nextChapter'> &
Pick<TReaderProgressBarContext, 'setIsMaximized' | 'isDragging'> &
Pick<ReaderProgressBarProps, 'currentPageIndex' | 'pages'> &
Pick<IReaderSettings, 'progressBarPosition' | 'progressBarPositionAutoVertical'> & {
direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
topOffset?: number;
@@ -69,6 +62,10 @@ const BaseMobileReaderProgressBar = ({
const openChapter = ReaderControls.useOpenChapter();
const scrollbar = useReaderStoreShallow((state) => state.scrollbar);
const isVisible = useReaderStore((state) => state.overlay.isVisible);
const { currentPageIndex, pages } = useReaderStoreShallow((state) => ({
currentPageIndex: state.pages.currentPageIndex,
pages: state.pages.pages,
}));
const [, setRefreshProgressBarPosition] = useState({});
useResizeObserver(
@@ -359,7 +356,6 @@ export const MobileReaderProgressBar = withPropsFrom(
[
useReaderStateChaptersContext,
useReaderProgressBarContext,
userReaderStatePagesContext,
() => ({ direction: ReaderService.useGetThemeDirection() }),
ReaderService.useSettingsWithoutDefaultFlag,
],
@@ -368,8 +364,6 @@ export const MobileReaderProgressBar = withPropsFrom(
'nextChapter',
'setIsMaximized',
'isDragging',
'currentPageIndex',
'pages',
'direction',
'progressBarPosition',
'progressBarPositionAutoVertical',