Move reader "manga state" to "reader store"

This commit is contained in:
schroda
2025-08-31 12:57:28 +02:00
parent 4e30081ed8
commit 433dc17c35
22 changed files with 124 additions and 209 deletions

View File

@@ -15,6 +15,8 @@ module.exports = {
{ {
files: ['*'], files: ['*'],
rules: { rules: {
'no-param-reassign': ['error', { props: true, ignorePropertyModificationsForRegex: ["^draft"] }],
'unused-imports/no-unused-imports': 'error', 'unused-imports/no-unused-imports': 'error',
'import/prefer-default-export': 'off', 'import/prefer-default-export': 'off',

View File

@@ -99,6 +99,7 @@ export const MangaCard = memo((props: MangaCardProps) => {
const longPressBind = useLongPress( const longPressBind = useLongPress(
useCallback( useCallback(
(e: any, { context }: any) => { (e: any, { context }: any) => {
// eslint-disable-next-line no-param-reassign
e.shiftKey = true; e.shiftKey = true;
handleClick(e, context as () => {}); handleClick(e, context as () => {});
}, },

View File

@@ -10,7 +10,6 @@ import { MutableRefObject } from 'react';
import { TapZoneInvertMode, TapZoneLayouts } from '@/features/reader/tap-zones/TapZoneLayout.types.ts'; import { TapZoneInvertMode, TapZoneLayouts } from '@/features/reader/tap-zones/TapZoneLayout.types.ts';
import { TChapterReader } from '@/features/chapter/Chapter.types.ts'; import { TChapterReader } from '@/features/chapter/Chapter.types.ts';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { TMangaReader } from '@/features/manga/Manga.types.ts';
import { useAutomaticScrolling } from '@/base/hooks/useAutomaticScrolling.ts'; import { useAutomaticScrolling } from '@/base/hooks/useAutomaticScrolling.ts';
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts'; import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
import { ScrollOffset } from '@/base/Base.types.ts'; import { ScrollOffset } from '@/base/Base.types.ts';
@@ -243,7 +242,7 @@ export interface ReaderStateChapters {
interface ReaderSettingsTypeBaseProps { interface ReaderSettingsTypeBaseProps {
settings: IReaderSettingsWithDefaultFlag; settings: IReaderSettingsWithDefaultFlag;
updateSetting: ( updateSetting: (
...args: OmitFirst<Parameters<typeof ReaderService.updateSetting>> ...args: Parameters<typeof ReaderService.updateSetting>
) => ReturnType<typeof ReaderService.updateSetting>; ) => ReturnType<typeof ReaderService.updateSetting>;
} }
@@ -378,11 +377,6 @@ export type TReaderScrollbarContext = {
setScrollbarYSize: (size: number) => void; setScrollbarYSize: (size: number) => void;
}; };
export type TReaderStateMangaContext = {
manga: TMangaReader | undefined;
setManga: (manga: TMangaReader | undefined) => void;
};
export type TReaderStateSettingsContext = { export type TReaderStateSettingsContext = {
settings: IReaderSettingsWithDefaultFlag; settings: IReaderSettingsWithDefaultFlag;
setSettings: (settings: IReaderSettingsWithDefaultFlag) => void; setSettings: (settings: IReaderSettingsWithDefaultFlag) => void;

View File

@@ -0,0 +1,35 @@
/*
* 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 { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { TMangaReader } from '@/features/manga/Manga.types.ts';
interface ReaderStore {
reset: () => void;
manga: TMangaReader | undefined;
setManga: (manga: TMangaReader | undefined) => void;
}
const DEFAULT_STATE = {
manga: undefined,
} satisfies Pick<ReaderStore, 'manga'>;
export const useReaderStore = create<ReaderStore>()(
immer((set) => ({
...DEFAULT_STATE,
reset: () =>
set((draft) => {
draft.manga = DEFAULT_STATE.manga;
}),
setManga: (manga) =>
set((draft) => {
draft.manga = manga;
}),
})),
);

View File

@@ -8,16 +8,13 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { ReaderStateChaptersContextProvider } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; import { ReaderStateChaptersContextProvider } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
import { ReaderStateMangaContextProvider } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { ReaderStatePagesContextProvider } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { ReaderStatePagesContextProvider } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { ReaderStateSettingsContextProvider } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx'; import { ReaderStateSettingsContextProvider } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx';
export const ReaderStateContextProvider = ({ children }: { children: ReactNode }) => ( export const ReaderStateContextProvider = ({ children }: { children: ReactNode }) => (
<ReaderStateMangaContextProvider>
<ReaderStateChaptersContextProvider> <ReaderStateChaptersContextProvider>
<ReaderStateSettingsContextProvider> <ReaderStateSettingsContextProvider>
<ReaderStatePagesContextProvider>{children}</ReaderStatePagesContextProvider> <ReaderStatePagesContextProvider>{children}</ReaderStatePagesContextProvider>
</ReaderStateSettingsContextProvider> </ReaderStateSettingsContextProvider>
</ReaderStateChaptersContextProvider> </ReaderStateChaptersContextProvider>
</ReaderStateMangaContextProvider>
); );

View File

@@ -1,25 +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 { TReaderStateMangaContext } from '@/features/reader/Reader.types.ts';
export const ReaderStateMangaContext = createContext<TReaderStateMangaContext>({
manga: undefined,
setManga: () => undefined,
});
export const useReaderStateMangaContext = () => useContext(ReaderStateMangaContext);
export const ReaderStateMangaContextProvider = ({ children }: { children: ReactNode }) => {
const [manga, setManga] = useState<TReaderStateMangaContext['manga']>();
const value = useMemo(() => ({ manga, setManga }), [manga]);
return <ReaderStateMangaContext.Provider value={value}>{children}</ReaderStateMangaContext.Provider>;
};

View File

@@ -13,15 +13,14 @@ import {
ReaderStatePages, ReaderStatePages,
ReaderTransitionPageMode, ReaderTransitionPageMode,
TReaderAutoScrollContext, TReaderAutoScrollContext,
TReaderStateMangaContext,
TReaderStateSettingsContext, TReaderStateSettingsContext,
} from '@/features/reader/Reader.types.ts'; } from '@/features/reader/Reader.types.ts';
import { DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG } from '@/features/reader/settings/ReaderSettingsMetadata.ts'; import { DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG } from '@/features/reader/settings/ReaderSettingsMetadata.ts';
import { TReaderOverlayContext } from '@/features/reader/overlay/ReaderOverlay.types.ts'; import { TReaderOverlayContext } from '@/features/reader/overlay/ReaderOverlay.types.ts';
import { READER_STATE_CHAPTERS_DEFAULTS } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; import { READER_STATE_CHAPTERS_DEFAULTS } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
import { getReaderStore } from '@/features/reader/ReaderStore.ts';
export const useReaderResetStates = ( export const useReaderResetStates = (
setManga: TReaderStateMangaContext['setManga'],
setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'], setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'],
setCurrentPageIndex: ReaderStatePages['setCurrentPageIndex'], setCurrentPageIndex: ReaderStatePages['setCurrentPageIndex'],
setPageToScrollToIndex: ReaderStatePages['setPageToScrollToIndex'], setPageToScrollToIndex: ReaderStatePages['setPageToScrollToIndex'],
@@ -36,7 +35,7 @@ export const useReaderResetStates = (
) => { ) => {
useEffect( useEffect(
() => () => { () => () => {
setManga(undefined); getReaderStore().reset();
setReaderStateChapters(READER_STATE_CHAPTERS_DEFAULTS); setReaderStateChapters(READER_STATE_CHAPTERS_DEFAULTS);
setCurrentPageIndex(0); setCurrentPageIndex(0);

View File

@@ -21,12 +21,10 @@ import {
READING_DIRECTION_VALUES, READING_DIRECTION_VALUES,
READING_MODE_VALUES, READING_MODE_VALUES,
} from '@/features/reader/settings/ReaderSettings.constants.tsx'; } from '@/features/reader/settings/ReaderSettings.constants.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { HotkeyScope } from '@/features/hotkeys/Hotkeys.types.ts'; import { HotkeyScope } from '@/features/hotkeys/Hotkeys.types.ts';
import { ReaderControls } from '@/features/reader/services/ReaderControls.ts'; import { ReaderControls } from '@/features/reader/services/ReaderControls.ts';
import { ScrollOffset } from '@/base/Base.types.ts'; import { ScrollOffset } from '@/base/Base.types.ts';
import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts'; import { getOptionForDirection } from '@/features/theme/services/ThemeCreator.ts';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { useReaderAutoScrollContext } from '@/features/reader/auto-scroll/ReaderAutoScrollContext.tsx'; import { useReaderAutoScrollContext } from '@/features/reader/auto-scroll/ReaderAutoScrollContext.tsx';
import { useReaderTapZoneContext } from '@/features/reader/tap-zones/ReaderTapZoneContext.tsx'; import { useReaderTapZoneContext } from '@/features/reader/tap-zones/ReaderTapZoneContext.tsx';
@@ -36,8 +34,6 @@ const useHotkeys = (...args: Parameters<typeof useHotKeysHook>): ReturnType<type
}; };
const updateSettingCycleThrough = <Setting extends keyof IReaderSettings>( const updateSettingCycleThrough = <Setting extends keyof IReaderSettings>(
updateSetting: ReturnType<typeof ReaderService.useCreateUpdateSetting>,
deleteSetting: ReturnType<typeof ReaderService.useCreateDeleteSetting>,
setting: Setting, setting: Setting,
value: IReaderSettings[Setting], value: IReaderSettings[Setting],
values: IReaderSettings[Setting][], values: IReaderSettings[Setting][],
@@ -45,7 +41,7 @@ const updateSettingCycleThrough = <Setting extends keyof IReaderSettings>(
isDefaultable: boolean, isDefaultable: boolean,
) => { ) => {
if (isDefault) { if (isDefault) {
updateSetting(setting, values[0]); ReaderService.updateSetting(setting, values[0]);
return; return;
} }
@@ -53,11 +49,11 @@ const updateSettingCycleThrough = <Setting extends keyof IReaderSettings>(
const isDefaultNextValue = nextValue === undefined; const isDefaultNextValue = nextValue === undefined;
if (isDefaultNextValue) { if (isDefaultNextValue) {
deleteSetting(setting); ReaderService.deleteSetting(setting);
return; return;
} }
updateSetting(setting, nextValue); ReaderService.updateSetting(setting, nextValue);
}; };
export const ReaderHotkeys = ({ export const ReaderHotkeys = ({
@@ -68,7 +64,6 @@ export const ReaderHotkeys = ({
const { direction: themeDirection } = useTheme(); const { direction: themeDirection } = useTheme();
const readerThemeDirection = ReaderService.useGetThemeDirection(); const readerThemeDirection = ReaderService.useGetThemeDirection();
const { enableScope, disableScope } = useHotkeysContext(); const { enableScope, disableScope } = useHotkeysContext();
const { manga } = useReaderStateMangaContext();
const { isVisible, setIsVisible: setIsOverlayVisible } = useReaderOverlayContext(); const { isVisible, setIsVisible: setIsOverlayVisible } = useReaderOverlayContext();
const { const {
hotkeys, hotkeys,
@@ -87,9 +82,6 @@ export const ReaderHotkeys = ({
const openChapter = ReaderControls.useOpenChapter(); const openChapter = ReaderControls.useOpenChapter();
const openPage = ReaderControls.useOpenPage(); const openPage = ReaderControls.useOpenPage();
const updateSetting = ReaderService.useCreateUpdateSetting(manga ?? FALLBACK_MANGA);
const deleteSetting = ReaderService.useCreateDeleteSetting(manga ?? FALLBACK_MANGA);
useHotkeys(hotkeys[ReaderHotkey.PREVIOUS_PAGE], () => openPage('previous'), [openPage]); useHotkeys(hotkeys[ReaderHotkey.PREVIOUS_PAGE], () => openPage('previous'), [openPage]);
useHotkeys(hotkeys[ReaderHotkey.NEXT_PAGE], () => openPage('next'), [openPage]); useHotkeys(hotkeys[ReaderHotkey.NEXT_PAGE], () => openPage('next'), [openPage]);
useHotkeys( useHotkeys(
@@ -177,8 +169,6 @@ export const ReaderHotkeys = ({
hotkeys[ReaderHotkey.CYCLE_SCALE_TYPE], hotkeys[ReaderHotkey.CYCLE_SCALE_TYPE],
() => { () => {
updateSettingCycleThrough( updateSettingCycleThrough(
updateSetting,
deleteSetting,
'pageScaleMode', 'pageScaleMode',
pageScaleMode.value, pageScaleMode.value,
READER_PAGE_SCALE_MODE_VALUES, READER_PAGE_SCALE_MODE_VALUES,
@@ -186,24 +176,22 @@ export const ReaderHotkeys = ({
true, true,
); );
}, },
[updateSetting, deleteSetting, pageScaleMode.value, pageScaleMode.isDefault], [pageScaleMode.value, pageScaleMode.isDefault],
); );
useHotkeys( useHotkeys(
hotkeys[ReaderHotkey.STRETCH_IMAGE], hotkeys[ReaderHotkey.STRETCH_IMAGE],
() => updateSetting('shouldStretchPage', !shouldStretchPage.value), () => ReaderService.updateSetting('shouldStretchPage', !shouldStretchPage.value),
[updateSetting, shouldStretchPage.value], [shouldStretchPage.value],
); );
useHotkeys( useHotkeys(
hotkeys[ReaderHotkey.OFFSET_SPREAD_PAGES], hotkeys[ReaderHotkey.OFFSET_SPREAD_PAGES],
() => updateSetting('shouldOffsetDoubleSpreads', !shouldOffsetDoubleSpreads.value), () => ReaderService.updateSetting('shouldOffsetDoubleSpreads', !shouldOffsetDoubleSpreads.value),
[updateSetting, shouldOffsetDoubleSpreads.value], [shouldOffsetDoubleSpreads.value],
); );
useHotkeys( useHotkeys(
hotkeys[ReaderHotkey.CYCLE_READING_MODE], hotkeys[ReaderHotkey.CYCLE_READING_MODE],
() => { () => {
updateSettingCycleThrough( updateSettingCycleThrough(
updateSetting,
deleteSetting,
'readingMode', 'readingMode',
readingMode.value, readingMode.value,
READING_MODE_VALUES, READING_MODE_VALUES,
@@ -211,14 +199,12 @@ export const ReaderHotkeys = ({
true, true,
); );
}, },
[updateSetting, deleteSetting, readingMode.value, readingMode.isDefault], [readingMode.value, readingMode.isDefault],
); );
useHotkeys( useHotkeys(
hotkeys[ReaderHotkey.CYCLE_READING_DIRECTION], hotkeys[ReaderHotkey.CYCLE_READING_DIRECTION],
() => { () => {
updateSettingCycleThrough( updateSettingCycleThrough(
updateSetting,
deleteSetting,
'readingDirection', 'readingDirection',
readingDirection.value, readingDirection.value,
READING_DIRECTION_VALUES, READING_DIRECTION_VALUES,
@@ -226,7 +212,7 @@ export const ReaderHotkeys = ({
true, true,
); );
}, },
[updateSetting, deleteSetting, readingDirection.value, readingDirection.isDefault], [readingDirection.value, readingDirection.isDefault],
); );
useHotkeys(hotkeys[ReaderHotkey.TOGGLE_AUTO_SCROLL], automaticScrolling.toggleActive, { preventDefault: true }, [ useHotkeys(hotkeys[ReaderHotkey.TOGGLE_AUTO_SCROLL], automaticScrolling.toggleActive, { preventDefault: true }, [
automaticScrolling.toggleActive, automaticScrolling.toggleActive,
@@ -234,20 +220,20 @@ export const ReaderHotkeys = ({
useHotkeys( useHotkeys(
hotkeys[ReaderHotkey.AUTO_SCROLL_SPEED_DECREASE], hotkeys[ReaderHotkey.AUTO_SCROLL_SPEED_DECREASE],
() => () =>
updateSetting('autoScroll', { ReaderService.updateSetting('autoScroll', {
...autoScroll, ...autoScroll,
value: Math.min(AUTO_SCROLL_SPEED.max, autoScroll.value + AUTO_SCROLL_SPEED.step), value: Math.min(AUTO_SCROLL_SPEED.max, autoScroll.value + AUTO_SCROLL_SPEED.step),
}), }),
[updateSetting, autoScroll.value], [autoScroll.value],
); );
useHotkeys( useHotkeys(
hotkeys[ReaderHotkey.AUTO_SCROLL_SPEED_INCREASE], hotkeys[ReaderHotkey.AUTO_SCROLL_SPEED_INCREASE],
() => () =>
updateSetting('autoScroll', { ReaderService.updateSetting('autoScroll', {
...autoScroll, ...autoScroll,
value: Math.max(AUTO_SCROLL_SPEED.min, autoScroll.value - AUTO_SCROLL_SPEED.step), value: Math.max(AUTO_SCROLL_SPEED.min, autoScroll.value - AUTO_SCROLL_SPEED.step),
}), }),
[updateSetting, autoScroll.value], [autoScroll.value],
); );
useHotkeys(hotkeys[ReaderHotkey.EXIT_READER], exitReader, [exitReader]); useHotkeys(hotkeys[ReaderHotkey.EXIT_READER], exitReader, [exitReader]);

View File

@@ -24,13 +24,8 @@ import { makeToast } from '@/base/utils/Toast.ts';
import { MobileHeaderProps } from '@/features/reader/overlay/ReaderOverlay.types.ts'; import { MobileHeaderProps } from '@/features/reader/overlay/ReaderOverlay.types.ts';
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx'; import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
import { AppRoutes } from '@/base/AppRoute.constants.ts'; import { AppRoutes } from '@/base/AppRoute.constants.ts';
import { import { ReaderStateChapters, TReaderScrollbarContext } from '@/features/reader/Reader.types.ts';
ReaderStateChapters,
TReaderScrollbarContext,
TReaderStateMangaContext,
} from '@/features/reader/Reader.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
import { useReaderScrollbarContext } from '@/features/reader/contexts/ReaderScrollbarContext.tsx'; import { useReaderScrollbarContext } from '@/features/reader/contexts/ReaderScrollbarContext.tsx';
import { ReaderLibraryButton } from '@/features/reader/overlay/navigation/components/ReaderLibraryButton.tsx'; import { ReaderLibraryButton } from '@/features/reader/overlay/navigation/components/ReaderLibraryButton.tsx';
@@ -39,19 +34,19 @@ import { FALLBACK_CHAPTER } from '@/features/chapter/Chapter.constants.ts';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts'; import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { ReaderExitButton } from '@/features/reader/overlay/navigation/components/ReaderExitButton.tsx'; import { ReaderExitButton } from '@/features/reader/overlay/navigation/components/ReaderExitButton.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const DEFAULT_MANGA = { ...FALLBACK_MANGA, title: '' }; const DEFAULT_MANGA = { ...FALLBACK_MANGA, title: '' };
const BaseReaderOverlayHeaderMobile = forwardRef< const BaseReaderOverlayHeaderMobile = forwardRef<
HTMLDivElement, HTMLDivElement,
MobileHeaderProps & MobileHeaderProps & Pick<ReaderStateChapters, 'currentChapter'> & Pick<TReaderScrollbarContext, 'scrollbarYSize'>
Pick<TReaderStateMangaContext, 'manga'> & >(({ isVisible, currentChapter, scrollbarYSize }, ref) => {
Pick<ReaderStateChapters, 'currentChapter'> &
Pick<TReaderScrollbarContext, 'scrollbarYSize'>
>(({ isVisible, manga, currentChapter, scrollbarYSize }, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
const popupState = usePopupState({ popupId: 'reader-overlay-more-menu', variant: 'popover' }); const popupState = usePopupState({ popupId: 'reader-overlay-more-menu', variant: 'popover' });
const manga = useReaderStoreShallow((state) => state.manga);
const { id: mangaId, title } = manga ?? DEFAULT_MANGA; const { id: mangaId, title } = manga ?? DEFAULT_MANGA;
const { id: chapterId, name, realUrl, isBookmarked } = currentChapter ?? FALLBACK_CHAPTER; const { id: chapterId, name, realUrl, isBookmarked } = currentChapter ?? FALLBACK_CHAPTER;
@@ -136,6 +131,6 @@ const BaseReaderOverlayHeaderMobile = forwardRef<
export const ReaderOverlayHeaderMobile = withPropsFrom( export const ReaderOverlayHeaderMobile = withPropsFrom(
memo(BaseReaderOverlayHeaderMobile), memo(BaseReaderOverlayHeaderMobile),
[useReaderStateMangaContext, useReaderStateChaptersContext, useReaderScrollbarContext], [useReaderStateChaptersContext, useReaderScrollbarContext],
['manga', 'currentChapter', 'scrollbarYSize'], ['currentChapter', 'scrollbarYSize'],
); );

View File

@@ -14,9 +14,7 @@ import { memo } from 'react';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx'; import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
import { useManageMangaLibraryState } from '@/features/manga/hooks/useManageMangaLibraryState.tsx'; import { useManageMangaLibraryState } from '@/features/manga/hooks/useManageMangaLibraryState.tsx';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts'; import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { TReaderStateMangaContext } from '@/features/reader/Reader.types.ts'; import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
const ACTION_FALLBACK_MANGA = { const ACTION_FALLBACK_MANGA = {
...FALLBACK_MANGA, ...FALLBACK_MANGA,
@@ -24,7 +22,9 @@ const ACTION_FALLBACK_MANGA = {
inLibrary: false, inLibrary: false,
}; };
const BaseReaderLibraryButton = ({ manga }: Pick<TReaderStateMangaContext, 'manga'>) => { export const ReaderLibraryButton = memo(() => {
const manga = useReaderStoreShallow((state) => state.manga);
const { inLibrary } = manga ?? ACTION_FALLBACK_MANGA; const { inLibrary } = manga ?? ACTION_FALLBACK_MANGA;
const { t } = useTranslation(); const { t } = useTranslation();
@@ -46,10 +46,4 @@ const BaseReaderLibraryButton = ({ manga }: Pick<TReaderStateMangaContext, 'mang
{CategorySelectComponent} {CategorySelectComponent}
</> </>
); );
}; });
export const ReaderLibraryButton = withPropsFrom(
memo(BaseReaderLibraryButton),
[useReaderStateMangaContext],
['manga'],
);

View File

@@ -24,16 +24,15 @@ import { ReaderNavBarDesktopQuickSettings } from '@/features/reader/overlay/navi
import { ReaderNavBarDesktopActions } from '@/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx'; import { ReaderNavBarDesktopActions } from '@/features/reader/overlay/navigation/desktop/components/ReaderNavBarDesktopActions.tsx';
import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx'; import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx'; import { useReaderStateChaptersContext } from '@/features/reader/contexts/state/ReaderStateChaptersContext.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx'; import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts'; import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
import { IReaderSettings, ReaderStateChapters, TReaderStateMangaContext } from '@/features/reader/Reader.types.ts'; import { IReaderSettings, ReaderStateChapters } from '@/features/reader/Reader.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { ReaderExitButton } from '@/features/reader/overlay/navigation/components/ReaderExitButton.tsx'; import { ReaderExitButton } from '@/features/reader/overlay/navigation/components/ReaderExitButton.tsx';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const useGetPreviousNavBarStaticValue = (isVisible: boolean, isStaticNav: boolean) => { const useGetPreviousNavBarStaticValue = (isVisible: boolean, isStaticNav: boolean) => {
const wasNavBarStaticRef = useRef(isStaticNav); const wasNavBarStaticRef = useRef(isStaticNav);
@@ -57,7 +56,6 @@ const BaseReaderNavBarDesktop = ({
isVisible, isVisible,
openSettings, openSettings,
setReaderNavBarWidth, setReaderNavBarWidth,
manga,
chapters, chapters,
currentChapter, currentChapter,
previousChapter, previousChapter,
@@ -65,12 +63,10 @@ const BaseReaderNavBarDesktop = ({
isStaticNav, isStaticNav,
}: ReaderNavBarDesktopProps & }: ReaderNavBarDesktopProps &
Pick<NavbarContextType, 'setReaderNavBarWidth'> & Pick<NavbarContextType, 'setReaderNavBarWidth'> &
Pick<TReaderStateMangaContext, 'manga'> &
Pick<ReaderStateChapters, 'currentChapter' | 'previousChapter' | 'nextChapter' | 'chapters'> & Pick<ReaderStateChapters, 'currentChapter' | 'previousChapter' | 'nextChapter' | 'chapters'> &
Pick<IReaderSettings, 'isStaticNav'>) => { Pick<IReaderSettings, 'isStaticNav'>) => {
const { t } = useTranslation(); const { t } = useTranslation();
const manga = useReaderStoreShallow((state) => state.manga);
const updateReaderSettings = ReaderService.useCreateUpdateSetting(manga ?? FALLBACK_MANGA);
const [navBarElement, setNavBarElement] = useState<HTMLDivElement | null>(); const [navBarElement, setNavBarElement] = useState<HTMLDivElement | null>();
useResizeObserver( useResizeObserver(
@@ -109,7 +105,7 @@ const BaseReaderNavBarDesktop = ({
<IconButton <IconButton
onClick={() => { onClick={() => {
setReaderNavBarWidth(0); setReaderNavBarWidth(0);
updateReaderSettings('isStaticNav', !isStaticNav); ReaderService.updateSetting('isStaticNav', !isStaticNav);
}} }}
color={isStaticNav ? 'primary' : 'inherit'} color={isStaticNav ? 'primary' : 'inherit'}
> >
@@ -153,10 +149,9 @@ export const ReaderNavBarDesktop = withPropsFrom(
memo(BaseReaderNavBarDesktop), memo(BaseReaderNavBarDesktop),
[ [
useNavBarContext, useNavBarContext,
useReaderStateMangaContext,
useReaderStateChaptersContext, useReaderStateChaptersContext,
userReaderStatePagesContext, userReaderStatePagesContext,
ReaderService.useSettingsWithoutDefaultFlag, ReaderService.useSettingsWithoutDefaultFlag,
], ],
['setReaderNavBarWidth', 'manga', 'chapters', 'currentChapter', 'previousChapter', 'nextChapter', 'isStaticNav'], ['setReaderNavBarWidth', 'chapters', 'currentChapter', 'previousChapter', 'nextChapter', 'isStaticNav'],
); );

View File

@@ -14,16 +14,13 @@ import { ReaderNavBarDesktopPageScale } from '@/features/reader/overlay/navigati
import { ReaderNavBarDesktopReadingMode } from '@/features/reader/overlay/navigation/desktop/quick-settings/components/ReaderNavBarDesktopReadingMode.tsx'; import { ReaderNavBarDesktopReadingMode } from '@/features/reader/overlay/navigation/desktop/quick-settings/components/ReaderNavBarDesktopReadingMode.tsx';
import { ReaderNavBarDesktopOffsetDoubleSpread } from '@/features/reader/overlay/navigation/desktop/quick-settings/components/ReaderNavBarDesktopOffsetDoubleSpread.tsx'; import { ReaderNavBarDesktopOffsetDoubleSpread } from '@/features/reader/overlay/navigation/desktop/quick-settings/components/ReaderNavBarDesktopOffsetDoubleSpread.tsx';
import { ReaderNavBarDesktopReadingDirection } from '@/features/reader/overlay/navigation/desktop/quick-settings/components/ReaderNavBarDesktopReadingDirection.tsx'; import { ReaderNavBarDesktopReadingDirection } from '@/features/reader/overlay/navigation/desktop/quick-settings/components/ReaderNavBarDesktopReadingDirection.tsx';
import { IReaderSettingsWithDefaultFlag, TReaderStateMangaContext } from '@/features/reader/Reader.types.ts'; import { IReaderSettingsWithDefaultFlag } from '@/features/reader/Reader.types.ts';
import { ReaderNavBarDesktopProps } from '@/features/reader/overlay/ReaderOverlay.types.ts'; import { ReaderNavBarDesktopProps } from '@/features/reader/overlay/ReaderOverlay.types.ts';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { ReaderNavBarDesktopAutoScroll } from '@/features/reader/auto-scroll/settings/quick-setting/ReaderNavBarDesktopAutoScroll.tsx'; import { ReaderNavBarDesktopAutoScroll } from '@/features/reader/auto-scroll/settings/quick-setting/ReaderNavBarDesktopAutoScroll.tsx';
const BaseReaderNavBarDesktopQuickSettings = ({ const BaseReaderNavBarDesktopQuickSettings = ({
manga,
readingMode, readingMode,
shouldOffsetDoubleSpreads, shouldOffsetDoubleSpreads,
pageScaleMode, pageScaleMode,
@@ -31,8 +28,7 @@ const BaseReaderNavBarDesktopQuickSettings = ({
readingDirection, readingDirection,
autoScroll, autoScroll,
openSettings, openSettings,
}: Pick<TReaderStateMangaContext, 'manga'> & }: Pick<ReaderNavBarDesktopProps, 'openSettings'> &
Pick<ReaderNavBarDesktopProps, 'openSettings'> &
Pick< Pick<
IReaderSettingsWithDefaultFlag, IReaderSettingsWithDefaultFlag,
| 'readingMode' | 'readingMode'
@@ -44,38 +40,37 @@ const BaseReaderNavBarDesktopQuickSettings = ({
>) => { >) => {
const { t } = useTranslation(); const { t } = useTranslation();
const updateSetting = ReaderService.useCreateUpdateSetting(manga ?? FALLBACK_MANGA);
const deleteSetting = ReaderService.useCreateDeleteSetting(manga ?? FALLBACK_MANGA);
return ( return (
<Stack sx={{ gap: 1 }}> <Stack sx={{ gap: 1 }}>
<ReaderNavBarDesktopReadingMode <ReaderNavBarDesktopReadingMode
readingMode={readingMode} readingMode={readingMode}
setReadingMode={(value) => updateSetting('readingMode', value)} setReadingMode={(value) => ReaderService.updateSetting('readingMode', value)}
isDefaultable isDefaultable
onDefault={() => deleteSetting('readingMode')} onDefault={() => ReaderService.deleteSetting('readingMode')}
/> />
<ReaderNavBarDesktopOffsetDoubleSpread <ReaderNavBarDesktopOffsetDoubleSpread
readingMode={readingMode.value} readingMode={readingMode.value}
shouldOffsetDoubleSpreads={shouldOffsetDoubleSpreads.value} shouldOffsetDoubleSpreads={shouldOffsetDoubleSpreads.value}
setShouldOffsetDoubleSpreads={(value) => updateSetting('shouldOffsetDoubleSpreads', value)} setShouldOffsetDoubleSpreads={(value) =>
ReaderService.updateSetting('shouldOffsetDoubleSpreads', value)
}
/> />
<ReaderNavBarDesktopPageScale <ReaderNavBarDesktopPageScale
pageScaleMode={pageScaleMode} pageScaleMode={pageScaleMode}
shouldStretchPage={shouldStretchPage} shouldStretchPage={shouldStretchPage}
updateSetting={updateSetting} updateSetting={ReaderService.updateSetting}
isDefaultable isDefaultable
onDefault={() => deleteSetting('pageScaleMode')} onDefault={() => ReaderService.deleteSetting('pageScaleMode')}
/> />
<ReaderNavBarDesktopReadingDirection <ReaderNavBarDesktopReadingDirection
readingDirection={readingDirection} readingDirection={readingDirection}
setReadingDirection={(value) => updateSetting('readingDirection', value)} setReadingDirection={(value) => ReaderService.updateSetting('readingDirection', value)}
isDefaultable isDefaultable
onDefault={() => deleteSetting('readingDirection')} onDefault={() => ReaderService.deleteSetting('readingDirection')}
/> />
<ReaderNavBarDesktopAutoScroll <ReaderNavBarDesktopAutoScroll
autoScroll={autoScroll} autoScroll={autoScroll}
setAutoScroll={(...args) => updateSetting('autoScroll', ...args)} setAutoScroll={(...args) => ReaderService.updateSetting('autoScroll', ...args)}
/> />
<Button <Button
onClick={() => openSettings()} onClick={() => openSettings()}
@@ -92,9 +87,8 @@ const BaseReaderNavBarDesktopQuickSettings = ({
export const ReaderNavBarDesktopQuickSettings = withPropsFrom( export const ReaderNavBarDesktopQuickSettings = withPropsFrom(
BaseReaderNavBarDesktopQuickSettings, BaseReaderNavBarDesktopQuickSettings,
[useReaderStateMangaContext, ReaderService.useSettings], [ReaderService.useSettings],
[ [
'manga',
'readingMode', 'readingMode',
'shouldOffsetDoubleSpreads', 'shouldOffsetDoubleSpreads',
'pageScaleMode', 'pageScaleMode',

View File

@@ -12,50 +12,37 @@ import { useTranslation } from 'react-i18next';
import { ReaderSettingReadingMode } from '@/features/reader/settings/layout/components/ReaderSettingReadingMode.tsx'; import { ReaderSettingReadingMode } from '@/features/reader/settings/layout/components/ReaderSettingReadingMode.tsx';
import { ReaderSettingReadingDirection } from '@/features/reader/settings/layout/components/ReaderSettingReadingDirection.tsx'; import { ReaderSettingReadingDirection } from '@/features/reader/settings/layout/components/ReaderSettingReadingDirection.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { DefaultSettingFootnote } from '@/features/reader/settings/components/DefaultSettingFootnote.tsx'; import { DefaultSettingFootnote } from '@/features/reader/settings/components/DefaultSettingFootnote.tsx';
import { import { IReaderSettingsWithDefaultFlag, TReaderAutoScrollContext } from '@/features/reader/Reader.types.ts';
IReaderSettingsWithDefaultFlag,
TReaderAutoScrollContext,
TReaderStateMangaContext,
} from '@/features/reader/Reader.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { ReaderSettingAutoScroll } from '@/features/reader/auto-scroll/settings/ReaderSettingAutoScroll.tsx'; import { ReaderSettingAutoScroll } from '@/features/reader/auto-scroll/settings/ReaderSettingAutoScroll.tsx';
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx'; import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
import { useReaderAutoScrollContext } from '@/features/reader/auto-scroll/ReaderAutoScrollContext.tsx'; import { useReaderAutoScrollContext } from '@/features/reader/auto-scroll/ReaderAutoScrollContext.tsx';
const BaseReaderBottomBarMobileQuickSettings = ({ const BaseReaderBottomBarMobileQuickSettings = ({
manga,
readingMode, readingMode,
readingDirection, readingDirection,
autoScroll, autoScroll,
isActive, isActive,
toggleActive, toggleActive,
}: Pick<TReaderStateMangaContext, 'manga'> & }: Pick<IReaderSettingsWithDefaultFlag, 'readingMode' | 'readingDirection' | 'autoScroll'> &
Pick<IReaderSettingsWithDefaultFlag, 'readingMode' | 'readingDirection' | 'autoScroll'> &
Pick<TReaderAutoScrollContext, 'isActive' | 'toggleActive'>) => { Pick<TReaderAutoScrollContext, 'isActive' | 'toggleActive'>) => {
const { t } = useTranslation(); const { t } = useTranslation();
const deleteSetting = ReaderService.useCreateDeleteSetting(manga ?? FALLBACK_MANGA);
if (!manga) {
return null;
}
return ( return (
<Stack sx={{ gap: 2 }}> <Stack sx={{ gap: 2 }}>
<DefaultSettingFootnote /> <DefaultSettingFootnote />
<ReaderSettingReadingMode <ReaderSettingReadingMode
readingMode={readingMode} readingMode={readingMode}
setReadingMode={(value) => ReaderService.updateSetting(manga, 'readingMode', value)} setReadingMode={(value) => ReaderService.updateSetting('readingMode', value)}
isDefaultable isDefaultable
onDefault={() => deleteSetting('readingMode')} onDefault={() => ReaderService.deleteSetting('readingMode')}
/> />
<ReaderSettingReadingDirection <ReaderSettingReadingDirection
readingDirection={readingDirection} readingDirection={readingDirection}
setReadingDirection={(value) => ReaderService.updateSetting(manga, 'readingDirection', value)} setReadingDirection={(value) => ReaderService.updateSetting('readingDirection', value)}
isDefaultable isDefaultable
onDefault={() => deleteSetting('readingDirection')} onDefault={() => ReaderService.deleteSetting('readingDirection')}
/> />
<CheckboxInput <CheckboxInput
label={t('reader.settings.auto_scroll.title')} label={t('reader.settings.auto_scroll.title')}
@@ -64,7 +51,7 @@ const BaseReaderBottomBarMobileQuickSettings = ({
/> />
<ReaderSettingAutoScroll <ReaderSettingAutoScroll
autoScroll={autoScroll} autoScroll={autoScroll}
setAutoScroll={(...args) => ReaderService.updateSetting(manga, 'autoScroll', ...args)} setAutoScroll={(...args) => ReaderService.updateSetting('autoScroll', ...args)}
/> />
</Stack> </Stack>
); );
@@ -72,6 +59,6 @@ const BaseReaderBottomBarMobileQuickSettings = ({
export const ReaderBottomBarMobileQuickSettings = withPropsFrom( export const ReaderBottomBarMobileQuickSettings = withPropsFrom(
memo(BaseReaderBottomBarMobileQuickSettings), memo(BaseReaderBottomBarMobileQuickSettings),
[useReaderStateMangaContext, ReaderService.useSettings, useReaderAutoScrollContext], [ReaderService.useSettings, useReaderAutoScrollContext],
['manga', 'readingMode', 'readingDirection', 'autoScroll', 'isActive', 'toggleActive'], ['readingMode', 'readingDirection', 'autoScroll', 'isActive', 'toggleActive'],
); );

View File

@@ -25,7 +25,6 @@ import { TapZoneLayout } from '@/features/reader/tap-zones/TapZoneLayout.tsx';
import { useReaderOverlayContext } from '@/features/reader/overlay/ReaderOverlayContext.tsx'; import { useReaderOverlayContext } from '@/features/reader/overlay/ReaderOverlayContext.tsx';
import { ReaderRGBAFilter } from '@/features/reader/filters/ReaderRGBAFilter.tsx'; import { ReaderRGBAFilter } from '@/features/reader/filters/ReaderRGBAFilter.tsx';
import { useReaderStateSettingsContext } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx'; import { useReaderStateSettingsContext } from '@/features/reader/contexts/state/ReaderStateSettingsContext.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { ReaderViewer } from '@/features/reader/viewer/ReaderViewer.tsx'; import { ReaderViewer } from '@/features/reader/viewer/ReaderViewer.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { READER_BACKGROUND_TO_COLOR } from '@/features/reader/settings/ReaderSettings.constants.tsx'; import { READER_BACKGROUND_TO_COLOR } from '@/features/reader/settings/ReaderSettings.constants.tsx';
@@ -36,7 +35,6 @@ import {
ReaderStateChapters, ReaderStateChapters,
ReaderStatePages, ReaderStatePages,
TReaderAutoScrollContext, TReaderAutoScrollContext,
TReaderStateMangaContext,
TReaderStateSettingsContext, TReaderStateSettingsContext,
} from '@/features/reader/Reader.types.ts'; } from '@/features/reader/Reader.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts';
@@ -54,14 +52,13 @@ import { useReaderSetChaptersState } from '@/features/reader/hooks/useReaderSetC
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
import { useChapterListOptions } from '@/features/chapter/utils/ChapterList.util.tsx'; import { useChapterListOptions } from '@/features/chapter/utils/ChapterList.util.tsx';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts'; import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { useReaderStore, useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const BaseReader = ({ const BaseReader = ({
setOverride, setOverride,
readerNavBarWidth, readerNavBarWidth,
isVisible: isOverlayVisible, isVisible: isOverlayVisible,
setIsVisible: setIsOverlayVisible, setIsVisible: setIsOverlayVisible,
manga,
setManga,
shouldSkipDupChapters, shouldSkipDupChapters,
shouldSkipFilteredChapters, shouldSkipFilteredChapters,
backgroundColor, backgroundColor,
@@ -87,7 +84,6 @@ const BaseReader = ({
setShowPreview, setShowPreview,
}: Pick<NavbarContextType, 'setOverride' | 'readerNavBarWidth'> & }: Pick<NavbarContextType, 'setOverride' | 'readerNavBarWidth'> &
Pick<TReaderOverlayContext, 'isVisible' | 'setIsVisible'> & Pick<TReaderOverlayContext, 'isVisible' | 'setIsVisible'> &
Pick<TReaderStateMangaContext, 'manga' | 'setManga'> &
Pick<TReaderStateSettingsContext, 'setSettings'> & Pick<TReaderStateSettingsContext, 'setSettings'> &
Pick< Pick<
IReaderSettings, IReaderSettings,
@@ -120,6 +116,7 @@ const BaseReader = ({
cancelAutoScroll: TReaderAutoScrollContext['cancel']; cancelAutoScroll: TReaderAutoScrollContext['cancel'];
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const manga = useReaderStoreShallow((state) => state.manga);
const scrollElementRef = useRef<HTMLDivElement | null>(null); const scrollElementRef = useRef<HTMLDivElement | null>(null);
@@ -157,11 +154,10 @@ const BaseReader = ({
const error = mangaResponse.error ?? chaptersResponse.error ?? defaultSettingsResponse.error; const error = mangaResponse.error ?? chaptersResponse.error ?? defaultSettingsResponse.error;
useEffect(() => { useEffect(() => {
setManga(mangaResponse.data?.manga); useReaderStore.getState().setManga(mangaResponse.data?.manga);
}, [mangaResponse.data?.manga]); }, [mangaResponse.data?.manga]);
useReaderResetStates( useReaderResetStates(
setManga,
setReaderStateChapters, setReaderStateChapters,
setCurrentPageIndex, setCurrentPageIndex,
setPageToScrollToIndex, setPageToScrollToIndex,
@@ -306,7 +302,6 @@ export const Reader = withPropsFrom(
[ [
useNavBarContext, useNavBarContext,
useReaderOverlayContext, useReaderOverlayContext,
useReaderStateMangaContext,
useReaderStateChaptersContext, useReaderStateChaptersContext,
useReaderStateSettingsContext, useReaderStateSettingsContext,
() => { () => {
@@ -338,8 +333,6 @@ export const Reader = withPropsFrom(
'readerNavBarWidth', 'readerNavBarWidth',
'isVisible', 'isVisible',
'setIsVisible', 'setIsVisible',
'manga',
'setManga',
'shouldSkipDupChapters', 'shouldSkipDupChapters',
'shouldSkipFilteredChapters', 'shouldSkipFilteredChapters',
'backgroundColor', 'backgroundColor',

View File

@@ -22,12 +22,10 @@ import {
ReadingDirection, ReadingDirection,
ReadingMode, ReadingMode,
} from '@/features/reader/Reader.types.ts'; } from '@/features/reader/Reader.types.ts';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { import {
convertFromReaderSettingsWithDefaultFlag, convertFromReaderSettingsWithDefaultFlag,
updateReaderSettings, updateReaderSettings,
} from '@/features/reader/settings/ReaderSettingsMetadata.ts'; } from '@/features/reader/settings/ReaderSettingsMetadata.ts';
import { MangaIdInfo } from '@/features/manga/Manga.types.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { MANGA_META_FIELDS } from '@/lib/graphql/fragments/MangaFragments.ts'; import { MANGA_META_FIELDS } from '@/lib/graphql/fragments/MangaFragments.ts';
import { makeToast } from '@/base/utils/Toast.ts'; import { makeToast } from '@/base/utils/Toast.ts';
@@ -54,6 +52,7 @@ import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts'; import { FALLBACK_MANGA } from '@/features/manga/Manga.constants.ts';
import { getMetadataKey } from '@/features/metadata/Metadata.utils.ts'; import { getMetadataKey } from '@/features/metadata/Metadata.utils.ts';
import { DirectionOffset } from '@/base/Base.types.ts'; import { DirectionOffset } from '@/base/Base.types.ts';
import { getReaderStore } from '@/features/reader/ReaderStore.ts';
const DIRECTION_TO_INVERTED: Record<Direction, Direction> = { const DIRECTION_TO_INVERTED: Record<Direction, Direction> = {
ltr: 'rtl', ltr: 'rtl',
@@ -156,7 +155,6 @@ export class ReaderService {
} }
static useUpdateChapter(): (patch: UpdateChapterPatchInput) => void { static useUpdateChapter(): (patch: UpdateChapterPatchInput) => void {
const { manga } = useReaderStateMangaContext();
const { currentChapter, mangaChapters, chapters } = useReaderStateChaptersContext(); const { currentChapter, mangaChapters, chapters } = useReaderStateChaptersContext();
const { shouldSkipDupChapters } = ReaderService.useSettings(); const { shouldSkipDupChapters } = ReaderService.useSettings();
const { const {
@@ -175,6 +173,8 @@ export class ReaderService {
return useCallback( return useCallback(
(patch) => { (patch) => {
const { manga } = getReaderStore();
if (!manga || !currentChapter || !mangaChapters) { if (!manga || !currentChapter || !mangaChapters) {
return; return;
} }
@@ -235,7 +235,6 @@ export class ReaderService {
ReaderService.getOrCreateChapterUpdateQueue(currentChapter.id).enqueue(`${currentChapter.id}`, update); ReaderService.getOrCreateChapterUpdateQueue(currentChapter.id).enqueue(`${currentChapter.id}`, update);
}, },
[ [
manga?.id,
currentChapter?.id, currentChapter?.id,
mangaChapters, mangaChapters,
previousChapters, previousChapters,
@@ -268,13 +267,14 @@ export class ReaderService {
* Writes the change immediately to the cache and sends a mutation in case "commit" is true. * Writes the change immediately to the cache and sends a mutation in case "commit" is true.
*/ */
static updateSetting<Setting extends keyof IReaderSettings>( static updateSetting<Setting extends keyof IReaderSettings>(
manga: MangaIdInfo,
setting: Setting, setting: Setting,
value: IReaderSettings[Setting], value: IReaderSettings[Setting],
commit: boolean = true, commit: boolean = true,
isGlobal: boolean = false, isGlobal: boolean = false,
profile?: ReadingMode, profile?: ReadingMode,
): void { ): void {
const { manga } = getReaderStore();
if (!manga || manga.id === FALLBACK_MANGA.id) { if (!manga || manga.id === FALLBACK_MANGA.id) {
return; return;
} }
@@ -334,11 +334,12 @@ export class ReaderService {
} }
static deleteSetting<Setting extends keyof IReaderSettings>( static deleteSetting<Setting extends keyof IReaderSettings>(
manga: MangaIdInfo,
setting: Setting, setting: Setting,
isGlobal: boolean = false, isGlobal: boolean = false,
profile?: string, profile?: string,
): void { ): void {
const { manga } = getReaderStore();
if (!manga || manga.id === FALLBACK_MANGA.id) { if (!manga || manga.id === FALLBACK_MANGA.id) {
return; return;
} }
@@ -362,31 +363,6 @@ export class ReaderService {
); );
} }
static useCreateUpdateSetting<Setting extends keyof IReaderSettings>(
manga: MangaIdInfo,
profile?: ReadingMode,
): (
...args: OmitFirst<Parameters<typeof ReaderService.updateSetting<Setting>>>
) => ReturnType<typeof ReaderService.updateSetting<Setting>> {
return useCallback(
(setting, value, commit, isGlobal) =>
ReaderService.updateSetting<Setting>(manga, setting, value, commit, isGlobal, profile),
[manga, profile],
);
}
static useCreateDeleteSetting<Setting extends keyof IReaderSettings>(
manga: MangaIdInfo,
profile?: ReadingMode,
): (
...args: OmitFirst<Parameters<typeof ReaderService.deleteSetting<Setting>>>
) => ReturnType<typeof ReaderService.deleteSetting<Setting>> {
return useCallback(
(setting, isGlobal) => ReaderService.deleteSetting<Setting>(manga, setting, isGlobal, profile?.toString()),
[manga, profile],
);
}
static useOverlayMode(): { mode: ReaderOverlayMode; isDesktop: boolean; isMobile: boolean } { static useOverlayMode(): { mode: ReaderOverlayMode; isDesktop: boolean; isMobile: boolean } {
const isTouchDevice = MediaQuery.useIsTouchDevice(); const isTouchDevice = MediaQuery.useIsTouchDevice();
const { overlayMode } = ReaderService.useSettings(); const { overlayMode } = ReaderService.useSettings();
@@ -406,18 +382,19 @@ export class ReaderService {
} }
static useExit(): () => void { static useExit(): () => void {
const { manga } = useReaderStateMangaContext();
const { exitMode } = ReaderService.useSettings(); const { exitMode } = ReaderService.useSettings();
const handleBack = useBackButton(); const handleBack = useBackButton();
const navigate = useNavigate(); const navigate = useNavigate();
const openMangaPage = useCallback(() => { const openMangaPage = useCallback(() => {
const { manga } = getReaderStore();
if (!manga) { if (!manga) {
return () => {}; return () => {};
} }
return navigate(AppRoutes.manga.path(manga.id)); return navigate(AppRoutes.manga.path(manga.id));
}, [manga]); }, []);
switch (exitMode) { switch (exitMode) {
case ReaderExitMode.PREVIOUS: case ReaderExitMode.PREVIOUS:

View File

@@ -31,7 +31,7 @@ export const ReaderBehaviourSettings = ({
}: { }: {
settings: IReaderSettingsWithDefaultFlag; settings: IReaderSettingsWithDefaultFlag;
updateSetting: ( updateSetting: (
...args: OmitFirst<Parameters<typeof ReaderService.updateSetting>> ...args: Parameters<typeof ReaderService.updateSetting>
) => ReturnType<typeof ReaderService.updateSetting>; ) => ReturnType<typeof ReaderService.updateSetting>;
} & ReaderSettingsTypeProps) => { } & ReaderSettingsTypeProps) => {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -41,7 +41,7 @@ const BaseReaderSettingsTabs = ({
activeTab: number; activeTab: number;
setActiveTab: (tab: number) => void; setActiveTab: (tab: number) => void;
settings: IReaderSettingsWithDefaultFlag; settings: IReaderSettingsWithDefaultFlag;
updateSetting: (...args: OmitFirst<Parameters<typeof ReaderService.updateSetting>>) => void; updateSetting: (...args: Parameters<typeof ReaderService.updateSetting>) => void;
areDefaultSettings?: boolean; areDefaultSettings?: boolean;
deleteSetting: (setting: keyof IReaderSettings) => void; deleteSetting: (setting: keyof IReaderSettings) => void;
setTransparent?: (transparent: boolean) => void; setTransparent?: (transparent: boolean) => void;

View File

@@ -26,7 +26,7 @@ export const ReaderSettingWidth = ({
setTransparent, setTransparent,
}: Pick<IReaderSettings, 'readerWidth' | 'pageScaleMode'> & }: Pick<IReaderSettings, 'readerWidth' | 'pageScaleMode'> &
Pick<MultiValueButtonDefaultableProps<IReaderSettings['readerWidth']['value']>, 'isDefaultable' | 'onDefault'> & { Pick<MultiValueButtonDefaultableProps<IReaderSettings['readerWidth']['value']>, 'isDefaultable' | 'onDefault'> & {
updateSetting: (...args: OmitFirst<Parameters<typeof ReaderService.updateSetting>>) => void; updateSetting: (...args: Parameters<typeof ReaderService.updateSetting>) => void;
setTransparent?: (transparent: boolean) => void; setTransparent?: (transparent: boolean) => void;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -16,7 +16,6 @@ import { IReaderSettings, ReadingMode } from '@/features/reader/Reader.types.ts'
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { ReaderSettingsTabs } from '@/features/reader/settings/components/ReaderSettingsTabs.tsx'; import { ReaderSettingsTabs } from '@/features/reader/settings/components/ReaderSettingsTabs.tsx';
import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { GLOBAL_READER_SETTINGS_MANGA } from '@/features/manga/Manga.constants.ts';
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts'; import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
export const GlobalReaderSettings = () => { export const GlobalReaderSettings = () => {
@@ -37,7 +36,7 @@ export const GlobalReaderSettings = () => {
commit?: boolean, commit?: boolean,
profile?: ReadingMode, profile?: ReadingMode,
) => { ) => {
ReaderService.updateSetting(GLOBAL_READER_SETTINGS_MANGA, key, value, commit, true, profile); ReaderService.updateSetting(key, value, commit, true, profile);
}; };
if (loading) { if (loading) {
@@ -61,7 +60,7 @@ export const GlobalReaderSettings = () => {
areDefaultSettings areDefaultSettings
settings={settings} settings={settings}
updateSetting={(setting, value, commit, _, profile) => updateSetting(setting, value, commit, profile)} updateSetting={(setting, value, commit, _, profile) => updateSetting(setting, value, commit, profile)}
deleteSetting={(setting) => ReaderService.deleteSetting(GLOBAL_READER_SETTINGS_MANGA, setting, true)} deleteSetting={(setting) => ReaderService.deleteSetting(setting, true)}
/> />
); );
}; };

View File

@@ -10,7 +10,6 @@ import Dialog from '@mui/material/Dialog';
import DialogContent from '@mui/material/DialogContent'; import DialogContent from '@mui/material/DialogContent';
import { useState } from 'react'; import { useState } from 'react';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { ReaderSettingsTabs } from '@/features/reader/settings/components/ReaderSettingsTabs.tsx'; import { ReaderSettingsTabs } from '@/features/reader/settings/components/ReaderSettingsTabs.tsx';
import { ReaderSettingTab } from '@/features/reader/settings/ReaderSettings.constants.tsx'; import { ReaderSettingTab } from '@/features/reader/settings/ReaderSettings.constants.tsx';
@@ -18,7 +17,6 @@ import { useDisableAllHotkeysWhileMounted } from '@/features/hotkeys/Hotkeys.uti
import { applyStyles } from '@/base/utils/ApplyStyles.ts'; import { applyStyles } from '@/base/utils/ApplyStyles.ts';
export const ReaderSettings = ({ isOpen, close }: { isOpen: boolean; close: () => void }) => { export const ReaderSettings = ({ isOpen, close }: { isOpen: boolean; close: () => void }) => {
const { manga } = useReaderStateMangaContext();
const settings = ReaderService.useSettings(); const settings = ReaderService.useSettings();
useDisableAllHotkeysWhileMounted(isOpen); useDisableAllHotkeysWhileMounted(isOpen);
@@ -26,10 +24,6 @@ export const ReaderSettings = ({ isOpen, close }: { isOpen: boolean; close: () =
const [activeTab, setActiveTab] = useState(0); const [activeTab, setActiveTab] = useState(0);
const [isTransparent, setIsTransparent] = useState(false); const [isTransparent, setIsTransparent] = useState(false);
if (!manga) {
return null;
}
if (!isOpen) { if (!isOpen) {
return null; return null;
} }
@@ -52,8 +46,8 @@ export const ReaderSettings = ({ isOpen, close }: { isOpen: boolean; close: () =
activeTab={activeTab} activeTab={activeTab}
setActiveTab={setActiveTab} setActiveTab={setActiveTab}
settings={settings} settings={settings}
updateSetting={(...args) => ReaderService.updateSetting(manga, ...args)} updateSetting={(...args) => ReaderService.updateSetting(...args)}
deleteSetting={(...args) => ReaderService.deleteSetting(manga, ...args)} deleteSetting={(...args) => ReaderService.deleteSetting(...args)}
setTransparent={setIsTransparent} setTransparent={setIsTransparent}
/> />
</DialogContent> </DialogContent>

View File

@@ -119,6 +119,7 @@ export class ReaderTapZoneService {
context.beginPath(); context.beginPath();
/* eslint-disable no-param-reassign */
context.rect(x, y, width, height); context.rect(x, y, width, height);
context.fillStyle = color; context.fillStyle = color;
context.strokeStyle = color; context.strokeStyle = color;
@@ -139,6 +140,7 @@ export class ReaderTapZoneService {
context.lineWidth = 1; context.lineWidth = 1;
context.fillStyle = 'white'; context.fillStyle = 'white';
context.fillText(text, rectCenterX, rectCenterY); context.fillText(text, rectCenterX, rectCenterY);
/* eslint-enable no-param-reassign */
}); });
} }

View File

@@ -21,7 +21,6 @@ import {
ReaderTransitionPageMode, ReaderTransitionPageMode,
ReadingMode, ReadingMode,
TReaderScrollbarContext, TReaderScrollbarContext,
TReaderStateMangaContext,
} from '@/features/reader/Reader.types.ts'; } from '@/features/reader/Reader.types.ts';
import { isTransitionPageVisible } from '@/features/reader/viewer/pager/ReaderPager.utils.tsx'; import { isTransitionPageVisible } from '@/features/reader/viewer/pager/ReaderPager.utils.tsx';
import { useBackButton } from '@/base/hooks/useBackButton.ts'; import { useBackButton } from '@/base/hooks/useBackButton.ts';
@@ -34,13 +33,13 @@ import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx';
import { AppRoutes } from '@/base/AppRoute.constants.ts'; import { AppRoutes } from '@/base/AppRoute.constants.ts';
import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts'; import { NavbarContextType } from '@/features/navigation-bar/NavigationBar.types.ts';
import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx'; import { withPropsFrom } from '@/base/hoc/withPropsFrom.tsx';
import { useReaderStateMangaContext } from '@/features/reader/contexts/state/ReaderStateMangaContext.tsx';
import { getValueFromObject, noOp } from '@/lib/HelperFunctions.ts'; import { getValueFromObject, noOp } from '@/lib/HelperFunctions.ts';
import { READER_BACKGROUND_TO_COLOR } from '@/features/reader/settings/ReaderSettings.constants.tsx'; import { READER_BACKGROUND_TO_COLOR } from '@/features/reader/settings/ReaderSettings.constants.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts'; import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx'; import { userReaderStatePagesContext } from '@/features/reader/contexts/state/ReaderStatePagesContext.tsx';
import { ChapterType } from '@/lib/graphql/generated/graphql.ts'; import { ChapterType } from '@/lib/graphql/generated/graphql.ts';
import { ChapterIdInfo } from '@/features/chapter/Chapter.types.ts'; import { ChapterIdInfo } from '@/features/chapter/Chapter.types.ts';
import { useReaderStoreShallow } from '@/features/reader/ReaderStore.ts';
const ChapterInfo = ({ const ChapterInfo = ({
title, title,
@@ -85,7 +84,6 @@ const BaseReaderTransitionPage = ({
readingMode, readingMode,
backgroundColor, backgroundColor,
shouldShowTransitionPage, shouldShowTransitionPage,
manga,
currentChapterName, currentChapterName,
currentChapterScanlator, currentChapterScanlator,
previousChapterName, previousChapterName,
@@ -97,7 +95,6 @@ const BaseReaderTransitionPage = ({
readerNavBarWidth, readerNavBarWidth,
handleBack, handleBack,
}: Pick<IReaderSettings, 'readingMode' | 'backgroundColor' | 'shouldShowTransitionPage'> & }: Pick<IReaderSettings, 'readingMode' | 'backgroundColor' | 'shouldShowTransitionPage'> &
Pick<TReaderStateMangaContext, 'manga'> &
Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> & Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> &
Pick<ReaderStatePages, 'transitionPageMode'> & Pick<ReaderStatePages, 'transitionPageMode'> &
Pick<NavbarContextType, 'readerNavBarWidth'> & { Pick<NavbarContextType, 'readerNavBarWidth'> & {
@@ -114,6 +111,7 @@ const BaseReaderTransitionPage = ({
handleBack: () => void; handleBack: () => void;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const manga = useReaderStoreShallow((state) => state.manga);
const isPreviousType = type === ReaderTransitionPageMode.PREVIOUS; const isPreviousType = type === ReaderTransitionPageMode.PREVIOUS;
const isNextType = type === ReaderTransitionPageMode.NEXT; const isNextType = type === ReaderTransitionPageMode.NEXT;
@@ -236,7 +234,6 @@ const BaseReaderTransitionPage = ({
export const ReaderTransitionPage = withPropsFrom( export const ReaderTransitionPage = withPropsFrom(
memo(BaseReaderTransitionPage) as typeof BaseReaderTransitionPage, memo(BaseReaderTransitionPage) as typeof BaseReaderTransitionPage,
[ [
useReaderStateMangaContext,
({ chapterId }: Pick<ComponentProps<typeof BaseReaderTransitionPage>, 'chapterId'>) => { ({ chapterId }: Pick<ComponentProps<typeof BaseReaderTransitionPage>, 'chapterId'>) => {
const { chapters } = useReaderStateChaptersContext(); const { chapters } = useReaderStateChaptersContext();
@@ -286,7 +283,6 @@ export const ReaderTransitionPage = withPropsFrom(
}, },
], ],
[ [
'manga',
'currentChapterName', 'currentChapterName',
'currentChapterScanlator', 'currentChapterScanlator',
'previousChapterName', 'previousChapterName',