Extract logic from "Reader" into hooks
This commit is contained in:
60
src/modules/reader/hooks/useReaderResetStates.ts
Normal file
60
src/modules/reader/hooks/useReaderResetStates.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 { useEffect } from 'react';
|
||||
import { createPageData } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
||||
import {
|
||||
ReaderStateChapters,
|
||||
ReaderTransitionPageMode,
|
||||
TReaderAutoScrollContext,
|
||||
TReaderStateMangaContext,
|
||||
TReaderStateSettingsContext,
|
||||
} from '@/modules/reader/types/Reader.types.ts';
|
||||
import { DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG } from '@/modules/reader/services/ReaderSettingsMetadata.ts';
|
||||
import { ReaderStatePages } from '@/modules/reader/types/ReaderProgressBar.types.ts';
|
||||
import { TReaderOverlayContext } from '@/modules/reader/types/ReaderOverlay.types.ts';
|
||||
|
||||
export const useReaderResetStates = (
|
||||
setManga: TReaderStateMangaContext['setManga'],
|
||||
setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'],
|
||||
setCurrentPageIndex: ReaderStatePages['setCurrentPageIndex'],
|
||||
setPageToScrollToIndex: ReaderStatePages['setPageToScrollToIndex'],
|
||||
setTotalPages: ReaderStatePages['setTotalPages'],
|
||||
setPages: ReaderStatePages['setPages'],
|
||||
setPageUrls: ReaderStatePages['setPageUrls'],
|
||||
setPageLoadStates: ReaderStatePages['setPageLoadStates'],
|
||||
setTransitionPageMode: ReaderStatePages['setTransitionPageMode'],
|
||||
setIsOverlayVisible: TReaderOverlayContext['setIsVisible'],
|
||||
setSettings: TReaderStateSettingsContext['setSettings'],
|
||||
cancelAutoScroll: TReaderAutoScrollContext['cancel'],
|
||||
) => {
|
||||
useEffect(
|
||||
() => () => {
|
||||
setManga(undefined);
|
||||
setReaderStateChapters({
|
||||
mangaChapters: [],
|
||||
chapters: [],
|
||||
});
|
||||
|
||||
setCurrentPageIndex(0);
|
||||
setPageToScrollToIndex(null);
|
||||
setTotalPages(0);
|
||||
setPages([createPageData('', 0)]);
|
||||
setPageUrls([]);
|
||||
setPageLoadStates([{ url: '', loaded: false }]);
|
||||
setTransitionPageMode(ReaderTransitionPageMode.NONE);
|
||||
|
||||
setIsOverlayVisible(false);
|
||||
|
||||
setSettings(DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG);
|
||||
|
||||
cancelAutoScroll();
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
56
src/modules/reader/hooks/useReaderSetChaptersState.ts
Normal file
56
src/modules/reader/hooks/useReaderSetChaptersState.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 { useEffect } from 'react';
|
||||
import { Chapters } from '@/modules/chapter/services/Chapters.ts';
|
||||
import { DirectionOffset } from '@/Base.types.ts';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { GetChaptersReaderQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { IReaderSettings, ReaderStateChapters } from '@/modules/reader/types/Reader.types.ts';
|
||||
|
||||
export const useReaderSetChaptersState = (
|
||||
chaptersResponse: ReturnType<typeof requestManager.useGetMangaChapters<GetChaptersReaderQuery>>,
|
||||
chapterSourceOrder: number,
|
||||
initialChapter: ReaderStateChapters['initialChapter'],
|
||||
setReaderStateChapters: ReaderStateChapters['setReaderStateChapters'],
|
||||
shouldSkipDupChapters: IReaderSettings['shouldSkipDupChapters'],
|
||||
) => {
|
||||
useEffect(() => {
|
||||
const newMangaChapters = chaptersResponse.data?.chapters.nodes;
|
||||
const newCurrentChapter = newMangaChapters
|
||||
? (newMangaChapters[newMangaChapters.length - chapterSourceOrder] ?? null)
|
||||
: undefined;
|
||||
const newInitialChapter = initialChapter ?? newCurrentChapter;
|
||||
|
||||
setReaderStateChapters({
|
||||
mangaChapters: newMangaChapters ?? [],
|
||||
chapters:
|
||||
newInitialChapter && newMangaChapters
|
||||
? Chapters.removeDuplicates(newInitialChapter, newMangaChapters)
|
||||
: [],
|
||||
initialChapter: newInitialChapter,
|
||||
currentChapter: newCurrentChapter,
|
||||
nextChapter:
|
||||
newMangaChapters &&
|
||||
newCurrentChapter &&
|
||||
Chapters.getNextChapter(newCurrentChapter, newMangaChapters, {
|
||||
offset: DirectionOffset.NEXT,
|
||||
skipDupe: shouldSkipDupChapters,
|
||||
skipDupeChapter: newInitialChapter,
|
||||
}),
|
||||
previousChapter:
|
||||
newMangaChapters &&
|
||||
newCurrentChapter &&
|
||||
Chapters.getNextChapter(newCurrentChapter, newMangaChapters, {
|
||||
offset: DirectionOffset.PREVIOUS,
|
||||
skipDupe: shouldSkipDupChapters,
|
||||
skipDupeChapter: newInitialChapter,
|
||||
}),
|
||||
});
|
||||
}, [chaptersResponse.data?.chapters.nodes, chapterSourceOrder, shouldSkipDupChapters]);
|
||||
};
|
||||
65
src/modules/reader/hooks/useReaderSetPagesState.ts
Normal file
65
src/modules/reader/hooks/useReaderSetPagesState.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 { useEffect } from 'react';
|
||||
import { getInitialReaderPageIndex } from '@/modules/reader/utils/Reader.utils.ts';
|
||||
import { createPageData, createPagesData } from '@/modules/reader/utils/ReaderPager.utils.tsx';
|
||||
import {
|
||||
ReaderResumeMode,
|
||||
ReaderStateChapters,
|
||||
ReaderTransitionPageMode,
|
||||
} from '@/modules/reader/types/Reader.types.ts';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { ReaderStatePages } from '@/modules/reader/types/ReaderProgressBar.types.ts';
|
||||
|
||||
export const useReaderSetPagesState = (
|
||||
pagesResponse: ReturnType<typeof requestManager.useGetChapterPagesFetch>[1],
|
||||
resumeMode: ReaderResumeMode,
|
||||
currentChapter: ReaderStateChapters['currentChapter'],
|
||||
setArePagesFetched: (fetched: boolean) => void,
|
||||
setTotalPages: ReaderStatePages['setTotalPages'],
|
||||
setPages: ReaderStatePages['setPages'],
|
||||
setPageUrls: ReaderStatePages['setPageUrls'],
|
||||
setPageLoadStates: ReaderStatePages['setPageLoadStates'],
|
||||
setCurrentPageIndex: ReaderStatePages['setCurrentPageIndex'],
|
||||
setPageToScrollToIndex: ReaderStatePages['setPageToScrollToIndex'],
|
||||
setTransitionPageMode: ReaderStatePages['setTransitionPageMode'],
|
||||
) => {
|
||||
useEffect(() => {
|
||||
const pagesPayload = pagesResponse.data?.fetchChapterPages;
|
||||
if (pagesPayload) {
|
||||
const { pages: newPages } = pagesPayload;
|
||||
|
||||
const initialReaderPageIndex = getInitialReaderPageIndex(
|
||||
resumeMode,
|
||||
currentChapter?.lastPageRead ?? 0,
|
||||
newPages.length - 1,
|
||||
);
|
||||
|
||||
const newPageData = createPagesData(newPages);
|
||||
|
||||
setArePagesFetched(true);
|
||||
setTotalPages(pagesPayload.chapter.pageCount);
|
||||
setPages(newPageData);
|
||||
setPageUrls(newPages);
|
||||
setPageLoadStates(newPageData.map(({ primary: { url } }) => ({ url, loaded: false })));
|
||||
setCurrentPageIndex(initialReaderPageIndex);
|
||||
setPageToScrollToIndex(initialReaderPageIndex);
|
||||
} else {
|
||||
setArePagesFetched(false);
|
||||
setCurrentPageIndex(0);
|
||||
setPageToScrollToIndex(null);
|
||||
setTotalPages(0);
|
||||
setPages([createPageData('', 0)]);
|
||||
setPageUrls([]);
|
||||
setPageLoadStates([{ url: '', loaded: false }]);
|
||||
}
|
||||
|
||||
setTransitionPageMode(ReaderTransitionPageMode.NONE);
|
||||
}, [pagesResponse.data?.fetchChapterPages?.pages]);
|
||||
};
|
||||
62
src/modules/reader/hooks/useReaderSetSettingsState.ts
Normal file
62
src/modules/reader/hooks/useReaderSetSettingsState.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 { useEffect } from 'react';
|
||||
import {
|
||||
getReaderSettings,
|
||||
getReaderSettingsFor,
|
||||
useDefaultReaderSettings,
|
||||
} from '@/modules/reader/services/ReaderSettingsMetadata.ts';
|
||||
import { isAutoWebtoonMode } from '@/modules/reader/utils/ReaderSettings.utils.tsx';
|
||||
import { ReadingMode, TReaderStateSettingsContext } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { GetMangaReaderQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
|
||||
export const useReaderSetSettingsState = (
|
||||
mangaResponse: ReturnType<typeof requestManager.useGetManga<GetMangaReaderQuery>>,
|
||||
defaultSettingsResponse: ReturnType<typeof useDefaultReaderSettings>['request'],
|
||||
defaultSettings: ReturnType<typeof useDefaultReaderSettings>['settings'],
|
||||
defaultSettingsMetadata: ReturnType<typeof useDefaultReaderSettings>['metadata'],
|
||||
setSettings: TReaderStateSettingsContext['setSettings'],
|
||||
setAreSettingsSet: (areSet: boolean) => void,
|
||||
) => {
|
||||
useEffect(() => {
|
||||
const mangaFromResponse = mangaResponse.data?.manga;
|
||||
if (!mangaFromResponse || defaultSettingsResponse.loading || defaultSettingsResponse.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
const settingsWithDefaultProfileFallback = getReaderSettingsFor(mangaFromResponse, defaultSettings);
|
||||
|
||||
const shouldUseWebtoonMode = isAutoWebtoonMode(
|
||||
mangaFromResponse,
|
||||
settingsWithDefaultProfileFallback.shouldUseAutoWebtoonMode,
|
||||
settingsWithDefaultProfileFallback.readingMode,
|
||||
);
|
||||
|
||||
const defaultSettingsWithAutoReadingMode = {
|
||||
...defaultSettings,
|
||||
readingMode: shouldUseWebtoonMode ? ReadingMode.WEBTOON : defaultSettings.readingMode,
|
||||
};
|
||||
|
||||
const profile = shouldUseWebtoonMode
|
||||
? ReadingMode.WEBTOON
|
||||
: settingsWithDefaultProfileFallback.readingMode.value;
|
||||
const profileSettings = getReaderSettings(
|
||||
'global',
|
||||
{ meta: defaultSettingsMetadata! },
|
||||
defaultSettingsWithAutoReadingMode,
|
||||
undefined,
|
||||
profile,
|
||||
);
|
||||
|
||||
const finalSettings = getReaderSettingsFor(mangaFromResponse, profileSettings);
|
||||
setSettings(finalSettings);
|
||||
setAreSettingsSet(true);
|
||||
}, [mangaResponse.data?.manga, defaultSettings]);
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 { useEffect, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IReaderSettings, IReaderSettingsWithDefaultFlag } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { makeToast } from '@/modules/core/utils/Toast.ts';
|
||||
import { READING_MODE_VALUE_TO_DISPLAY_DATA } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
|
||||
import { TranslationKey } from '@/Base.types.ts';
|
||||
import { TReaderTapZoneContext } from '@/modules/reader/types/TapZoneLayout.types.ts';
|
||||
|
||||
const HIDE_PREVIEW_TIMEOUT = 5000;
|
||||
|
||||
export const useReaderShowSettingPreviewOnChange = (
|
||||
isLoading: boolean,
|
||||
error: any,
|
||||
areSettingsSet: boolean,
|
||||
readingMode: IReaderSettingsWithDefaultFlag['readingMode'],
|
||||
tapZoneLayout: IReaderSettingsWithDefaultFlag['tapZoneLayout'],
|
||||
tapZoneInvertMode: IReaderSettingsWithDefaultFlag['tapZoneInvertMode'],
|
||||
shouldShowReadingModePreview: IReaderSettings['shouldShowReadingModePreview'],
|
||||
shouldShowTapZoneLayoutPreview: IReaderSettings['shouldShowTapZoneLayoutPreview'],
|
||||
setShowPreview: TReaderTapZoneContext['setShowPreview'],
|
||||
) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// show setting previews on change or when open reader
|
||||
const previousReadingMode = useRef<IReaderSettingsWithDefaultFlag['readingMode']>();
|
||||
const previousTapZoneLayout = useRef<IReaderSettingsWithDefaultFlag['tapZoneLayout']>();
|
||||
const previousTapZoneInvertMode = useRef<IReaderSettingsWithDefaultFlag['tapZoneInvertMode']>();
|
||||
const isInitialPreview = useRef(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoading || error || !areSettingsSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
const didReadingModeChange = JSON.stringify(readingMode) !== JSON.stringify(previousReadingMode.current);
|
||||
const showReadingModePreview = shouldShowReadingModePreview && didReadingModeChange;
|
||||
if (showReadingModePreview) {
|
||||
makeToast(t(READING_MODE_VALUE_TO_DISPLAY_DATA[readingMode.value].title as TranslationKey), {
|
||||
autoHideDuration: HIDE_PREVIEW_TIMEOUT,
|
||||
});
|
||||
}
|
||||
previousReadingMode.current = readingMode;
|
||||
|
||||
const didTapZoneLayoutChange =
|
||||
JSON.stringify(tapZoneLayout) !== JSON.stringify(previousTapZoneLayout.current) ||
|
||||
JSON.stringify(tapZoneInvertMode) !== JSON.stringify(previousTapZoneInvertMode.current);
|
||||
const showTapZoneLayoutPreview = shouldShowTapZoneLayoutPreview && didTapZoneLayoutChange;
|
||||
if (showTapZoneLayoutPreview) {
|
||||
setShowPreview(true);
|
||||
if (isInitialPreview.current) {
|
||||
setTimeout(() => setShowPreview(false), HIDE_PREVIEW_TIMEOUT);
|
||||
}
|
||||
}
|
||||
previousTapZoneLayout.current = tapZoneLayout;
|
||||
previousTapZoneInvertMode.current = tapZoneInvertMode;
|
||||
|
||||
isInitialPreview.current = false;
|
||||
}, [
|
||||
isLoading,
|
||||
error,
|
||||
areSettingsSet,
|
||||
readingMode.value,
|
||||
readingMode.isDefault,
|
||||
tapZoneLayout.value,
|
||||
tapZoneLayout.isDefault,
|
||||
tapZoneInvertMode.value,
|
||||
tapZoneInvertMode.isDefault,
|
||||
]);
|
||||
};
|
||||
Reference in New Issue
Block a user