From bada26ead67e075f017f39d69ca9dd739fb70647 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Fri, 19 Sep 2025 17:01:20 +0200 Subject: [PATCH] Move reader "pages state" to "reader store" --- src/features/reader/Reader.types.ts | 24 +++-- ....constants.ts => ReaderStore.constants.ts} | 34 ++++--- src/features/reader/ReaderStore.ts | 59 +++++++++++- .../state/ReaderStateContextProvider.tsx | 5 +- .../state/ReaderStatePagesContext.tsx | 88 ------------------ .../reader/hooks/useReaderResetStates.ts | 23 +---- .../overlay/components/ReaderPageNumber.tsx | 30 ++---- .../desktop/ReaderNavBarDesktop.tsx | 8 +- .../components/ReaderNavBarDesktopActions.tsx | 21 ++--- .../ReaderNavBarDesktopPageNavigation.tsx | 27 +++--- .../progress-bar/ReaderProgressBar.tsx | 25 ++--- .../progress-bar/ReaderProgressBar.types.ts | 6 +- .../progress-bar/ReaderProgressBar.utils.tsx | 17 ++-- .../ReaderProgressBarSlotWrapper.tsx | 14 +-- .../desktop/StandardReaderProgressBar.tsx | 15 +-- .../mobile/MobileReaderProgressBar.tsx | 16 +--- src/features/reader/screens/Reader.tsx | 39 +------- .../reader/services/ReaderControls.ts | 65 ++++--------- .../reader/viewer/ReaderChapterViewer.tsx | 12 +-- src/features/reader/viewer/ReaderViewer.tsx | 93 ++++++++----------- .../components/ReaderTransitionPage.tsx | 15 +-- .../hooks/useReaderPreserveScrollPosition.ts | 2 +- 22 files changed, 232 insertions(+), 406 deletions(-) rename src/features/reader/{ReaderContext.constants.ts => ReaderStore.constants.ts} (50%) delete mode 100644 src/features/reader/contexts/state/ReaderStatePagesContext.tsx diff --git a/src/features/reader/Reader.types.ts b/src/features/reader/Reader.types.ts index e6ca670a..65019ab9 100644 --- a/src/features/reader/Reader.types.ts +++ b/src/features/reader/Reader.types.ts @@ -292,23 +292,31 @@ export interface PageData { secondary?: SinglePageData; } +interface ReaderPageLoadState { + url: string; + loaded: boolean; + error?: boolean; +} + export interface ReaderStatePages { totalPages: number; - setTotalPages: React.Dispatch>; + setTotalPages: (index: number) => void; currentPageIndex: number; - setCurrentPageIndex: React.Dispatch>; + setCurrentPageIndex: (index: number) => void; pageToScrollToIndex: number | null; - setPageToScrollToIndex: React.Dispatch>; + setPageToScrollToIndex: (total: number | null) => void; pageUrls: string[]; - setPageUrls: React.Dispatch>; + setPageUrls: (urls: string[]) => void; pageLoadStates: { url: string; loaded: boolean; error?: boolean }[]; - setPageLoadStates: React.Dispatch>; + setPageLoadStates: ( + set: ((prevStates: ReaderPageLoadState[]) => ReaderPageLoadState[]) | ReaderPageLoadState[], + ) => void; pages: PageData[]; - setPages: React.Dispatch>; + setPages: (pages: PageData[]) => void; transitionPageMode: ReaderTransitionPageMode; - setTransitionPageMode: React.Dispatch>; + setTransitionPageMode: (mode: ReaderTransitionPageMode) => void; retryFailedPagesKeyPrefix: string; - setRetryFailedPagesKeyPrefix: React.Dispatch>; + setRetryFailedPagesKeyPrefix: (prefix: string) => void; } export interface ReaderPagerProps diff --git a/src/features/reader/ReaderContext.constants.ts b/src/features/reader/ReaderStore.constants.ts similarity index 50% rename from src/features/reader/ReaderContext.constants.ts rename to src/features/reader/ReaderStore.constants.ts index 963fe52e..dbb68b55 100644 --- a/src/features/reader/ReaderContext.constants.ts +++ b/src/features/reader/ReaderStore.constants.ts @@ -7,23 +7,35 @@ */ import { ReaderStatePages, ReaderTransitionPageMode } from '@/features/reader/Reader.types.ts'; -import { createPageData } from '@/features/reader/viewer/pager/ReaderPager.utils.tsx'; +import { requestManager } from '@/lib/requests/RequestManager.ts'; -export const READER_STATE_PAGES_DEFAULTS: ReaderStatePages = { +export const READER_DEFAULT_PAGES_STATE: Omit< + ReaderStatePages, + | 'setCurrentPageIndex' + | 'setPageToScrollToIndex' + | 'setTotalPages' + | 'setPageUrls' + | 'setPageLoadStates' + | 'setPages' + | 'setTransitionPageMode' + | 'setRetryFailedPagesKeyPrefix' + | 'reset' +> = { totalPages: 0, - setTotalPages: () => undefined, currentPageIndex: 0, - setCurrentPageIndex: () => undefined, pageToScrollToIndex: null, - setPageToScrollToIndex: () => undefined, pageUrls: [], - setPageUrls: () => undefined, pageLoadStates: [{ url: '', loaded: false }], - setPageLoadStates: () => undefined, - pages: [createPageData('', 0)], - setPages: () => undefined, + pages: [ + { + name: '1', + primary: { + index: 0, + alt: `Page #1`, + url: `${requestManager.getBaseUrl()}`, + }, + }, + ], transitionPageMode: ReaderTransitionPageMode.NONE, - setTransitionPageMode: () => undefined, retryFailedPagesKeyPrefix: '', - setRetryFailedPagesKeyPrefix: () => undefined, }; diff --git a/src/features/reader/ReaderStore.ts b/src/features/reader/ReaderStore.ts index d82e92e4..9dd142f9 100644 --- a/src/features/reader/ReaderStore.ts +++ b/src/features/reader/ReaderStore.ts @@ -18,8 +18,17 @@ import { createReaderAutoScrollStoreSlice, ReaderAutoScrollStoreSlice, } from '@/features/reader/auto-scroll/ReaderAutoScrollStore.ts'; +import { ReaderStatePages } from '@/features/reader/Reader.types.ts'; +import { ImmerStateCreator } from '@/lib/zustand/Zustand.types.ts'; +import { READER_DEFAULT_PAGES_STATE } from '@/features/reader/ReaderStore.constants.ts'; -interface ReaderStore extends ReaderOverlayStoreSlice, ReaderAutoScrollStoreSlice { +interface ReaderPagesStoreSlice { + pages: ReaderStatePages & { + reset: () => void; + }; +} + +interface ReaderStore extends ReaderOverlayStoreSlice, ReaderAutoScrollStoreSlice, ReaderPagesStoreSlice { reset: () => void; manga: TMangaReader | undefined; setManga: (manga: TMangaReader | undefined) => void; @@ -39,6 +48,52 @@ const DEFAULT_STATE = { }, } satisfies Pick & { scrollbar: Pick }; +const createReaderPagesStoreSlice = ( + ...[set, get]: Parameters> +): ReaderPagesStoreSlice => ({ + pages: { + ...READER_DEFAULT_PAGES_STATE, + reset: () => set(() => ({ pages: { ...get().pages, ...READER_DEFAULT_PAGES_STATE } })), + setCurrentPageIndex: (index) => + set((draft) => { + draft.pages.currentPageIndex = index; + }), + setPageToScrollToIndex: (index) => + set((draft) => { + draft.pages.pageToScrollToIndex = index; + }), + setTotalPages: (total) => + set((draft) => { + draft.pages.totalPages = total; + }), + setPageUrls: (urls) => + set((draft) => { + draft.pages.pageUrls = urls; + }), + setPageLoadStates: (loadStates) => + set((draft) => { + if (typeof loadStates === 'function') { + draft.pages.pageLoadStates = loadStates(get().pages.pageLoadStates); + return; + } + + draft.pages.pageLoadStates = loadStates; + }), + setPages: (pages) => + set((draft) => { + draft.pages.pages = pages; + }), + setTransitionPageMode: (mode) => + set((draft) => { + draft.pages.transitionPageMode = mode; + }), + setRetryFailedPagesKeyPrefix: (prefix) => + set((draft) => { + draft.pages.retryFailedPagesKeyPrefix = prefix; + }), + }, +}); + export const useReaderStore = create()( immer((set, get, store) => ({ ...DEFAULT_STATE, @@ -48,6 +103,7 @@ export const useReaderStore = create()( draft.scrollbar = { ...get().scrollbar, ...DEFAULT_STATE.scrollbar }; get().overlay.reset(); get().autoScroll.reset(); + get().pages.reset(); }), setManga: (manga) => set((draft) => { @@ -66,6 +122,7 @@ export const useReaderStore = create()( }, ...createReaderOverlayStoreSlice(set, get, store), ...createReaderAutoScrollStoreSlice(set, get, store), + ...createReaderPagesStoreSlice(set, get, store), })), ); export const useReaderStoreShallow = (selector: (state: ReaderStore) => T): T => diff --git a/src/features/reader/contexts/state/ReaderStateContextProvider.tsx b/src/features/reader/contexts/state/ReaderStateContextProvider.tsx index 7c1b3c5f..0ed00a49 100644 --- a/src/features/reader/contexts/state/ReaderStateContextProvider.tsx +++ b/src/features/reader/contexts/state/ReaderStateContextProvider.tsx @@ -8,13 +8,10 @@ import { ReactNode } from 'react'; import { ReaderStateChaptersContextProvider } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; -import { ReaderStatePagesContextProvider } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { ReaderStateSettingsContextProvider } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx'; export const ReaderStateContextProvider = ({ children }: { children: ReactNode }) => ( - - {children} - + {children} ); diff --git a/src/features/reader/contexts/state/ReaderStatePagesContext.tsx b/src/features/reader/contexts/state/ReaderStatePagesContext.tsx deleted file mode 100644 index 763a02d5..00000000 --- a/src/features/reader/contexts/state/ReaderStatePagesContext.tsx +++ /dev/null @@ -1,88 +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, ReactNode, useContext, useMemo, useState } from 'react'; -import { ReaderStatePages, ReaderTransitionPageMode } from '@/features/reader/Reader.types.ts'; -import { READER_STATE_PAGES_DEFAULTS } from '@/features/reader/ReaderContext.constants.ts'; - -export const ReaderStatePagesContext = createContext({ - totalPages: 0, - currentPageIndex: 0, - setCurrentPageIndex: () => undefined, - pageToScrollToIndex: null, - setPageToScrollToIndex: () => undefined, - setTotalPages: () => undefined, - pageUrls: [], - setPageUrls: () => undefined, - pageLoadStates: [], - setPageLoadStates: () => undefined, - pages: [], - setPages: () => undefined, - transitionPageMode: ReaderTransitionPageMode.NONE, - setTransitionPageMode: () => undefined, - retryFailedPagesKeyPrefix: '', - setRetryFailedPagesKeyPrefix: () => undefined, -}); - -export const userReaderStatePagesContext = () => useContext(ReaderStatePagesContext); - -export const ReaderStatePagesContextProvider = ({ children }: { children: ReactNode }) => { - const [totalPages, setTotalPages] = useState( - READER_STATE_PAGES_DEFAULTS.totalPages, - ); - const [currentPageIndex, setCurrentPageIndex] = useState( - READER_STATE_PAGES_DEFAULTS.currentPageIndex, - ); - const [pageToScrollToIndex, setPageToScrollToIndex] = useState( - READER_STATE_PAGES_DEFAULTS.pageToScrollToIndex, - ); - const [pageUrls, setPageUrls] = useState(READER_STATE_PAGES_DEFAULTS.pageUrls); - const [pageLoadStates, setPageLoadStates] = useState( - READER_STATE_PAGES_DEFAULTS.pageLoadStates, - ); - const [pages, setPages] = useState(READER_STATE_PAGES_DEFAULTS.pages); - const [transitionPageMode, setTransitionPageMode] = useState( - READER_STATE_PAGES_DEFAULTS.transitionPageMode, - ); - const [retryFailedPagesKeyPrefix, setRetryFailedPagesKeyPrefix] = useState< - ReaderStatePages['retryFailedPagesKeyPrefix'] - >(READER_STATE_PAGES_DEFAULTS.retryFailedPagesKeyPrefix); - - const value = useMemo( - () => ({ - totalPages, - setTotalPages, - currentPageIndex, - setCurrentPageIndex, - pageToScrollToIndex, - setPageToScrollToIndex, - pageUrls, - setPageUrls, - pageLoadStates, - setPageLoadStates, - pages, - setPages, - transitionPageMode, - setTransitionPageMode, - retryFailedPagesKeyPrefix, - setRetryFailedPagesKeyPrefix, - }), - [ - totalPages, - pages, - currentPageIndex, - pageToScrollToIndex, - pageUrls, - pageLoadStates, - transitionPageMode, - retryFailedPagesKeyPrefix, - ], - ); - - return {children}; -}; diff --git a/src/features/reader/hooks/useReaderResetStates.ts b/src/features/reader/hooks/useReaderResetStates.ts index 53175299..e0eb60b9 100644 --- a/src/features/reader/hooks/useReaderResetStates.ts +++ b/src/features/reader/hooks/useReaderResetStates.ts @@ -7,26 +7,13 @@ */ import { useEffect } from 'react'; -import { createPageData } from '@/features/reader/viewer/pager/ReaderPager.utils.tsx'; -import { - ReaderStateChapters, - ReaderStatePages, - ReaderTransitionPageMode, - TReaderStateSettingsContext, -} from '@/features/reader/Reader.types.ts'; +import { ReaderStateChapters, TReaderStateSettingsContext } from '@/features/reader/Reader.types.ts'; import { DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG } from '@/features/reader/settings/ReaderSettingsMetadata.ts'; import { READER_STATE_CHAPTERS_DEFAULTS } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; import { getReaderStore } from '@/features/reader/ReaderStore.ts'; export const useReaderResetStates = ( setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'], - setCurrentPageIndex: ReaderStatePages['setCurrentPageIndex'], - setPageToScrollToIndex: ReaderStatePages['setPageToScrollToIndex'], - setTotalPages: ReaderStatePages['setTotalPages'], - setPages: ReaderStatePages['setPages'], - setPageUrls: ReaderStatePages['setPageUrls'], - setPageLoadStates: ReaderStatePages['setPageLoadStates'], - setTransitionPageMode: ReaderStatePages['setTransitionPageMode'], setSettings: TReaderStateSettingsContext['setSettings'], ) => { useEffect( @@ -34,14 +21,6 @@ export const useReaderResetStates = ( getReaderStore().reset(); setReaderStateChapters(READER_STATE_CHAPTERS_DEFAULTS); - setCurrentPageIndex(0); - setPageToScrollToIndex(null); - setTotalPages(0); - setPages([createPageData('', 0)]); - setPageUrls([]); - setPageLoadStates([{ url: '', loaded: false }]); - setTransitionPageMode(ReaderTransitionPageMode.NONE); - setSettings(DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG); }, [], diff --git a/src/features/reader/overlay/components/ReaderPageNumber.tsx b/src/features/reader/overlay/components/ReaderPageNumber.tsx index 9f251bdb..dee041d7 100644 --- a/src/features/reader/overlay/components/ReaderPageNumber.tsx +++ b/src/features/reader/overlay/components/ReaderPageNumber.tsx @@ -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, 'isDesktop'> & Pick & Pick & - Pick & Pick) => { 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'], ); diff --git a/src/features/reader/overlay/navigation/desktop/ReaderNavBarDesktop.tsx b/src/features/reader/overlay/navigation/desktop/ReaderNavBarDesktop.tsx index 544d364f..feb119b0 100644 --- a/src/features/reader/overlay/navigation/desktop/ReaderNavBarDesktop.tsx +++ b/src/features/reader/overlay/navigation/desktop/ReaderNavBarDesktop.tsx @@ -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'], ); diff --git a/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx b/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx index da331421..fc912af4 100644 --- a/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx +++ b/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx @@ -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>) => { const { t } = useTranslation(); @@ -60,16 +60,15 @@ const DownloadButton = ({ currentChapter }: Required> & - Pick) => { + ({ currentChapter }: Required>) => { 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(0); @@ -130,6 +129,6 @@ const BaseReaderNavBarDesktopActions = memo( export const ReaderNavBarDesktopActions = withPropsFrom( BaseReaderNavBarDesktopActions, - [useReaderStateChaptersContext, userReaderStatePagesContext], - ['currentChapter', 'pageLoadStates', 'setPageLoadStates', 'setRetryFailedPagesKeyPrefix'], + [useReaderStateChaptersContext], + ['currentChapter'], ); diff --git a/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopPageNavigation.tsx b/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopPageNavigation.tsx index c4da6525..eef2817a 100644 --- a/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopPageNavigation.tsx +++ b/src/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopPageNavigation.tsx @@ -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 & - Pick & { - openPage: ReturnType; - }) => { +}: Pick & { + openPage: ReturnType; +}) => { 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'], ); diff --git a/src/features/reader/overlay/progress-bar/ReaderProgressBar.tsx b/src/features/reader/overlay/progress-bar/ReaderProgressBar.tsx index fdef5da3..e0fe7a72 100644 --- a/src/features/reader/overlay/progress-bar/ReaderProgressBar.tsx +++ b/src/features/reader/overlay/progress-bar/ReaderProgressBar.tsx @@ -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; 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(null); const draggingDetectionTimeout = useRef(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'], ); diff --git a/src/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts b/src/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts index c88b754f..7c949288 100644 --- a/src/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts +++ b/src/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts @@ -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, - Pick {} +export interface ReaderProgressBarProps extends Pick {} export interface TReaderProgressCurrentPage extends PageData { pagesIndex: number; diff --git a/src/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx b/src/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx index cfffc1da..6930c127 100644 --- a/src/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx +++ b/src/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx @@ -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); diff --git a/src/features/reader/overlay/progress-bar/components/ReaderProgressBarSlotWrapper.tsx b/src/features/reader/overlay/progress-bar/components/ReaderProgressBarSlotWrapper.tsx index e317160b..58dfd766 100644 --- a/src/features/reader/overlay/progress-bar/components/ReaderProgressBarSlotWrapper.tsx +++ b/src/features/reader/overlay/progress-bar/components/ReaderProgressBarSlotWrapper.tsx @@ -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, diff --git a/src/features/reader/overlay/progress-bar/desktop/StandardReaderProgressBar.tsx b/src/features/reader/overlay/progress-bar/desktop/StandardReaderProgressBar.tsx index 19f14579..4f0eefae 100644 --- a/src/features/reader/overlay/progress-bar/desktop/StandardReaderProgressBar.tsx +++ b/src/features/reader/overlay/progress-bar/desktop/StandardReaderProgressBar.tsx @@ -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 & Pick & Pick< IReaderSettings, 'progressBarType' | 'progressBarSize' | 'progressBarPosition' | 'progressBarPositionAutoVertical' - > & - Pick & { + > & { readerDirection: ReturnType; }) => { 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', ], ); diff --git a/src/features/reader/overlay/progress-bar/mobile/MobileReaderProgressBar.tsx b/src/features/reader/overlay/progress-bar/mobile/MobileReaderProgressBar.tsx index 3e6619d2..845e741b 100644 --- a/src/features/reader/overlay/progress-bar/mobile/MobileReaderProgressBar.tsx +++ b/src/features/reader/overlay/progress-bar/mobile/MobileReaderProgressBar.tsx @@ -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 & Pick & - Pick & Pick & { direction: ReturnType; 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', diff --git a/src/features/reader/screens/Reader.tsx b/src/features/reader/screens/Reader.tsx index cb87adea..a069e5a6 100644 --- a/src/features/reader/screens/Reader.tsx +++ b/src/features/reader/screens/Reader.tsx @@ -19,7 +19,6 @@ import { GET_MANGA_READER } from '@/lib/graphql/queries/MangaQuery.ts'; import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx'; import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { GET_CHAPTERS_READER } from '@/lib/graphql/queries/ChapterQuery.ts'; import { TapZoneLayout } from '@/features/reader/tap-zones/TapZoneLayout.tsx'; import { ReaderRGBAFilter } from '@/features/reader/filters/ReaderRGBAFilter.tsx'; @@ -32,7 +31,6 @@ import { IReaderSettings, IReaderSettingsWithDefaultFlag, ReaderStateChapters, - ReaderStatePages, TReaderStateSettingsContext, } from '@/features/reader/Reader.types.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts'; @@ -68,13 +66,6 @@ const BaseReader = ({ chapterForDuplicatesHandling, currentChapter, setReaderStateChapters, - setTotalPages, - setCurrentPageIndex, - setPageToScrollToIndex, - setPages, - setPageUrls, - setPageLoadStates, - setTransitionPageMode, setShowPreview, }: Pick & Pick & @@ -95,16 +86,6 @@ const BaseReader = ({ | 'currentChapter' | 'setReaderStateChapters' > & - Pick< - ReaderStatePages, - | 'setTotalPages' - | 'setCurrentPageIndex' - | 'setPageToScrollToIndex' - | 'setPages' - | 'setPageUrls' - | 'setPageLoadStates' - | 'setTransitionPageMode' - > & Pick) => { const { t } = useTranslation(); const manga = useReaderStoreShallow((state) => state.manga); @@ -149,17 +130,7 @@ const BaseReader = ({ useReaderStore.getState().setManga(mangaResponse.data?.manga); }, [mangaResponse.data?.manga]); - useReaderResetStates( - setReaderStateChapters, - setCurrentPageIndex, - setPageToScrollToIndex, - setTotalPages, - setPages, - setPageUrls, - setPageLoadStates, - setTransitionPageMode, - setSettings, - ); + useReaderResetStates(setReaderStateChapters, setSettings); useReaderSetSettingsState( mangaResponse, defaultSettingsResponse, @@ -314,7 +285,6 @@ export const Reader = withPropsFrom( const { readingMode, tapZoneLayout, tapZoneInvertMode } = ReaderService.useSettings(); return { readingMode, tapZoneLayout, tapZoneInvertMode }; }, - userReaderStatePagesContext, useReaderTapZoneContext, ], [ @@ -334,13 +304,6 @@ export const Reader = withPropsFrom( 'chapterForDuplicatesHandling', 'currentChapter', 'setReaderStateChapters', - 'setTotalPages', - 'setCurrentPageIndex', - 'setPageToScrollToIndex', - 'setPages', - 'setPageUrls', - 'setPageLoadStates', - 'setTransitionPageMode', 'setShowPreview', ], ); diff --git a/src/features/reader/services/ReaderControls.ts b/src/features/reader/services/ReaderControls.ts index 38f7cb0a..6dd0c867 100644 --- a/src/features/reader/services/ReaderControls.ts +++ b/src/features/reader/services/ReaderControls.ts @@ -10,7 +10,6 @@ import { MutableRefObject, RefObject, useCallback, useEffect, useMemo } from 're import { Direction, useTheme } from '@mui/material/styles'; import { useTranslation } from 'react-i18next'; import { TFunction } from 'i18next'; -import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { getNextIndexFromPage, getNextPageIndex, @@ -25,6 +24,7 @@ import { PageInViewportType, ProgressBarPosition, ReaderScrollAmount, + ReaderStatePages, ReaderTransitionPageMode, ReadingDirection, ReadingMode, @@ -50,10 +50,7 @@ import { useMetadataServerSettings } from '@/features/settings/services/ServerSe import { ChapterIdInfo, TChapterReader } from '@/features/chapter/Chapter.types.ts'; import { awaitConfirmation } from '@/base/utils/AwaitableDialog.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { - ReaderProgressBarProps, - TReaderProgressCurrentPage, -} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts'; +import { TReaderProgressCurrentPage } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.types.ts'; import { getReaderStore } from '@/features/reader/ReaderStore.ts'; const getScrollDirectionInvert = ( @@ -346,31 +343,13 @@ export class ReaderControls { forceDirection?: Direction, hideOverlay?: boolean, ) => void { - const { currentPageIndex, setPageToScrollToIndex, pages, transitionPageMode, setTransitionPageMode } = - userReaderStatePagesContext(); const { previousChapter, nextChapter } = useReaderStateChaptersContext(); const { setShowPreview } = useReaderTapZoneContext(); const { readingDirection, readingMode, shouldShowTransitionPage } = ReaderService.useSettings(); const openChapter = ReaderControls.useOpenChapter(); - const currentPage = useMemo(() => getPage(currentPageIndex, pages), [currentPageIndex, pages]); - const previousPageIndex = useMemo( - () => getNextPageIndex('previous', currentPage.pagesIndex, pages), - [currentPage, pages], - ); - const nextPageIndex = useMemo( - () => getNextPageIndex('next', currentPage.pagesIndex, pages), - [currentPage, pages], - ); - const indexOfFirstPage = getNextIndexFromPage(pages[0]); - const indexOfLastPage = getNextIndexFromPage(pages[pages.length - 1]); const direction = READING_DIRECTION_TO_THEME_DIRECTION[readingDirection.value]; - const isFirstPage = currentPage.primary.index === 0; - const isLastPage = currentPageIndex === indexOfLastPage; - const isATransitionPageVisibleFlag = isATransitionPageVisible(transitionPageMode, readingMode.value); - const isContinuousReadingModeActive = isContinuousReadingMode(readingMode.value); - return useCallback( (page, forceDirection = direction, hideOverlay: boolean = true) => { const convertedPage = getOptionForDirection( @@ -379,6 +358,20 @@ export class ReaderControls { forceDirection, ); + const { currentPageIndex, setPageToScrollToIndex, pages, transitionPageMode, setTransitionPageMode } = + getReaderStore().pages; + + const currentPage = getPage(currentPageIndex, pages); + const previousPageIndex = getNextPageIndex('previous', currentPage.pagesIndex, pages); + const nextPageIndex = getNextPageIndex('next', currentPage.pagesIndex, pages); + const indexOfFirstPage = getNextIndexFromPage(pages[0]); + const indexOfLastPage = getNextIndexFromPage(pages[pages.length - 1]); + + const isFirstPage = currentPage.primary.index === 0; + const isLastPage = currentPageIndex === indexOfLastPage; + const isATransitionPageVisibleFlag = isATransitionPageVisible(transitionPageMode, readingMode.value); + const isContinuousReadingModeActive = isContinuousReadingMode(readingMode.value); + if (hideOverlay) { getReaderStore().overlay.setIsVisible(false); setShowPreview(false); @@ -449,22 +442,7 @@ export class ReaderControls { setPageToScrollToIndex(isPreviousMode ? previousPageIndex : nextPageIndex); }, - [ - direction, - indexOfFirstPage, - indexOfLastPage, - previousPageIndex, - nextPageIndex, - indexOfLastPage, - isATransitionPageVisibleFlag, - isContinuousReadingModeActive, - isFirstPage, - isLastPage, - openChapter, - !!previousChapter, - !!nextChapter, - shouldShowTransitionPage, - ], + [direction, openChapter, !!previousChapter, !!nextChapter, shouldShowTransitionPage, readingMode.value], ); } @@ -473,7 +451,6 @@ export class ReaderControls { debounceChapterUpdate?: boolean, endReached?: boolean, ) => void { - const { currentPageIndex, setCurrentPageIndex } = userReaderStatePagesContext(); const { currentChapter, chapters, previousChapter, nextChapter, visibleChapters, setReaderStateChapters } = useReaderStateChaptersContext(); const updateChapter = ReaderService.useUpdateChapter(); @@ -493,6 +470,8 @@ export class ReaderControls { return useCallback( (pageIndex, debounceChapterUpdate = true, endReached = false) => { + const { currentPageIndex, setCurrentPageIndex } = getReaderStore().pages; + if (pageIndex === currentPageIndex && !endReached) { return; } @@ -544,7 +523,6 @@ export class ReaderControls { previousChapter?.id, nextChapter?.id, nextChapters, - currentPageIndex, downloadAheadLimit, visibleChapters, ], @@ -595,7 +573,6 @@ export class ReaderControls { scrollElement: HTMLElement | null, ): (event: React.MouseEvent) => void { const { direction: themeDirection } = useTheme(); - const { currentPageIndex, pages } = userReaderStatePagesContext(); const { setShowPreview } = useReaderTapZoneContext(); const { readingMode, readingDirection, isStaticNav, scrollAmount } = ReaderService.useSettings(); const openPage = ReaderControls.useOpenPage(); @@ -646,8 +623,6 @@ export class ReaderControls { }, [ scrollElement, - currentPageIndex, - pages, readingMode.value, openPage, readingDirection.value, @@ -664,7 +639,7 @@ export class ReaderControls { progressBarRef: RefObject, isDragging: boolean, currentPage: TReaderProgressCurrentPage, - pages: ReaderProgressBarProps['pages'], + pages: ReaderStatePages['pages'], progressBarPosition: ProgressBarPosition, getOptionForDirectionFn: typeof getOptionForDirection, fullSegmentClicks: boolean, diff --git a/src/features/reader/viewer/ReaderChapterViewer.tsx b/src/features/reader/viewer/ReaderChapterViewer.tsx index d8349789..219acc2c 100644 --- a/src/features/reader/viewer/ReaderChapterViewer.tsx +++ b/src/features/reader/viewer/ReaderChapterViewer.tsx @@ -34,7 +34,6 @@ import { createHandleReaderPageLoadError, createUpdateReaderPageLoadState } from import { useReaderConvertPagesForReadingMode } from '@/features/reader/viewer/hooks/useReaderConvertPagesForReadingMode.ts'; import { ReaderTransitionPage } from '@/features/reader/viewer/components/ReaderTransitionPage.tsx'; import { applyStyles } from '@/base/utils/ApplyStyles.ts'; -import { READER_STATE_PAGES_DEFAULTS } from '@/features/reader/ReaderContext.constants.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { useReaderSetPagesState } from '@/features/reader/viewer/hooks/useReaderSetPagesState.ts'; @@ -44,6 +43,7 @@ import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholde import { ReaderInfiniteScrollUpdateChapter } from '@/features/reader/infinite-scroll/ReaderInfiniteScrollUpdateChapter.tsx'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import { ChapterIdInfo } from '@/features/chapter/Chapter.types.ts'; +import { READER_DEFAULT_PAGES_STATE } from '@/features/reader/ReaderStore.constants.ts'; const BaseReaderChapterViewer = ({ currentPageIndex, @@ -138,13 +138,11 @@ const BaseReaderChapterViewer = ({ const [fetchPages, pagesResponse] = requestManager.useGetChapterPagesFetch(chapterId ?? -1); const [arePagesFetched, setArePagesFetched] = useState(false); - const [totalPages, setTotalPages] = useState( - READER_STATE_PAGES_DEFAULTS.totalPages, - ); - const [pageUrls, setPageUrls] = useState(READER_STATE_PAGES_DEFAULTS.pageUrls); - const [pages, setPages] = useState(READER_STATE_PAGES_DEFAULTS.pages); + const [totalPages, setTotalPages] = useState(READER_DEFAULT_PAGES_STATE.totalPages); + const [pageUrls, setPageUrls] = useState(READER_DEFAULT_PAGES_STATE.pageUrls); + const [pages, setPages] = useState(READER_DEFAULT_PAGES_STATE.pages); const [pageLoadStates, setPageLoadStates] = useState( - READER_STATE_PAGES_DEFAULTS.pageLoadStates, + READER_DEFAULT_PAGES_STATE.pageLoadStates, ); const [pagesToSpreadState, setPagesToSpreadState] = useState( pageLoadStates.map(({ url }) => ({ url, isSpread: false })), diff --git a/src/features/reader/viewer/ReaderViewer.tsx b/src/features/reader/viewer/ReaderViewer.tsx index 3b40163a..e7cd03a1 100644 --- a/src/features/reader/viewer/ReaderViewer.tsx +++ b/src/features/reader/viewer/ReaderViewer.tsx @@ -28,11 +28,9 @@ import { ReaderOpenChapterLocationState, ReaderResumeMode, ReaderStateChapters, - ReaderStatePages, ReadingDirection, ReadingMode, } from '@/features/reader/Reader.types.ts'; -import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { MediaQuery } from '@/base/utils/MediaQuery.tsx'; import { ReaderControls } from '@/features/reader/services/ReaderControls.ts'; import { @@ -77,18 +75,6 @@ const READING_MODE_TO_IN_VIEWPORT_TYPE: Record const BaseReaderViewer = forwardRef( ( { - currentPageIndex, - pageToScrollToIndex, - setPageToScrollToIndex, - pages, - totalPages, - setPages, - setPageLoadStates, - setTotalPages, - setCurrentPageIndex, - transitionPageMode, - retryFailedPagesKeyPrefix, - setTransitionPageMode, readingMode, readingDirection, shouldUseInfiniteScroll, @@ -111,34 +97,19 @@ const BaseReaderViewer = forwardRef( setReaderStateChapters, isCurrentChapterReady, }: Pick< - ReaderStatePages, - | 'currentPageIndex' - | 'pageToScrollToIndex' - | 'setPageToScrollToIndex' - | 'pages' - | 'totalPages' - | 'setPages' - | 'setPageLoadStates' - | 'setTotalPages' - | 'setCurrentPageIndex' - | 'transitionPageMode' - | 'retryFailedPagesKeyPrefix' - | 'setTransitionPageMode' + IReaderSettings, + | 'readingMode' + | 'readingDirection' + | 'shouldUseInfiniteScroll' + | 'readerWidth' + | 'pageScaleMode' + | 'shouldOffsetDoubleSpreads' + | 'imagePreLoadAmount' + | 'pageGap' + | 'customFilter' + | 'shouldStretchPage' + | 'isStaticNav' > & - Pick< - IReaderSettings, - | 'readingMode' - | 'readingDirection' - | 'shouldUseInfiniteScroll' - | 'readerWidth' - | 'pageScaleMode' - | 'shouldOffsetDoubleSpreads' - | 'imagePreLoadAmount' - | 'pageGap' - | 'customFilter' - | 'shouldStretchPage' - | 'isStaticNav' - > & Pick & Pick< ReaderStateChapters, @@ -157,6 +128,33 @@ const BaseReaderViewer = forwardRef( ) => { const { direction: themeDirection } = useTheme(); const isOverlayVisible = useReaderStore((state) => state.overlay.isVisible); + const { + currentPageIndex, + pageToScrollToIndex, + setPageToScrollToIndex, + pages, + totalPages, + setPages, + setPageLoadStates, + setTotalPages, + setCurrentPageIndex, + transitionPageMode, + retryFailedPagesKeyPrefix, + setTransitionPageMode, + } = useReaderStoreShallow((state) => ({ + currentPageIndex: state.pages.currentPageIndex, + pageToScrollToIndex: state.pages.pageToScrollToIndex, + setPageToScrollToIndex: state.pages.setPageToScrollToIndex, + pages: state.pages.pages, + totalPages: state.pages.totalPages, + setPages: state.pages.setPages, + setPageLoadStates: state.pages.setPageLoadStates, + setTotalPages: state.pages.setTotalPages, + setCurrentPageIndex: state.pages.setCurrentPageIndex, + transitionPageMode: state.pages.transitionPageMode, + retryFailedPagesKeyPrefix: state.pages.retryFailedPagesKeyPrefix, + setTransitionPageMode: state.pages.setTransitionPageMode, + })); const { resumeMode = ReaderResumeMode.START } = useLocation().state ?? { resumeMode: ReaderResumeMode.START, }; @@ -445,7 +443,6 @@ const BaseReaderViewer = forwardRef( export const ReaderViewer = withPropsFrom( memo(BaseReaderViewer), [ - userReaderStatePagesContext, ReaderService.useSettingsWithoutDefaultFlag, () => ({ updateCurrentPageIndex: ReaderControls.useUpdateCurrentPageIndex() }), useReaderTapZoneContext, @@ -453,17 +450,6 @@ export const ReaderViewer = withPropsFrom( useNavBarContext, ], [ - 'currentPageIndex', - 'pageToScrollToIndex', - 'setPageToScrollToIndex', - 'pages', - 'totalPages', - 'setPages', - 'setPageLoadStates', - 'setTotalPages', - 'setCurrentPageIndex', - 'retryFailedPagesKeyPrefix', - 'setTransitionPageMode', 'readingMode', 'readingDirection', 'shouldUseInfiniteScroll', @@ -476,7 +462,6 @@ export const ReaderViewer = withPropsFrom( 'shouldStretchPage', 'isStaticNav', 'readerNavBarWidth', - 'transitionPageMode', 'updateCurrentPageIndex', 'showPreview', 'setShowPreview', diff --git a/src/features/reader/viewer/components/ReaderTransitionPage.tsx b/src/features/reader/viewer/components/ReaderTransitionPage.tsx index e17d3ac4..adb06766 100644 --- a/src/features/reader/viewer/components/ReaderTransitionPage.tsx +++ b/src/features/reader/viewer/components/ReaderTransitionPage.tsx @@ -14,12 +14,7 @@ import { Link } from 'react-router-dom'; import { ComponentProps, memo, useMemo } from 'react'; import { alpha, useTheme } from '@mui/material/styles'; import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; -import { - IReaderSettings, - ReaderStatePages, - ReaderTransitionPageMode, - ReadingMode, -} from '@/features/reader/Reader.types.ts'; +import { IReaderSettings, ReaderTransitionPageMode, ReadingMode } from '@/features/reader/Reader.types.ts'; import { isTransitionPageVisible } from '@/features/reader/viewer/pager/ReaderPager.utils.tsx'; import { useBackButton } from '@/base/hooks/useBackButton.ts'; import { applyStyles } from '@/base/utils/ApplyStyles.ts'; @@ -34,10 +29,9 @@ import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { getValueFromObject, noOp } from '@/lib/HelperFunctions.ts'; import { READER_BACKGROUND_TO_COLOR } from '@/features/reader/settings/ReaderSettings.constants.tsx'; import { ReaderService } from '@/features/reader/services/ReaderService.ts'; -import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { ChapterType } from '@/lib/graphql/generated/graphql.ts'; import { ChapterIdInfo } from '@/features/chapter/Chapter.types.ts'; -import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts'; +import { useReaderStore, useReaderStoreShallow } from '@/features/reader/ReaderStore.ts'; const ChapterInfo = ({ title, @@ -78,7 +72,6 @@ const ChapterInfo = ({ const BaseReaderTransitionPage = ({ type, - transitionPageMode, readingMode, backgroundColor, shouldShowTransitionPage, @@ -91,7 +84,6 @@ const BaseReaderTransitionPage = ({ readerNavBarWidth, handleBack, }: Pick & - Pick & Pick & { // gets used in the "source props creators" of the "withPropsFrom" call // eslint-disable-next-line react/no-unused-prop-types @@ -108,6 +100,7 @@ const BaseReaderTransitionPage = ({ const { t } = useTranslation(); const manga = useReaderStoreShallow((state) => state.manga); const scrollbar = useReaderStoreShallow((state) => state.scrollbar); + const transitionPageMode = useReaderStore((state) => state.pages.transitionPageMode); const isPreviousType = type === ReaderTransitionPageMode.PREVIOUS; const isNextType = type === ReaderTransitionPageMode.NEXT; @@ -252,7 +245,6 @@ export const ReaderTransitionPage = withPropsFrom( }; }, useNavBarContext, - userReaderStatePagesContext, ReaderService.useSettingsWithoutDefaultFlag, ({ chapterId, type }: Pick, 'chapterId' | 'type'>) => { const handleBack = useBackButton(); @@ -286,7 +278,6 @@ export const ReaderTransitionPage = withPropsFrom( 'nextChapterScanlator', 'readerNavBarWidth', 'backgroundColor', - 'transitionPageMode', 'readingMode', 'handleBack', 'shouldShowTransitionPage', diff --git a/src/features/reader/viewer/hooks/useReaderPreserveScrollPosition.ts b/src/features/reader/viewer/hooks/useReaderPreserveScrollPosition.ts index be47e2a5..43665b97 100644 --- a/src/features/reader/viewer/hooks/useReaderPreserveScrollPosition.ts +++ b/src/features/reader/viewer/hooks/useReaderPreserveScrollPosition.ts @@ -59,7 +59,7 @@ const usePreserveOnValueChange = ( const usePreserveOnWindowResize = ( readingMode: ReadingMode, pageScaleMode: ReaderPageScaleMode, - setPageToScrollToIndex: React.Dispatch>, + setPageToScrollToIndex: (index: number | null) => void, pageIndex: number, ) => { const previousDimensionsRef = useRef({ width: window.innerWidth, height: window.innerHeight });