Move reader "chapters state" to "reader store"
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { ReaderStatePages, ReaderTransitionPageMode } from '@/features/reader/Reader.types.ts';
|
||||
import { ReaderStateChapters, ReaderStatePages, ReaderTransitionPageMode } from '@/features/reader/Reader.types.ts';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
|
||||
export const READER_DEFAULT_PAGES_STATE: Omit<
|
||||
@@ -39,3 +39,22 @@ export const READER_DEFAULT_PAGES_STATE: Omit<
|
||||
transitionPageMode: ReaderTransitionPageMode.NONE,
|
||||
retryFailedPagesKeyPrefix: '',
|
||||
};
|
||||
|
||||
export const READER_DEFAULT_CHAPTERS_STATE = {
|
||||
chapters: {
|
||||
chapters: [],
|
||||
isCurrentChapterReady: false,
|
||||
visibleChapters: {
|
||||
leading: 0,
|
||||
trailing: 0,
|
||||
lastLeadingChapterSourceOrder: 99999,
|
||||
lastTrailingChapterSourceOrder: -1,
|
||||
isLeadingChapterPreloadMode: true,
|
||||
isTrailingChapterPreloadMode: true,
|
||||
scrollIntoView: false,
|
||||
resumeMode: undefined,
|
||||
},
|
||||
},
|
||||
} satisfies {
|
||||
chapters: Omit<ReaderStateChapters, 'setReaderStateChapters'>;
|
||||
};
|
||||
|
||||
@@ -18,9 +18,9 @@ import {
|
||||
createReaderAutoScrollStoreSlice,
|
||||
ReaderAutoScrollStoreSlice,
|
||||
} from '@/features/reader/auto-scroll/ReaderAutoScrollStore.ts';
|
||||
import { ReaderStatePages } from '@/features/reader/Reader.types.ts';
|
||||
import { ReaderStateChapters, 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';
|
||||
import { READER_DEFAULT_CHAPTERS_STATE, READER_DEFAULT_PAGES_STATE } from '@/features/reader/ReaderStore.constants.ts';
|
||||
|
||||
interface ReaderPagesStoreSlice {
|
||||
pages: ReaderStatePages & {
|
||||
@@ -28,7 +28,17 @@ interface ReaderPagesStoreSlice {
|
||||
};
|
||||
}
|
||||
|
||||
interface ReaderStore extends ReaderOverlayStoreSlice, ReaderAutoScrollStoreSlice, ReaderPagesStoreSlice {
|
||||
interface ReaderChaptersStoreSlice {
|
||||
chapters: ReaderStateChapters & {
|
||||
reset: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
interface ReaderStore
|
||||
extends ReaderOverlayStoreSlice,
|
||||
ReaderAutoScrollStoreSlice,
|
||||
ReaderPagesStoreSlice,
|
||||
ReaderChaptersStoreSlice {
|
||||
reset: () => void;
|
||||
manga: TMangaReader | undefined;
|
||||
setManga: (manga: TMangaReader | undefined) => void;
|
||||
@@ -94,6 +104,30 @@ const createReaderPagesStoreSlice = <T extends ReaderPagesStoreSlice>(
|
||||
},
|
||||
});
|
||||
|
||||
const createReaderChaptersStoreSlice = <T extends ReaderChaptersStoreSlice>(
|
||||
...[set, get]: Parameters<ImmerStateCreator<T>>
|
||||
): ReaderChaptersStoreSlice => ({
|
||||
chapters: {
|
||||
...READER_DEFAULT_CHAPTERS_STATE.chapters,
|
||||
reset: () => set(() => ({ chapters: { ...get().chapters, ...READER_DEFAULT_CHAPTERS_STATE.chapters } })),
|
||||
setReaderStateChapters: (state) =>
|
||||
set((draft) => {
|
||||
if (typeof state === 'function') {
|
||||
draft.chapters = {
|
||||
...get().chapters,
|
||||
...state(get().chapters),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
draft.chapters = {
|
||||
...get().chapters,
|
||||
...state,
|
||||
};
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
export const useReaderStore = create<ReaderStore>()(
|
||||
immer((set, get, store) => ({
|
||||
...DEFAULT_STATE,
|
||||
@@ -104,6 +138,7 @@ export const useReaderStore = create<ReaderStore>()(
|
||||
get().overlay.reset();
|
||||
get().autoScroll.reset();
|
||||
get().pages.reset();
|
||||
get().chapters.reset();
|
||||
}),
|
||||
setManga: (manga) =>
|
||||
set((draft) => {
|
||||
@@ -123,6 +158,7 @@ export const useReaderStore = create<ReaderStore>()(
|
||||
...createReaderOverlayStoreSlice(set, get, store),
|
||||
...createReaderAutoScrollStoreSlice(set, get, store),
|
||||
...createReaderPagesStoreSlice(set, get, store),
|
||||
...createReaderChaptersStoreSlice(set, get, store),
|
||||
})),
|
||||
);
|
||||
export const useReaderStoreShallow = <T>(selector: (state: ReaderStore) => T): T =>
|
||||
|
||||
@@ -1,47 +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 { ReaderStateChapters } from '@/features/reader/Reader.types.ts';
|
||||
|
||||
export const READER_STATE_CHAPTERS_DEFAULTS: Omit<ReaderStateChapters, 'setReaderStateChapters'> = {
|
||||
chapters: [],
|
||||
isCurrentChapterReady: false,
|
||||
visibleChapters: {
|
||||
leading: 0,
|
||||
trailing: 0,
|
||||
lastLeadingChapterSourceOrder: 99999,
|
||||
lastTrailingChapterSourceOrder: -1,
|
||||
isLeadingChapterPreloadMode: true,
|
||||
isTrailingChapterPreloadMode: true,
|
||||
scrollIntoView: false,
|
||||
resumeMode: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
export const ReaderStateChaptersContext = createContext<ReaderStateChapters>({
|
||||
...READER_STATE_CHAPTERS_DEFAULTS,
|
||||
setReaderStateChapters: () => {},
|
||||
});
|
||||
|
||||
export const useReaderStateChaptersContext = () => useContext(ReaderStateChaptersContext);
|
||||
|
||||
export const ReaderStateChaptersContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [state, setState] =
|
||||
useState<Omit<ReaderStateChapters, 'setReaderStateChapters'>>(READER_STATE_CHAPTERS_DEFAULTS);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
...state,
|
||||
setReaderStateChapters: setState,
|
||||
}),
|
||||
[state],
|
||||
);
|
||||
|
||||
return <ReaderStateChaptersContext.Provider value={value}>{children}</ReaderStateChaptersContext.Provider>;
|
||||
};
|
||||
@@ -7,11 +7,8 @@
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { ReaderStateChaptersContextProvider } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderStateSettingsContextProvider } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx';
|
||||
|
||||
export const ReaderStateContextProvider = ({ children }: { children: ReactNode }) => (
|
||||
<ReaderStateChaptersContextProvider>
|
||||
<ReaderStateSettingsContextProvider>{children}</ReaderStateSettingsContextProvider>
|
||||
</ReaderStateChaptersContextProvider>
|
||||
<ReaderStateSettingsContextProvider>{children}</ReaderStateSettingsContextProvider>
|
||||
);
|
||||
|
||||
@@ -7,19 +7,14 @@
|
||||
*/
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { ReaderStateChapters, TReaderStateSettingsContext } from '@/features/reader/Reader.types.ts';
|
||||
import { 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'],
|
||||
setSettings: TReaderStateSettingsContext['setSettings'],
|
||||
) => {
|
||||
export const useReaderResetStates = (setSettings: TReaderStateSettingsContext['setSettings']) => {
|
||||
useEffect(
|
||||
() => () => {
|
||||
getReaderStore().reset();
|
||||
setReaderStateChapters(READER_STATE_CHAPTERS_DEFAULTS);
|
||||
|
||||
setSettings(DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG);
|
||||
},
|
||||
|
||||
@@ -16,11 +16,12 @@ import {
|
||||
ReaderOpenChapterLocationState,
|
||||
ReaderStateChapters,
|
||||
} from '@/features/reader/Reader.types.ts';
|
||||
import { READER_STATE_CHAPTERS_DEFAULTS } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { filterChapters } from '@/features/chapter/utils/ChapterList.util.tsx';
|
||||
import { ChapterListOptions } from '@/features/chapter/Chapter.types.ts';
|
||||
import { getReaderChapterFromCache } from '@/features/reader/Reader.utils.ts';
|
||||
import { DirectionOffset } from '@/base/Base.types.ts';
|
||||
import { getReaderStore } from '@/features/reader/ReaderStore.ts';
|
||||
import { READER_DEFAULT_CHAPTERS_STATE } from '@/features/reader/ReaderStore.constants.ts';
|
||||
|
||||
export const useReaderSetChaptersState = (
|
||||
chaptersResponse: ReturnType<typeof requestManager.useGetMangaChapters<GetChaptersReaderQuery>>,
|
||||
@@ -28,7 +29,6 @@ export const useReaderSetChaptersState = (
|
||||
mangaChapters: ReaderStateChapters['mangaChapters'],
|
||||
initialChapter: ReaderStateChapters['initialChapter'],
|
||||
chapterForDuplicatesHandling: ReaderStateChapters['chapterForDuplicatesHandling'],
|
||||
setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'],
|
||||
shouldSkipDupChapters: IReaderSettings['shouldSkipDupChapters'],
|
||||
shouldSkipFilteredChapters: IReaderSettings['shouldSkipFilteredChapters'],
|
||||
chapterListOptions: ChapterListOptions,
|
||||
@@ -78,7 +78,7 @@ export const useReaderSetChaptersState = (
|
||||
navigate('', { replace: true, state: { ...locationState, updateInitialChapter: undefined } });
|
||||
}
|
||||
|
||||
setReaderStateChapters((prevState) => {
|
||||
getReaderStore().chapters.setReaderStateChapters((prevState) => {
|
||||
const hasCurrentChapterChanged = newCurrentChapter?.id !== prevState.currentChapter?.id;
|
||||
|
||||
return {
|
||||
@@ -93,13 +93,13 @@ export const useReaderSetChaptersState = (
|
||||
isCurrentChapterReady: hasCurrentChapterChanged ? false : prevState.isCurrentChapterReady,
|
||||
visibleChapters: hasInitialChapterChanged
|
||||
? {
|
||||
...READER_STATE_CHAPTERS_DEFAULTS.visibleChapters,
|
||||
...READER_DEFAULT_CHAPTERS_STATE.chapters.visibleChapters,
|
||||
lastLeadingChapterSourceOrder:
|
||||
newInitialChapter?.sourceOrder ??
|
||||
READER_STATE_CHAPTERS_DEFAULTS.visibleChapters.lastLeadingChapterSourceOrder,
|
||||
READER_DEFAULT_CHAPTERS_STATE.chapters.visibleChapters.lastLeadingChapterSourceOrder,
|
||||
lastTrailingChapterSourceOrder:
|
||||
newInitialChapter?.sourceOrder ??
|
||||
READER_STATE_CHAPTERS_DEFAULTS.visibleChapters.lastTrailingChapterSourceOrder,
|
||||
READER_DEFAULT_CHAPTERS_STATE.chapters.visibleChapters.lastTrailingChapterSourceOrder,
|
||||
isLeadingChapterPreloadMode: false,
|
||||
isTrailingChapterPreloadMode: false,
|
||||
// do not set "scrollIntoView" to "true" for the initial render
|
||||
|
||||
@@ -24,9 +24,6 @@ import { makeToast } from '@/base/utils/Toast.ts';
|
||||
import { MobileHeaderProps } from '@/features/reader/overlay/ReaderOverlay.types.ts';
|
||||
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
|
||||
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
||||
import { ReaderStateChapters } from '@/features/reader/Reader.types.ts';
|
||||
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderLibraryButton } from '@/features/reader/overlay/navigation/components/ReaderLibraryButton.tsx';
|
||||
import { ReaderBookmarkButton } from '@/features/reader/overlay/navigation/components/ReaderBookmarkButton.tsx';
|
||||
import { FALLBACK_CHAPTER } from '@/features/chapter/Chapter.constants.ts';
|
||||
@@ -37,12 +34,10 @@ import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
|
||||
|
||||
const DEFAULT_MANGA = { ...FALLBACK_MANGA, title: '' };
|
||||
|
||||
const BaseReaderOverlayHeaderMobile = forwardRef<
|
||||
HTMLDivElement,
|
||||
MobileHeaderProps & Pick<ReaderStateChapters, 'currentChapter'>
|
||||
>(({ isVisible, currentChapter }, ref) => {
|
||||
const BaseReaderOverlayHeaderMobile = forwardRef<HTMLDivElement, MobileHeaderProps>(({ isVisible }, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const popupState = usePopupState({ popupId: 'reader-overlay-more-menu', variant: 'popover' });
|
||||
const currentChapter = useReaderStoreShallow((state) => state.chapters.currentChapter);
|
||||
|
||||
const manga = useReaderStoreShallow((state) => state.manga);
|
||||
const scrollbar = useReaderStoreShallow((state) => state.scrollbar);
|
||||
@@ -129,8 +124,4 @@ const BaseReaderOverlayHeaderMobile = forwardRef<
|
||||
);
|
||||
});
|
||||
|
||||
export const ReaderOverlayHeaderMobile = withPropsFrom(
|
||||
memo(BaseReaderOverlayHeaderMobile),
|
||||
[useReaderStateChaptersContext],
|
||||
['currentChapter'],
|
||||
);
|
||||
export const ReaderOverlayHeaderMobile = memo(BaseReaderOverlayHeaderMobile);
|
||||
|
||||
@@ -24,11 +24,10 @@ 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 { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
|
||||
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
|
||||
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||
import { IReaderSettings, ReaderStateChapters } from '@/features/reader/Reader.types.ts';
|
||||
import { IReaderSettings } from '@/features/reader/Reader.types.ts';
|
||||
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
|
||||
import { ReaderExitButton } from '@/features/reader/overlay/navigation/components/ReaderExitButton.tsx';
|
||||
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
|
||||
@@ -55,17 +54,18 @@ const BaseReaderNavBarDesktop = ({
|
||||
isVisible,
|
||||
openSettings,
|
||||
setReaderNavBarWidth,
|
||||
chapters,
|
||||
currentChapter,
|
||||
previousChapter,
|
||||
nextChapter,
|
||||
isStaticNav,
|
||||
}: ReaderNavBarDesktopProps &
|
||||
Pick<NavbarContextType, 'setReaderNavBarWidth'> &
|
||||
Pick<ReaderStateChapters, 'currentChapter' | 'previousChapter' | 'nextChapter' | 'chapters'> &
|
||||
Pick<IReaderSettings, 'isStaticNav'>) => {
|
||||
const { t } = useTranslation();
|
||||
const manga = useReaderStoreShallow((state) => state.manga);
|
||||
const { chapters, currentChapter, previousChapter, nextChapter } = useReaderStoreShallow((state) => ({
|
||||
chapters: state.chapters.chapters,
|
||||
currentChapter: state.chapters.currentChapter,
|
||||
previousChapter: state.chapters.previousChapter,
|
||||
nextChapter: state.chapters.nextChapter,
|
||||
}));
|
||||
|
||||
const [navBarElement, setNavBarElement] = useState<HTMLDivElement | null>();
|
||||
useResizeObserver(
|
||||
@@ -146,6 +146,6 @@ const BaseReaderNavBarDesktop = ({
|
||||
|
||||
export const ReaderNavBarDesktop = withPropsFrom(
|
||||
memo(BaseReaderNavBarDesktop),
|
||||
[useNavBarContext, useReaderStateChaptersContext, ReaderService.useSettingsWithoutDefaultFlag],
|
||||
['setReaderNavBarWidth', 'chapters', 'currentChapter', 'previousChapter', 'nextChapter', 'isStaticNav'],
|
||||
[useNavBarContext, ReaderService.useSettingsWithoutDefaultFlag],
|
||||
['setReaderNavBarWidth', 'isStaticNav'],
|
||||
);
|
||||
|
||||
@@ -15,10 +15,7 @@ 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 } 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 { 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';
|
||||
@@ -26,8 +23,13 @@ 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';
|
||||
import { ChapterDownloadInfo, ChapterIdInfo } from '@/features/chapter/Chapter.types.ts';
|
||||
|
||||
const DownloadButton = ({ currentChapter }: Required<Pick<ReaderStateChapters, 'currentChapter'>>) => {
|
||||
const DownloadButton = ({
|
||||
currentChapter,
|
||||
}: {
|
||||
currentChapter: NullAndUndefined<ChapterIdInfo & ChapterDownloadInfo>;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const downloadStatus = Chapters.useDownloadStatusFromCache(currentChapter?.id ?? -1);
|
||||
@@ -59,76 +61,64 @@ const DownloadButton = ({ currentChapter }: Required<Pick<ReaderStateChapters, '
|
||||
);
|
||||
};
|
||||
|
||||
const BaseReaderNavBarDesktopActions = memo(
|
||||
({ currentChapter }: Required<Pick<ReaderStateChapters, 'currentChapter'>>) => {
|
||||
const { id, isBookmarked, realUrl } = currentChapter ?? FALLBACK_CHAPTER;
|
||||
export const ReaderNavBarDesktopActions = memo(() => {
|
||||
const currentChapter = useReaderStoreShallow((state) => state.chapters.currentChapter);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { pageLoadStates, setPageLoadStates, setRetryFailedPagesKeyPrefix } = useReaderStoreShallow((state) => ({
|
||||
pageLoadStates: state.pages.pageLoadStates,
|
||||
setPageLoadStates: state.pages.setPageLoadStates,
|
||||
setRetryFailedPagesKeyPrefix: state.pages.setRetryFailedPagesKeyPrefix,
|
||||
}));
|
||||
const { id, isBookmarked, realUrl } = currentChapter ?? FALLBACK_CHAPTER;
|
||||
|
||||
const pageRetryKeyPrefix = useRef<number>(0);
|
||||
const { t } = useTranslation();
|
||||
const { pageLoadStates, setPageLoadStates, setRetryFailedPagesKeyPrefix } = useReaderStoreShallow((state) => ({
|
||||
pageLoadStates: state.pages.pageLoadStates,
|
||||
setPageLoadStates: state.pages.setPageLoadStates,
|
||||
setRetryFailedPagesKeyPrefix: state.pages.setRetryFailedPagesKeyPrefix,
|
||||
}));
|
||||
|
||||
const haveSomePagesFailedToLoad = useMemo(
|
||||
() => pageLoadStates.some((pageLoadState) => pageLoadState.error),
|
||||
[pageLoadStates],
|
||||
);
|
||||
const pageRetryKeyPrefix = useRef<number>(0);
|
||||
|
||||
return (
|
||||
<Stack sx={{ flexDirection: 'row', justifyContent: 'center', gap: 1 }}>
|
||||
<ReaderLibraryButton />
|
||||
<ReaderBookmarkButton id={id} isBookmarked={isBookmarked} />
|
||||
<CustomTooltip title={t('reader.button.retry_load_pages')} disabled={!haveSomePagesFailedToLoad}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setPageLoadStates((statePageLoadStates) =>
|
||||
statePageLoadStates.map((pageLoadState) => ({
|
||||
url: pageLoadState.url,
|
||||
loaded: pageLoadState.loaded,
|
||||
})),
|
||||
);
|
||||
setRetryFailedPagesKeyPrefix(`${pageRetryKeyPrefix.current}`);
|
||||
pageRetryKeyPrefix.current = (pageRetryKeyPrefix.current + 1) % 1000;
|
||||
}}
|
||||
disabled={!haveSomePagesFailedToLoad}
|
||||
color="inherit"
|
||||
>
|
||||
<ReplayIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
<DownloadButton currentChapter={currentChapter} />
|
||||
<CustomTooltip title={t('global.button.open_browser')} disabled={!realUrl}>
|
||||
<IconButton
|
||||
disabled={!realUrl}
|
||||
href={realUrl ?? ''}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
color="inherit"
|
||||
>
|
||||
<IconBrowser />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
<CustomTooltip title={t('global.button.open_webview')} disabled={!realUrl}>
|
||||
<IconButton
|
||||
disabled={!realUrl}
|
||||
href={realUrl ? requestManager.getWebviewUrl(realUrl) : ''}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
color="inherit"
|
||||
>
|
||||
<IconWebView />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
</Stack>
|
||||
);
|
||||
},
|
||||
);
|
||||
const haveSomePagesFailedToLoad = useMemo(
|
||||
() => pageLoadStates.some((pageLoadState) => pageLoadState.error),
|
||||
[pageLoadStates],
|
||||
);
|
||||
|
||||
export const ReaderNavBarDesktopActions = withPropsFrom(
|
||||
BaseReaderNavBarDesktopActions,
|
||||
[useReaderStateChaptersContext],
|
||||
['currentChapter'],
|
||||
);
|
||||
return (
|
||||
<Stack sx={{ flexDirection: 'row', justifyContent: 'center', gap: 1 }}>
|
||||
<ReaderLibraryButton />
|
||||
<ReaderBookmarkButton id={id} isBookmarked={isBookmarked} />
|
||||
<CustomTooltip title={t('reader.button.retry_load_pages')} disabled={!haveSomePagesFailedToLoad}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setPageLoadStates((statePageLoadStates) =>
|
||||
statePageLoadStates.map((pageLoadState) => ({
|
||||
url: pageLoadState.url,
|
||||
loaded: pageLoadState.loaded,
|
||||
})),
|
||||
);
|
||||
setRetryFailedPagesKeyPrefix(`${pageRetryKeyPrefix.current}`);
|
||||
pageRetryKeyPrefix.current = (pageRetryKeyPrefix.current + 1) % 1000;
|
||||
}}
|
||||
disabled={!haveSomePagesFailedToLoad}
|
||||
color="inherit"
|
||||
>
|
||||
<ReplayIcon />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
<DownloadButton currentChapter={currentChapter} />
|
||||
<CustomTooltip title={t('global.button.open_browser')} disabled={!realUrl}>
|
||||
<IconButton disabled={!realUrl} href={realUrl ?? ''} rel="noreferrer" target="_blank" color="inherit">
|
||||
<IconBrowser />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
<CustomTooltip title={t('global.button.open_webview')} disabled={!realUrl}>
|
||||
<IconButton
|
||||
disabled={!realUrl}
|
||||
href={realUrl ? requestManager.getWebviewUrl(realUrl) : ''}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
color="inherit"
|
||||
>
|
||||
<IconWebView />
|
||||
</IconButton>
|
||||
</CustomTooltip>
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -23,20 +23,19 @@ import { ReaderBottomBarMobileProps } from '@/features/reader/overlay/ReaderOver
|
||||
import { MobileReaderProgressBar } from '@/features/reader/overlay/progress-bar/mobile/MobileReaderProgressBar.tsx';
|
||||
import { ReaderChapterList } from '@/features/reader/overlay/navigation/components/ReaderChapterList.tsx';
|
||||
import { ReaderBottomBarMobileQuickSettings } from '@/features/reader/overlay/navigation/mobile/quick-settings/ReaderBottomBarMobileQuickSettings.tsx';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderStateChapters } from '@/features/reader/Reader.types.ts';
|
||||
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
|
||||
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
|
||||
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
|
||||
|
||||
const BaseReaderBottomBarMobile = ({
|
||||
openSettings,
|
||||
isVisible,
|
||||
currentChapter,
|
||||
chapters,
|
||||
topOffset = 0,
|
||||
}: ReaderBottomBarMobileProps & Pick<ReaderStateChapters, 'currentChapter' | 'chapters'> & { topOffset?: number }) => {
|
||||
}: ReaderBottomBarMobileProps & { topOffset?: number }) => {
|
||||
const { t } = useTranslation();
|
||||
const { currentChapter, chapters } = useReaderStoreShallow((state) => ({
|
||||
currentChapter: state.chapters.currentChapter,
|
||||
chapters: state.chapters.chapters,
|
||||
}));
|
||||
|
||||
const chapterListPopupState = usePopupState({ variant: 'dialog', popupId: 'reader-chapter-list-dialog' });
|
||||
const quickSettingsPopupState = usePopupState({ variant: 'dialog', popupId: 'reader-quick-settings-dialog' });
|
||||
@@ -130,8 +129,4 @@ const BaseReaderBottomBarMobile = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const ReaderBottomBarMobile = withPropsFrom(
|
||||
memo(BaseReaderBottomBarMobile),
|
||||
[useReaderStateChaptersContext],
|
||||
['currentChapter', 'chapters'],
|
||||
);
|
||||
export const ReaderBottomBarMobile = memo(BaseReaderBottomBarMobile);
|
||||
|
||||
@@ -15,14 +15,13 @@ import Box from '@mui/material/Box';
|
||||
import { ComponentProps, memo, useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import Slide, { SlideProps } from '@mui/material/Slide';
|
||||
import { ReaderProgressBar } from '@/features/reader/overlay/progress-bar/ReaderProgressBar.tsx';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
|
||||
import {
|
||||
getPage,
|
||||
getProgressBarPositionInfo,
|
||||
} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx';
|
||||
import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts';
|
||||
import { IReaderSettings, ProgressBarPosition, ReaderStateChapters } from '@/features/reader/Reader.types.ts';
|
||||
import { IReaderSettings, ProgressBarPosition } from '@/features/reader/Reader.types.ts';
|
||||
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';
|
||||
@@ -43,8 +42,6 @@ const PROGRESS_BAR_POSITION_TO_SLIDE_DIRECTION: Record<ProgressBarPosition, Slid
|
||||
};
|
||||
|
||||
const BaseMobileReaderProgressBar = ({
|
||||
previousChapter,
|
||||
nextChapter,
|
||||
setIsMaximized,
|
||||
isDragging,
|
||||
direction: readerDirection,
|
||||
@@ -52,8 +49,7 @@ const BaseMobileReaderProgressBar = ({
|
||||
progressBarPositionAutoVertical,
|
||||
topOffset = 0,
|
||||
bottomOffset = 0,
|
||||
}: Pick<ReaderStateChapters, 'previousChapter' | 'nextChapter'> &
|
||||
Pick<TReaderProgressBarContext, 'setIsMaximized' | 'isDragging'> &
|
||||
}: Pick<TReaderProgressBarContext, 'setIsMaximized' | 'isDragging'> &
|
||||
Pick<IReaderSettings, 'progressBarPosition' | 'progressBarPositionAutoVertical'> & {
|
||||
direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
|
||||
topOffset?: number;
|
||||
@@ -66,6 +62,10 @@ const BaseMobileReaderProgressBar = ({
|
||||
currentPageIndex: state.pages.currentPageIndex,
|
||||
pages: state.pages.pages,
|
||||
}));
|
||||
const { previousChapter, nextChapter } = useReaderStore((state) => ({
|
||||
previousChapter: state.chapters.previousChapter,
|
||||
nextChapter: state.chapters.nextChapter,
|
||||
}));
|
||||
|
||||
const [, setRefreshProgressBarPosition] = useState({});
|
||||
useResizeObserver(
|
||||
@@ -354,18 +354,9 @@ const BaseMobileReaderProgressBar = ({
|
||||
export const MobileReaderProgressBar = withPropsFrom(
|
||||
memo(BaseMobileReaderProgressBar),
|
||||
[
|
||||
useReaderStateChaptersContext,
|
||||
useReaderProgressBarContext,
|
||||
() => ({ direction: ReaderService.useGetThemeDirection() }),
|
||||
ReaderService.useSettingsWithoutDefaultFlag,
|
||||
],
|
||||
[
|
||||
'previousChapter',
|
||||
'nextChapter',
|
||||
'setIsMaximized',
|
||||
'isDragging',
|
||||
'direction',
|
||||
'progressBarPosition',
|
||||
'progressBarPositionAutoVertical',
|
||||
],
|
||||
['setIsMaximized', 'isDragging', 'direction', 'progressBarPosition', 'progressBarPositionAutoVertical'],
|
||||
);
|
||||
|
||||
@@ -30,13 +30,11 @@ import { ReaderHotkeys } from '@/features/reader/hotkeys/ReaderHotkeys.tsx';
|
||||
import {
|
||||
IReaderSettings,
|
||||
IReaderSettingsWithDefaultFlag,
|
||||
ReaderStateChapters,
|
||||
TReaderStateSettingsContext,
|
||||
} from '@/features/reader/Reader.types.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { TReaderTapZoneContext } from '@/features/reader/tap-zones/TapZoneLayout.types.ts';
|
||||
import { useReaderTapZoneContext } from '@/features/reader/tap-zones/ReaderTapZoneContext.tsx';
|
||||
import { useReaderResetStates } from '@/features/reader/hooks/useReaderResetStates.ts';
|
||||
@@ -61,11 +59,6 @@ const BaseReader = ({
|
||||
shouldShowReadingModePreview,
|
||||
shouldShowTapZoneLayoutPreview,
|
||||
setSettings,
|
||||
mangaChapters,
|
||||
initialChapter,
|
||||
chapterForDuplicatesHandling,
|
||||
currentChapter,
|
||||
setReaderStateChapters,
|
||||
setShowPreview,
|
||||
}: Pick<NavbarContextType, 'setOverride' | 'readerNavBarWidth'> &
|
||||
Pick<TReaderStateSettingsContext, 'setSettings'> &
|
||||
@@ -78,18 +71,18 @@ const BaseReader = ({
|
||||
| 'shouldShowTapZoneLayoutPreview'
|
||||
> &
|
||||
Pick<IReaderSettingsWithDefaultFlag, 'readingMode' | 'tapZoneLayout' | 'tapZoneInvertMode'> &
|
||||
Pick<
|
||||
ReaderStateChapters,
|
||||
| 'mangaChapters'
|
||||
| 'initialChapter'
|
||||
| 'chapterForDuplicatesHandling'
|
||||
| 'currentChapter'
|
||||
| 'setReaderStateChapters'
|
||||
> &
|
||||
Pick<TReaderTapZoneContext, 'setShowPreview'>) => {
|
||||
const { t } = useTranslation();
|
||||
const manga = useReaderStoreShallow((state) => state.manga);
|
||||
const overlay = useReaderStoreShallow((state) => state.overlay);
|
||||
const { mangaChapters, initialChapter, chapterForDuplicatesHandling, currentChapter } = useReaderStoreShallow(
|
||||
(state) => ({
|
||||
mangaChapters: state.chapters.mangaChapters,
|
||||
initialChapter: state.chapters.initialChapter,
|
||||
chapterForDuplicatesHandling: state.chapters.chapterForDuplicatesHandling,
|
||||
currentChapter: state.chapters.currentChapter,
|
||||
}),
|
||||
);
|
||||
|
||||
const scrollElementRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
@@ -130,7 +123,7 @@ const BaseReader = ({
|
||||
useReaderStore.getState().setManga(mangaResponse.data?.manga);
|
||||
}, [mangaResponse.data?.manga]);
|
||||
|
||||
useReaderResetStates(setReaderStateChapters, setSettings);
|
||||
useReaderResetStates(setSettings);
|
||||
useReaderSetSettingsState(
|
||||
mangaResponse,
|
||||
defaultSettingsResponse,
|
||||
@@ -156,7 +149,6 @@ const BaseReader = ({
|
||||
mangaChapters,
|
||||
initialChapter,
|
||||
chapterForDuplicatesHandling,
|
||||
setReaderStateChapters,
|
||||
shouldSkipDupChapters,
|
||||
shouldSkipFilteredChapters,
|
||||
chapterListOptions,
|
||||
@@ -263,7 +255,6 @@ export const Reader = withPropsFrom(
|
||||
memo(BaseReader),
|
||||
[
|
||||
useNavBarContext,
|
||||
useReaderStateChaptersContext,
|
||||
useReaderStateSettingsContext,
|
||||
() => {
|
||||
const {
|
||||
@@ -299,11 +290,6 @@ export const Reader = withPropsFrom(
|
||||
'shouldShowReadingModePreview',
|
||||
'shouldShowTapZoneLayoutPreview',
|
||||
'setSettings',
|
||||
'mangaChapters',
|
||||
'initialChapter',
|
||||
'chapterForDuplicatesHandling',
|
||||
'currentChapter',
|
||||
'setReaderStateChapters',
|
||||
'setShowPreview',
|
||||
],
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { MutableRefObject, RefObject, useCallback, useEffect, useMemo } from 'react';
|
||||
import { MutableRefObject, RefObject, useCallback, useEffect } from 'react';
|
||||
import { Direction, useTheme } from '@mui/material/styles';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TFunction } from 'i18next';
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
} from '@/features/reader/overlay/progress-bar/ReaderProgressBar.utils.tsx';
|
||||
import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts';
|
||||
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import {
|
||||
PageInViewportType,
|
||||
ProgressBarPosition,
|
||||
@@ -173,19 +172,20 @@ export class ReaderControls {
|
||||
shouldInformAboutScanlatorChange,
|
||||
shouldUseInfiniteScroll,
|
||||
} = ReaderService.useSettings();
|
||||
const {
|
||||
currentChapter,
|
||||
previousChapter,
|
||||
nextChapter,
|
||||
chapters,
|
||||
visibleChapters: { lastLeadingChapterSourceOrder, lastTrailingChapterSourceOrder },
|
||||
setReaderStateChapters,
|
||||
} = useReaderStateChaptersContext();
|
||||
|
||||
const openChapter = ReaderService.useNavigateToChapter();
|
||||
|
||||
return useCallback(
|
||||
(offset, doTransitionCheck = true, scrollIntoView = true) => {
|
||||
const {
|
||||
currentChapter,
|
||||
previousChapter,
|
||||
nextChapter,
|
||||
chapters,
|
||||
visibleChapters: { lastLeadingChapterSourceOrder, lastTrailingChapterSourceOrder },
|
||||
setReaderStateChapters,
|
||||
} = getReaderStore().chapters;
|
||||
|
||||
if (!currentChapter) {
|
||||
return;
|
||||
}
|
||||
@@ -266,13 +266,10 @@ export class ReaderControls {
|
||||
},
|
||||
[
|
||||
t,
|
||||
currentChapter?.id,
|
||||
openChapter,
|
||||
readingMode.value,
|
||||
shouldInformAboutMissingChapter,
|
||||
shouldInformAboutScanlatorChange,
|
||||
lastLeadingChapterSourceOrder,
|
||||
lastTrailingChapterSourceOrder,
|
||||
shouldUseInfiniteScroll,
|
||||
],
|
||||
);
|
||||
@@ -343,7 +340,6 @@ export class ReaderControls {
|
||||
forceDirection?: Direction,
|
||||
hideOverlay?: boolean,
|
||||
) => void {
|
||||
const { previousChapter, nextChapter } = useReaderStateChaptersContext();
|
||||
const { setShowPreview } = useReaderTapZoneContext();
|
||||
const { readingDirection, readingMode, shouldShowTransitionPage } = ReaderService.useSettings();
|
||||
const openChapter = ReaderControls.useOpenChapter();
|
||||
@@ -398,7 +394,7 @@ export class ReaderControls {
|
||||
isFirstPage &&
|
||||
(!shouldShowTransitionPage || isPreviousTransitionPageVisible) &&
|
||||
convertedPage === 'previous' &&
|
||||
!!previousChapter;
|
||||
!!getReaderStore().chapters.previousChapter;
|
||||
if (shouldOpenPreviousChapter) {
|
||||
openChapter('previous');
|
||||
return;
|
||||
@@ -408,7 +404,7 @@ export class ReaderControls {
|
||||
isLastPage &&
|
||||
(!shouldShowTransitionPage || isNextTransitionPageVisible) &&
|
||||
convertedPage === 'next' &&
|
||||
!!nextChapter;
|
||||
!!getReaderStore().chapters.nextChapter;
|
||||
if (shouldOpenNextChapter) {
|
||||
openChapter('next');
|
||||
return;
|
||||
@@ -442,7 +438,7 @@ export class ReaderControls {
|
||||
|
||||
setPageToScrollToIndex(isPreviousMode ? previousPageIndex : nextPageIndex);
|
||||
},
|
||||
[direction, openChapter, !!previousChapter, !!nextChapter, shouldShowTransitionPage, readingMode.value],
|
||||
[direction, openChapter, shouldShowTransitionPage, readingMode.value],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -451,26 +447,24 @@ export class ReaderControls {
|
||||
debounceChapterUpdate?: boolean,
|
||||
endReached?: boolean,
|
||||
) => void {
|
||||
const { currentChapter, chapters, previousChapter, nextChapter, visibleChapters, setReaderStateChapters } =
|
||||
useReaderStateChaptersContext();
|
||||
const updateChapter = ReaderService.useUpdateChapter();
|
||||
const {
|
||||
settings: { downloadAheadLimit },
|
||||
} = useMetadataServerSettings();
|
||||
|
||||
const nextChapters = useMemo(() => {
|
||||
if (!currentChapter) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Chapters.getNextChapters(currentChapter, chapters, {
|
||||
offset: DirectionOffset.NEXT,
|
||||
});
|
||||
}, [currentChapter?.id, chapters]);
|
||||
|
||||
return useCallback(
|
||||
(pageIndex, debounceChapterUpdate = true, endReached = false) => {
|
||||
const { currentPageIndex, setCurrentPageIndex } = getReaderStore().pages;
|
||||
const {
|
||||
pages: { currentPageIndex, setCurrentPageIndex },
|
||||
chapters: {
|
||||
currentChapter,
|
||||
chapters,
|
||||
previousChapter,
|
||||
nextChapter,
|
||||
visibleChapters,
|
||||
setReaderStateChapters,
|
||||
},
|
||||
} = getReaderStore();
|
||||
|
||||
if (pageIndex === currentPageIndex && !endReached) {
|
||||
return;
|
||||
@@ -482,6 +476,10 @@ export class ReaderControls {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextChapters = Chapters.getNextChapters(currentChapter, chapters, {
|
||||
offset: DirectionOffset.NEXT,
|
||||
});
|
||||
|
||||
const direction = currentPageIndex > pageIndex ? DirectionOffset.PREVIOUS : DirectionOffset.NEXT;
|
||||
|
||||
ReaderService.downloadAhead(currentChapter, nextChapter, nextChapters, pageIndex, downloadAheadLimit);
|
||||
@@ -518,14 +516,7 @@ export class ReaderControls {
|
||||
|
||||
handleCurrentPageIndexChange();
|
||||
},
|
||||
[
|
||||
currentChapter?.id,
|
||||
previousChapter?.id,
|
||||
nextChapter?.id,
|
||||
nextChapters,
|
||||
downloadAheadLimit,
|
||||
visibleChapters,
|
||||
],
|
||||
[downloadAheadLimit],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Direction, useTheme } from '@mui/material/styles';
|
||||
import { t as translate } from 'i18next';
|
||||
@@ -36,7 +36,6 @@ import { useBackButton } from '@/base/hooks/useBackButton.ts';
|
||||
import { GLOBAL_READER_SETTING_KEYS } from '@/features/reader/settings/ReaderSettings.constants.tsx';
|
||||
import { useReaderStateSettingsContext } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx';
|
||||
import { UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { useMetadataServerSettings } from '@/features/settings/services/ServerSettingsMetadata.ts';
|
||||
import {
|
||||
getChapterIdsForDownloadAhead,
|
||||
@@ -155,30 +154,26 @@ export class ReaderService {
|
||||
}
|
||||
|
||||
static useUpdateChapter(): (patch: UpdateChapterPatchInput) => void {
|
||||
const { currentChapter, mangaChapters, chapters } = useReaderStateChaptersContext();
|
||||
const { shouldSkipDupChapters } = ReaderService.useSettings();
|
||||
const {
|
||||
settings: { deleteChaptersWhileReading, deleteChaptersWithBookmark, updateProgressAfterReading },
|
||||
} = useMetadataServerSettings();
|
||||
|
||||
const previousChapters = useMemo(() => {
|
||||
if (!currentChapter) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Chapters.getNextChapters(currentChapter, chapters, {
|
||||
offset: DirectionOffset.PREVIOUS,
|
||||
});
|
||||
}, [currentChapter?.id, chapters]);
|
||||
|
||||
return useCallback(
|
||||
(patch) => {
|
||||
const { manga } = getReaderStore();
|
||||
const {
|
||||
manga,
|
||||
chapters: { currentChapter, mangaChapters, chapters },
|
||||
} = getReaderStore();
|
||||
|
||||
if (!manga || !currentChapter || !mangaChapters) {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousChapters = Chapters.getNextChapters(currentChapter, chapters, {
|
||||
offset: DirectionOffset.PREVIOUS,
|
||||
});
|
||||
|
||||
const update = async () => {
|
||||
const chapterIdsToUpdate = Chapters.getIds(
|
||||
shouldSkipDupChapters
|
||||
@@ -234,15 +229,7 @@ export class ReaderService {
|
||||
|
||||
ReaderService.getOrCreateChapterUpdateQueue(currentChapter.id).enqueue(`${currentChapter.id}`, update);
|
||||
},
|
||||
[
|
||||
currentChapter?.id,
|
||||
mangaChapters,
|
||||
previousChapters,
|
||||
shouldSkipDupChapters,
|
||||
deleteChaptersWhileReading,
|
||||
deleteChaptersWithBookmark,
|
||||
updateProgressAfterReading,
|
||||
],
|
||||
[shouldSkipDupChapters, deleteChaptersWhileReading, deleteChaptersWithBookmark, updateProgressAfterReading],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
PageInViewportType,
|
||||
ReaderOpenChapterLocationState,
|
||||
ReaderResumeMode,
|
||||
ReaderStateChapters,
|
||||
ReadingDirection,
|
||||
ReadingMode,
|
||||
} from '@/features/reader/Reader.types.ts';
|
||||
@@ -49,7 +48,6 @@ import { useReaderHorizontalModeInvertXYScrolling } from '@/features/reader/view
|
||||
import { useReaderHideCursorOnInactivity } from '@/features/reader/viewer/hooks/useReaderHideCursorOnInactivity.ts';
|
||||
import { useReaderScrollToStartOnPageChange } from '@/features/reader/viewer/hooks/useReaderScrollToStartOnPageChange.ts';
|
||||
import { useReaderHandlePageSelection } from '@/features/reader/viewer/hooks/useReaderHandlePageSelection.ts';
|
||||
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderChapterViewer } from '@/features/reader/viewer/ReaderChapterViewer.tsx';
|
||||
import {
|
||||
getPreviousNextChapterVisibility,
|
||||
@@ -90,12 +88,6 @@ const BaseReaderViewer = forwardRef(
|
||||
updateCurrentPageIndex,
|
||||
showPreview,
|
||||
setShowPreview,
|
||||
initialChapter,
|
||||
currentChapter,
|
||||
chapters,
|
||||
visibleChapters,
|
||||
setReaderStateChapters,
|
||||
isCurrentChapterReady,
|
||||
}: Pick<
|
||||
IReaderSettings,
|
||||
| 'readingMode'
|
||||
@@ -111,15 +103,6 @@ const BaseReaderViewer = forwardRef(
|
||||
| 'isStaticNav'
|
||||
> &
|
||||
Pick<NavbarContextType, 'readerNavBarWidth'> &
|
||||
Pick<
|
||||
ReaderStateChapters,
|
||||
| 'initialChapter'
|
||||
| 'currentChapter'
|
||||
| 'chapters'
|
||||
| 'visibleChapters'
|
||||
| 'setReaderStateChapters'
|
||||
| 'isCurrentChapterReady'
|
||||
> &
|
||||
TReaderTapZoneContext & {
|
||||
updateCurrentPageIndex: ReturnType<typeof ReaderControls.useUpdateCurrentPageIndex>;
|
||||
},
|
||||
@@ -155,6 +138,21 @@ const BaseReaderViewer = forwardRef(
|
||||
retryFailedPagesKeyPrefix: state.pages.retryFailedPagesKeyPrefix,
|
||||
setTransitionPageMode: state.pages.setTransitionPageMode,
|
||||
}));
|
||||
const {
|
||||
initialChapter,
|
||||
currentChapter,
|
||||
chapters,
|
||||
visibleChapters,
|
||||
setReaderStateChapters,
|
||||
isCurrentChapterReady,
|
||||
} = useReaderStoreShallow((state) => ({
|
||||
initialChapter: state.chapters.initialChapter,
|
||||
currentChapter: state.chapters.currentChapter,
|
||||
chapters: state.chapters.chapters,
|
||||
visibleChapters: state.chapters.visibleChapters,
|
||||
setReaderStateChapters: state.chapters.setReaderStateChapters,
|
||||
isCurrentChapterReady: state.chapters.isCurrentChapterReady,
|
||||
}));
|
||||
const { resumeMode = ReaderResumeMode.START } = useLocation<ReaderOpenChapterLocationState>().state ?? {
|
||||
resumeMode: ReaderResumeMode.START,
|
||||
};
|
||||
@@ -446,7 +444,6 @@ export const ReaderViewer = withPropsFrom(
|
||||
ReaderService.useSettingsWithoutDefaultFlag,
|
||||
() => ({ updateCurrentPageIndex: ReaderControls.useUpdateCurrentPageIndex() }),
|
||||
useReaderTapZoneContext,
|
||||
useReaderStateChaptersContext,
|
||||
useNavBarContext,
|
||||
],
|
||||
[
|
||||
@@ -465,11 +462,5 @@ export const ReaderViewer = withPropsFrom(
|
||||
'updateCurrentPageIndex',
|
||||
'showPreview',
|
||||
'setShowPreview',
|
||||
'initialChapter',
|
||||
'currentChapter',
|
||||
'chapters',
|
||||
'visibleChapters',
|
||||
'setReaderStateChapters',
|
||||
'isCurrentChapterReady',
|
||||
],
|
||||
);
|
||||
|
||||
@@ -13,7 +13,6 @@ import Button from '@mui/material/Button';
|
||||
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, 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';
|
||||
@@ -224,7 +223,7 @@ export const ReaderTransitionPage = withPropsFrom(
|
||||
memo(BaseReaderTransitionPage) as typeof BaseReaderTransitionPage,
|
||||
[
|
||||
({ chapterId }: Pick<ComponentProps<typeof BaseReaderTransitionPage>, 'chapterId'>) => {
|
||||
const { chapters } = useReaderStateChaptersContext();
|
||||
const chapters = useReaderStoreShallow((state) => state.chapters.chapters);
|
||||
|
||||
const currentChapterIndex = useMemo(
|
||||
() => chapters.findIndex((chapter) => chapter.id === chapterId),
|
||||
@@ -248,7 +247,7 @@ export const ReaderTransitionPage = withPropsFrom(
|
||||
ReaderService.useSettingsWithoutDefaultFlag,
|
||||
({ chapterId, type }: Pick<ComponentProps<typeof BaseReaderTransitionPage>, 'chapterId' | 'type'>) => {
|
||||
const handleBack = useBackButton();
|
||||
const { chapters } = useReaderStateChaptersContext();
|
||||
const chapters = useReaderStoreShallow((state) => state.chapters.chapters);
|
||||
|
||||
const currentChapterIndex = useMemo(
|
||||
() => chapters.findIndex((chapter) => chapter.id === chapterId),
|
||||
|
||||
Reference in New Issue
Block a user