Simplify selecting zustand store state
This commit is contained in:
@@ -31,10 +31,7 @@ const BaseReaderAutoScroll = ({
|
||||
themeDirection: Direction;
|
||||
combinedDirection: Direction;
|
||||
}) => {
|
||||
const { scrollRef, direction } = useReaderAutoScrollStore((state) => ({
|
||||
scrollRef: state.scrollRef,
|
||||
direction: state.direction,
|
||||
}));
|
||||
const { scrollRef, direction } = useReaderAutoScrollStore('scrollRef', 'direction');
|
||||
const { readingMode, autoScroll } = useReaderSettingsStore((state) => ({
|
||||
readingMode: state.readingMode.value,
|
||||
autoScroll: state.autoScroll,
|
||||
|
||||
@@ -11,9 +11,7 @@ import type { IReaderSettings } from '@/features/reader/Reader.types.ts';
|
||||
import { getReaderAutoScrollStore, useReaderAutoScrollStore } from '@/features/reader/stores/ReaderStore.ts';
|
||||
|
||||
export const useReaderAutoScroll = (isOverlayVisible: boolean, isStaticNav: IReaderSettings['isStaticNav']): void => {
|
||||
const { isPaused } = useReaderAutoScrollStore((state) => ({
|
||||
isPaused: state.isPaused,
|
||||
}));
|
||||
const isPaused = useReaderAutoScrollStore('isPaused');
|
||||
|
||||
useEffect(() => {
|
||||
const { pause, resume } = getReaderAutoScrollStore();
|
||||
|
||||
@@ -28,7 +28,7 @@ export const ReaderNavBarDesktopAutoScroll = ({
|
||||
setAutoScroll: (newAutoScroll: IReaderSettings['autoScroll'], commit: boolean) => void;
|
||||
}) => {
|
||||
const { t } = useLingui();
|
||||
const isActive = useReaderAutoScrollStore((state) => state.isActive);
|
||||
const isActive = useReaderAutoScrollStore('isActive');
|
||||
|
||||
const updateTimeout = useRef<NodeJS.Timeout>(undefined);
|
||||
|
||||
|
||||
@@ -66,9 +66,7 @@ export const ReaderHotkeys = ({
|
||||
}) => {
|
||||
const readerThemeDirection = ReaderService.useGetThemeDirection();
|
||||
const { enableScope, disableScope } = useHotkeysContext();
|
||||
const { hotkeys } = useReaderSettingsStore((state) => ({
|
||||
hotkeys: state.hotkeys,
|
||||
}));
|
||||
const hotkeys = useReaderSettingsStore('hotkeys');
|
||||
const exitReader = ReaderService.useExit();
|
||||
|
||||
useHotkeys(hotkeys[ReaderHotkey.PREVIOUS_PAGE], () => ReaderControls.openPage('previous'));
|
||||
|
||||
@@ -23,7 +23,7 @@ const BaseReaderOverlay = ({
|
||||
isDesktop,
|
||||
isMobile,
|
||||
}: Pick<ReturnType<typeof ReaderService.useOverlayMode>, 'isDesktop' | 'isMobile'>) => {
|
||||
const isVisible = useReaderOverlayStore((state) => state.isVisible);
|
||||
const isVisible = useReaderOverlayStore('isVisible');
|
||||
|
||||
const [areSettingsOpen, setAreSettingsOpen] = useState(false);
|
||||
|
||||
|
||||
@@ -30,17 +30,13 @@ const BaseReaderPageNumber = ({
|
||||
}: Pick<ReturnType<typeof ReaderService.useOverlayMode>, 'isDesktop'> &
|
||||
Pick<NavbarContextType, 'readerNavBarWidth'>) => {
|
||||
const scrollbar = useReaderScrollbarStore((state) => state);
|
||||
const { currentPageIndex, pages, totalPages } = useReaderPagesStore((state) => ({
|
||||
currentPageIndex: state.currentPageIndex,
|
||||
pages: state.pages,
|
||||
totalPages: state.totalPages,
|
||||
}));
|
||||
const { currentPageIndex, pages, totalPages } = useReaderPagesStore('currentPageIndex', 'pages', 'totalPages');
|
||||
const { readingDirection, shouldShowPageNumber, progressBarType } = useReaderSettingsStore((state) => ({
|
||||
readingDirection: state.readingDirection.value,
|
||||
shouldShowPageNumber: state.shouldShowPageNumber,
|
||||
progressBarType: state.progressBarType,
|
||||
}));
|
||||
const isMaximized = useReaderProgressBarStore((state) => state.isMaximized);
|
||||
const isMaximized = useReaderProgressBarStore('isMaximized');
|
||||
|
||||
const pageName = useMemo(() => {
|
||||
const currentPageName = getPage(currentPageIndex, pages).name;
|
||||
|
||||
@@ -18,9 +18,7 @@ export const useReaderHideOverlayOnUserScroll = (
|
||||
isOverlayVisible: boolean,
|
||||
scrollElementRef: MutableRefObject<HTMLDivElement | null>,
|
||||
) => {
|
||||
const { showPreview } = useReaderTapZoneStore((state) => ({
|
||||
showPreview: state.showPreview,
|
||||
}));
|
||||
const showPreview = useReaderTapZoneStore('showPreview');
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
|
||||
@@ -42,9 +42,9 @@ const DEFAULT_MANGA = { ...FALLBACK_MANGA, title: '' };
|
||||
const BaseReaderOverlayHeaderMobile = ({ isVisible, ref }: MobileHeaderProps & { ref?: Ref<HTMLDivElement> }) => {
|
||||
const { t } = useLingui();
|
||||
const popupState = usePopupState({ popupId: 'reader-overlay-more-menu', variant: 'popover' });
|
||||
const currentChapter = useReaderChaptersStore((state) => state.currentChapter);
|
||||
const currentChapter = useReaderChaptersStore('currentChapter');
|
||||
|
||||
const manga = useReaderStore((state) => state.manga);
|
||||
const manga = useReaderStore('manga');
|
||||
const scrollbar = useReaderScrollbarStore((state) => state);
|
||||
|
||||
const { id: mangaId, title } = manga ?? DEFAULT_MANGA;
|
||||
|
||||
@@ -23,7 +23,7 @@ const ACTION_FALLBACK_MANGA = {
|
||||
};
|
||||
|
||||
export const ReaderLibraryButton = memo(() => {
|
||||
const manga = useReaderStore((state) => state.manga);
|
||||
const manga = useReaderStore('manga');
|
||||
|
||||
const { inLibrary } = manga ?? ACTION_FALLBACK_MANGA;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ const BaseReaderNavBarDesktop = ({
|
||||
setReaderNavBarWidth,
|
||||
}: ReaderNavBarDesktopProps & Pick<NavbarContextType, 'setReaderNavBarWidth'>) => {
|
||||
const { t } = useLingui();
|
||||
const manga = useReaderStore((state) => state.manga);
|
||||
const manga = useReaderStore('manga');
|
||||
const {
|
||||
chapters,
|
||||
currentChapterId,
|
||||
@@ -77,7 +77,7 @@ const BaseReaderNavBarDesktop = ({
|
||||
previousChapter: state.previousChapter,
|
||||
nextChapter: state.nextChapter,
|
||||
}));
|
||||
const isStaticNav = useReaderSettingsStore((state) => state.isStaticNav);
|
||||
const isStaticNav = useReaderSettingsStore('isStaticNav');
|
||||
|
||||
const [navBarElement, setNavBarElement] = useState<HTMLDivElement | null>();
|
||||
useResizeObserver(
|
||||
|
||||
@@ -72,7 +72,7 @@ export const ReaderNavBarDesktopActions = memo(() => {
|
||||
}));
|
||||
|
||||
const { t } = useLingui();
|
||||
const pageLoadStates = useReaderPagesStore((state) => state.pageLoadStates);
|
||||
const pageLoadStates = useReaderPagesStore('pageLoadStates');
|
||||
|
||||
const pageRetryKeyPrefix = useRef<number>(0);
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ import { ReaderControls } from '@/features/reader/services/ReaderControls.ts';
|
||||
const BaseReaderNavBarDesktopPageNavigation = () => {
|
||||
const { t } = useLingui();
|
||||
const getOptionForDirection = useGetOptionForDirection();
|
||||
const { currentPageIndex, pages } = useReaderPagesStore((state) => ({
|
||||
currentPageIndex: state.currentPageIndex,
|
||||
pages: state.pages,
|
||||
}));
|
||||
const { currentPageIndex, pages } = useReaderPagesStore('currentPageIndex', 'pages');
|
||||
const readingDirection = useReaderSettingsStore((state) => state.readingDirection.value);
|
||||
|
||||
const currentPage = useMemo(() => getPage(currentPageIndex, pages), [currentPageIndex, pages]);
|
||||
|
||||
@@ -23,14 +23,14 @@ import { useReaderSettingsStore } from '@/features/reader/stores/ReaderStore.ts'
|
||||
const BaseReaderNavBarDesktopQuickSettings = ({ openSettings }: Pick<ReaderNavBarDesktopProps, 'openSettings'>) => {
|
||||
const { t } = useLingui();
|
||||
const { readingMode, shouldOffsetDoubleSpreads, pageScaleMode, shouldStretchPage, readingDirection, autoScroll } =
|
||||
useReaderSettingsStore((state) => ({
|
||||
readingMode: state.readingMode,
|
||||
shouldOffsetDoubleSpreads: state.shouldOffsetDoubleSpreads,
|
||||
pageScaleMode: state.pageScaleMode,
|
||||
shouldStretchPage: state.shouldStretchPage,
|
||||
readingDirection: state.readingDirection,
|
||||
autoScroll: state.autoScroll,
|
||||
}));
|
||||
useReaderSettingsStore(
|
||||
'readingMode',
|
||||
'shouldOffsetDoubleSpreads',
|
||||
'pageScaleMode',
|
||||
'shouldStretchPage',
|
||||
'readingDirection',
|
||||
'autoScroll',
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack sx={{ gap: 1 }}>
|
||||
|
||||
@@ -23,12 +23,12 @@ import {
|
||||
|
||||
const BaseReaderBottomBarMobileQuickSettings = () => {
|
||||
const { t } = useLingui();
|
||||
const isActive = useReaderAutoScrollStore((state) => state.isActive);
|
||||
const { readingMode, readingDirection, autoScroll } = useReaderSettingsStore((state) => ({
|
||||
readingMode: state.readingMode,
|
||||
readingDirection: state.readingDirection,
|
||||
autoScroll: state.autoScroll,
|
||||
}));
|
||||
const isActive = useReaderAutoScrollStore('isActive');
|
||||
const { readingMode, readingDirection, autoScroll } = useReaderSettingsStore(
|
||||
'readingMode',
|
||||
'readingDirection',
|
||||
'autoScroll',
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack sx={{ gap: 2 }}>
|
||||
|
||||
@@ -68,14 +68,14 @@ const BaseReaderProgressBar = ({
|
||||
direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
|
||||
fullSegmentClicks: boolean;
|
||||
}) => {
|
||||
const { pages, pageLoadStates, totalPages, currentPageIndex } = useReaderPagesStore((state) => ({
|
||||
pages: state.pages,
|
||||
pageLoadStates: state.pageLoadStates,
|
||||
totalPages: state.totalPages,
|
||||
currentPageIndex: state.currentPageIndex,
|
||||
}));
|
||||
const { pages, pageLoadStates, totalPages, currentPageIndex } = useReaderPagesStore(
|
||||
'pages',
|
||||
'pageLoadStates',
|
||||
'totalPages',
|
||||
'currentPageIndex',
|
||||
);
|
||||
const readingMode = useReaderSettingsStore((state) => state.readingMode.value);
|
||||
const isDragging = useReaderProgressBarStore((state) => state.isDragging);
|
||||
const isDragging = useReaderProgressBarStore('isDragging');
|
||||
|
||||
const progressBarRef = useRef<HTMLDivElement | null>(null);
|
||||
const draggingDetectionTimeout = useRef<NodeJS.Timeout>(undefined);
|
||||
|
||||
@@ -37,18 +37,15 @@ const BaseStandardReaderProgressBar = ({
|
||||
const theme = useTheme();
|
||||
|
||||
const scrollbar = useReaderScrollbarStore((state) => state);
|
||||
const totalPages = useReaderPagesStore((state) => state.totalPages);
|
||||
const totalPages = useReaderPagesStore('totalPages');
|
||||
const { progressBarType, progressBarSize, progressBarPosition, progressBarPositionAutoVertical } =
|
||||
useReaderSettingsStore((state) => ({
|
||||
progressBarType: state.progressBarType,
|
||||
progressBarSize: state.progressBarSize,
|
||||
progressBarPosition: state.progressBarPosition,
|
||||
progressBarPositionAutoVertical: state.progressBarPositionAutoVertical,
|
||||
}));
|
||||
const { isMaximized, isDragging } = useReaderProgressBarStore((state) => ({
|
||||
isMaximized: state.isMaximized,
|
||||
isDragging: state.isDragging,
|
||||
}));
|
||||
useReaderSettingsStore(
|
||||
'progressBarType',
|
||||
'progressBarSize',
|
||||
'progressBarPosition',
|
||||
'progressBarPositionAutoVertical',
|
||||
);
|
||||
const { isMaximized, isDragging } = useReaderProgressBarStore('isMaximized', 'isDragging');
|
||||
|
||||
const [, setRefreshProgressBarPosition] = useState({});
|
||||
useResizeObserver(
|
||||
|
||||
@@ -59,20 +59,14 @@ const BaseMobileReaderProgressBar = ({
|
||||
bottomOffset?: number;
|
||||
}) => {
|
||||
const scrollbar = useReaderScrollbarStore((state) => state);
|
||||
const isVisible = useReaderOverlayStore((state) => state.isVisible);
|
||||
const { currentPageIndex, pages } = useReaderPagesStore((state) => ({
|
||||
currentPageIndex: state.currentPageIndex,
|
||||
pages: state.pages,
|
||||
}));
|
||||
const { previousChapter, nextChapter } = useReaderChaptersStore((state) => ({
|
||||
previousChapter: state.previousChapter,
|
||||
nextChapter: state.nextChapter,
|
||||
}));
|
||||
const { progressBarPosition, progressBarPositionAutoVertical } = useReaderSettingsStore((state) => ({
|
||||
progressBarPosition: state.progressBarPosition,
|
||||
progressBarPositionAutoVertical: state.progressBarPositionAutoVertical,
|
||||
}));
|
||||
const isDragging = useReaderProgressBarStore((state) => state.isDragging);
|
||||
const isVisible = useReaderOverlayStore('isVisible');
|
||||
const { currentPageIndex, pages } = useReaderPagesStore('currentPageIndex', 'pages');
|
||||
const { previousChapter, nextChapter } = useReaderChaptersStore('previousChapter', 'nextChapter');
|
||||
const { progressBarPosition, progressBarPositionAutoVertical } = useReaderSettingsStore(
|
||||
'progressBarPosition',
|
||||
'progressBarPositionAutoVertical',
|
||||
);
|
||||
const isDragging = useReaderProgressBarStore('isDragging');
|
||||
|
||||
const [, setRefreshProgressBarPosition] = useState({});
|
||||
useResizeObserver(
|
||||
|
||||
@@ -49,14 +49,12 @@ const BaseReader = ({
|
||||
readerNavBarWidth,
|
||||
}: Pick<NavbarContextType, 'setOverride' | 'readerNavBarWidth'>) => {
|
||||
const { t } = useLingui();
|
||||
const manga = useReaderStore((state) => state.manga);
|
||||
const manga = useReaderStore('manga');
|
||||
const { mangaChapters, initialChapter, chapterForDuplicatesHandling, currentChapter } = useReaderChaptersStore(
|
||||
(state) => ({
|
||||
mangaChapters: state.mangaChapters,
|
||||
initialChapter: state.initialChapter,
|
||||
chapterForDuplicatesHandling: state.chapterForDuplicatesHandling,
|
||||
currentChapter: state.currentChapter,
|
||||
}),
|
||||
'mangaChapters',
|
||||
'initialChapter',
|
||||
'chapterForDuplicatesHandling',
|
||||
'currentChapter',
|
||||
);
|
||||
const {
|
||||
shouldSkipDupChapters,
|
||||
@@ -67,16 +65,16 @@ const BaseReader = ({
|
||||
tapZoneInvertMode,
|
||||
shouldShowReadingModePreview,
|
||||
shouldShowTapZoneLayoutPreview,
|
||||
} = useReaderSettingsStore((state) => ({
|
||||
shouldSkipDupChapters: state.shouldSkipDupChapters,
|
||||
shouldSkipFilteredChapters: state.shouldSkipFilteredChapters,
|
||||
backgroundColor: state.backgroundColor,
|
||||
readingMode: state.readingMode,
|
||||
tapZoneLayout: state.tapZoneLayout,
|
||||
tapZoneInvertMode: state.tapZoneInvertMode,
|
||||
shouldShowReadingModePreview: state.shouldShowReadingModePreview,
|
||||
shouldShowTapZoneLayoutPreview: state.shouldShowTapZoneLayoutPreview,
|
||||
}));
|
||||
} = useReaderSettingsStore(
|
||||
'shouldSkipDupChapters',
|
||||
'shouldSkipFilteredChapters',
|
||||
'backgroundColor',
|
||||
'readingMode',
|
||||
'tapZoneLayout',
|
||||
'tapZoneInvertMode',
|
||||
'shouldShowReadingModePreview',
|
||||
'shouldShowTapZoneLayoutPreview',
|
||||
);
|
||||
|
||||
const scrollElementRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ export class ReaderService {
|
||||
|
||||
static useOverlayMode(): { mode: ReaderOverlayMode; isDesktop: boolean; isMobile: boolean } {
|
||||
const isTouchDevice = MediaQuery.useIsTouchDevice();
|
||||
const overlayMode = useReaderSettingsStore((state) => state.overlayMode);
|
||||
const overlayMode = useReaderSettingsStore('overlayMode');
|
||||
|
||||
const isAutoModeSelected = overlayMode === ReaderOverlayMode.AUTO;
|
||||
const isDesktopModeSelected = overlayMode === ReaderOverlayMode.DESKTOP;
|
||||
@@ -442,7 +442,7 @@ export class ReaderService {
|
||||
}
|
||||
|
||||
static useExit(): () => void {
|
||||
const exitMode = useReaderSettingsStore((state) => state.exitMode);
|
||||
const exitMode = useReaderSettingsStore('exitMode');
|
||||
const handleBack = useBackButton();
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import type { TMangaReader } from '@/features/manga/Manga.types.ts';
|
||||
import type { ReaderOverlayStoreSlice } from '@/features/reader/overlay/ReaderOverlayStore.ts';
|
||||
import { createReaderOverlayStoreSlice } from '@/features/reader/overlay/ReaderOverlayStore.ts';
|
||||
@@ -156,37 +155,29 @@ const readerStore = create<ReaderStore>()(
|
||||
},
|
||||
),
|
||||
);
|
||||
export const useReaderStore = <T>(selector: (state: ReaderStore) => T): T => readerStore(useShallow(selector));
|
||||
export const useReaderStore = ZustandUtil.createStoreHook(readerStore);
|
||||
export const getReaderStore = () => readerStore.getState();
|
||||
|
||||
export const useReaderScrollbarStore = <T>(selector: (state: ReaderStore['scrollbar']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.scrollbar)));
|
||||
export const useReaderScrollbarStore = ZustandUtil.createStoreHook(readerStore, 'scrollbar');
|
||||
export const getReaderScrollbarStore = () => readerStore.getState().scrollbar;
|
||||
|
||||
export const useReaderSettingsStore = <T>(selector: (state: ReaderStore['settings']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.settings)));
|
||||
export const useReaderSettingsStore = ZustandUtil.createStoreHook(readerStore, 'settings');
|
||||
export const getReaderSettingsStore = () => readerStore.getState().settings;
|
||||
|
||||
export const useReaderOverlayStore = <T>(selector: (state: ReaderOverlayStoreSlice['overlay']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.overlay)));
|
||||
export const useReaderOverlayStore = ZustandUtil.createStoreHook(readerStore, 'overlay');
|
||||
export const getReaderOverlayStore = () => readerStore.getState().overlay;
|
||||
|
||||
export const useReaderAutoScrollStore = <T>(selector: (state: ReaderAutoScrollStoreSlice['autoScroll']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.autoScroll)));
|
||||
export const useReaderAutoScrollStore = ZustandUtil.createStoreHook(readerStore, 'autoScroll');
|
||||
export const getReaderAutoScrollStore = () => readerStore.getState().autoScroll;
|
||||
|
||||
export const useReaderPagesStore = <T>(selector: (state: ReaderPagesStoreSlice['pages']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.pages)));
|
||||
export const useReaderPagesStore = ZustandUtil.createStoreHook(readerStore, 'pages');
|
||||
export const getReaderPagesStore = () => readerStore.getState().pages;
|
||||
|
||||
export const useReaderChaptersStore = <T>(selector: (state: ReaderChaptersStoreSlice['chapters']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.chapters)));
|
||||
export const useReaderChaptersStore = ZustandUtil.createStoreHook(readerStore, 'chapters');
|
||||
export const getReaderChaptersStore = () => readerStore.getState().chapters;
|
||||
|
||||
export const useReaderProgressBarStore = <T>(selector: (state: ReaderProgressBarStoreSlice['progressBar']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.progressBar)));
|
||||
export const useReaderProgressBarStore = ZustandUtil.createStoreHook(readerStore, 'progressBar');
|
||||
export const getReaderProgressBarStore = () => readerStore.getState().progressBar;
|
||||
|
||||
export const useReaderTapZoneStore = <T>(selector: (state: ReaderTapZoneStoreSlice['tapZone']) => T): T =>
|
||||
readerStore(useShallow((state) => selector(state.tapZone)));
|
||||
export const useReaderTapZoneStore = ZustandUtil.createStoreHook(readerStore, 'tapZone');
|
||||
export const getReaderTapZoneStore = () => readerStore.getState().tapZone;
|
||||
|
||||
@@ -26,7 +26,7 @@ const BaseTapZoneLayout = ({ readerNavBarWidth }: Pick<NavbarContextType, 'reade
|
||||
tapZoneInvertMode: state.tapZoneInvertMode.value,
|
||||
readingDirection: state.readingDirection.value,
|
||||
}));
|
||||
const showPreview = useReaderTapZoneStore((state) => state.showPreview);
|
||||
const showPreview = useReaderTapZoneStore('showPreview');
|
||||
|
||||
const [width, setWidth] = useState(0);
|
||||
const [height, setHeight] = useState(0);
|
||||
|
||||
@@ -68,24 +68,22 @@ const BaseReaderViewer = ({
|
||||
ref?: ForwardedRef<HTMLDivElement | null>;
|
||||
}) => {
|
||||
const { direction: themeDirection } = useTheme();
|
||||
const isOverlayVisible = useReaderOverlayStore((state) => state.isVisible);
|
||||
const isOverlayVisible = useReaderOverlayStore('isVisible');
|
||||
const { currentPageIndex, pageToScrollToIndex, pages, totalPages, transitionPageMode, retryFailedPagesKeyPrefix } =
|
||||
useReaderPagesStore((state) => ({
|
||||
currentPageIndex: state.currentPageIndex,
|
||||
pageToScrollToIndex: state.pageToScrollToIndex,
|
||||
pages: state.pages,
|
||||
totalPages: state.totalPages,
|
||||
transitionPageMode: state.transitionPageMode,
|
||||
retryFailedPagesKeyPrefix: state.retryFailedPagesKeyPrefix,
|
||||
}));
|
||||
useReaderPagesStore(
|
||||
'currentPageIndex',
|
||||
'pageToScrollToIndex',
|
||||
'pages',
|
||||
'totalPages',
|
||||
'transitionPageMode',
|
||||
'retryFailedPagesKeyPrefix',
|
||||
);
|
||||
const { initialChapter, currentChapter, chapters, visibleChapters, isCurrentChapterReady } = useReaderChaptersStore(
|
||||
(state) => ({
|
||||
initialChapter: state.initialChapter,
|
||||
currentChapter: state.currentChapter,
|
||||
chapters: state.chapters,
|
||||
visibleChapters: state.visibleChapters,
|
||||
isCurrentChapterReady: state.isCurrentChapterReady,
|
||||
}),
|
||||
'initialChapter',
|
||||
'currentChapter',
|
||||
'chapters',
|
||||
'visibleChapters',
|
||||
'isCurrentChapterReady',
|
||||
);
|
||||
const {
|
||||
readingMode,
|
||||
|
||||
@@ -99,9 +99,9 @@ const BaseReaderTransitionPage = ({
|
||||
handleBack: () => void;
|
||||
}) => {
|
||||
const { t } = useLingui();
|
||||
const manga = useReaderStore((state) => state.manga);
|
||||
const manga = useReaderStore('manga');
|
||||
const scrollbar = useReaderScrollbarStore((state) => state);
|
||||
const transitionPageMode = useReaderPagesStore((state) => state.transitionPageMode);
|
||||
const transitionPageMode = useReaderPagesStore('transitionPageMode');
|
||||
const { readingMode, backgroundColor, shouldShowTransitionPage } = useReaderSettingsStore((state) => ({
|
||||
readingMode: state.readingMode.value,
|
||||
backgroundColor: state.backgroundColor,
|
||||
@@ -226,7 +226,7 @@ export const ReaderTransitionPage = withPropsFrom(
|
||||
memo(BaseReaderTransitionPage) as typeof BaseReaderTransitionPage,
|
||||
[
|
||||
({ chapterId }: Pick<ComponentProps<typeof BaseReaderTransitionPage>, 'chapterId'>) => {
|
||||
const chapters = useReaderChaptersStore((state) => state.chapters);
|
||||
const chapters = useReaderChaptersStore('chapters');
|
||||
|
||||
const currentChapterIndex = useMemo(
|
||||
() => chapters.findIndex((chapter) => chapter.id === chapterId),
|
||||
@@ -249,7 +249,7 @@ export const ReaderTransitionPage = withPropsFrom(
|
||||
useNavBarContext,
|
||||
({ chapterId, type }: Pick<ComponentProps<typeof BaseReaderTransitionPage>, 'chapterId' | 'type'>) => {
|
||||
const handleBack = useBackButton();
|
||||
const chapters = useReaderChaptersStore((state) => state.chapters);
|
||||
const chapters = useReaderChaptersStore('chapters');
|
||||
|
||||
const currentChapterIndex = useMemo(
|
||||
() => chapters.findIndex((chapter) => chapter.id === chapterId),
|
||||
|
||||
@@ -6,7 +6,64 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
type UseBoundStoreAny<S> = <T>(selector: (state: S) => T) => T;
|
||||
|
||||
type StoreHook<State> = {
|
||||
<T>(selector: (state: State) => T): T;
|
||||
<Key extends keyof State>(key: Key): State[Key];
|
||||
<Key extends keyof State>(...keys: Key[]): Pick<State, Key>;
|
||||
};
|
||||
|
||||
export class ZustandUtil {
|
||||
static createKeySelector<State, Key extends keyof State>(keys: Key[]): (state: State) => Pick<State, Key> {
|
||||
return (state) => {
|
||||
const result = {} as Pick<State, Key>;
|
||||
|
||||
for (const key of keys) {
|
||||
result[key] = state[key];
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
static createStoreHook<FullState extends object, SliceKey extends keyof FullState>(
|
||||
store: UseBoundStoreAny<FullState>,
|
||||
sliceKey: SliceKey,
|
||||
): StoreHook<FullState[SliceKey]>;
|
||||
static createStoreHook<State>(store: UseBoundStoreAny<State>): StoreHook<State>;
|
||||
static createStoreHook<State>(
|
||||
store: UseBoundStoreAny<State>,
|
||||
sliceKey?: keyof State,
|
||||
): StoreHook<State[keyof State] | State> {
|
||||
return ((...args: unknown[]) => {
|
||||
let selector: (state: State) => unknown;
|
||||
|
||||
if (typeof args[0] === 'function') {
|
||||
const fn = args[0] as (state: unknown) => unknown;
|
||||
selector = sliceKey !== undefined ? (state: State) => fn(state[sliceKey]) : fn;
|
||||
} else if (args.length === 1) {
|
||||
const key = args[0];
|
||||
selector =
|
||||
sliceKey !== undefined
|
||||
? (state: State) => (state[sliceKey] as Record<PropertyKey, unknown>)[key as PropertyKey]
|
||||
: (state: State) => (state as Record<PropertyKey, unknown>)[key as PropertyKey];
|
||||
} else {
|
||||
const pickSelector = ZustandUtil.createKeySelector<Record<PropertyKey, unknown>, PropertyKey>(
|
||||
args as PropertyKey[],
|
||||
);
|
||||
selector =
|
||||
sliceKey !== undefined
|
||||
? (state: State) => pickSelector(state[sliceKey] as Record<PropertyKey, unknown>)
|
||||
: (pickSelector as (state: State) => unknown);
|
||||
}
|
||||
|
||||
return store(useShallow(selector));
|
||||
}) as StoreHook<State[keyof State] | State>;
|
||||
}
|
||||
|
||||
static createActionName(...names: string[]) {
|
||||
const storeAndSlices = names.slice(0, -1);
|
||||
const action = names.slice(-1)[0];
|
||||
|
||||
Reference in New Issue
Block a user