Move reader "chapters state" to "reader store"
This commit is contained in:
@@ -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'],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user