From 942d8699c1e457927eb30592669a3cd5a22cb031 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:26:32 +0100 Subject: [PATCH] Add "Webtoon" reading mode --- src/assets/icons/svg/WebtoonPageIcon.tsx | 24 +++++++++++++++++++ .../reader/components/ReaderHotkeys.tsx | 1 + .../settings/layout/ReaderSettingPageGap.tsx | 4 ++-- .../viewer/ReaderTransitionPage.tsx | 9 ++++--- .../reader/components/viewer/ReaderViewer.tsx | 2 ++ .../viewer/pager/ReaderVerticalPager.tsx | 8 ++++--- .../constants/ReaderSettings.constants.tsx | 5 ++++ src/modules/reader/types/Reader.types.ts | 1 + .../reader/utils/ReaderPager.utils.tsx | 16 +++++++++---- .../reader/utils/ReaderSettings.utils.tsx | 5 +++- 10 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 src/assets/icons/svg/WebtoonPageIcon.tsx diff --git a/src/assets/icons/svg/WebtoonPageIcon.tsx b/src/assets/icons/svg/WebtoonPageIcon.tsx new file mode 100644 index 00000000..a4dd0527 --- /dev/null +++ b/src/assets/icons/svg/WebtoonPageIcon.tsx @@ -0,0 +1,24 @@ +/* + * 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 SvgIcon from '@mui/material/SvgIcon'; + +export const WebtoonPageIcon = () => ( + + + + + +); diff --git a/src/modules/reader/components/ReaderHotkeys.tsx b/src/modules/reader/components/ReaderHotkeys.tsx index 499185ec..cc047631 100644 --- a/src/modules/reader/components/ReaderHotkeys.tsx +++ b/src/modules/reader/components/ReaderHotkeys.tsx @@ -62,6 +62,7 @@ const CONTINUOUS_READING_MODE_TO_SCROLL_DIRECTION: Record { const { t } = useTranslation(); - const isChangeable = isContinuousReadingMode(readingMode.value); + const isChangeable = readingMode.value !== ReadingMode.WEBTOON && isContinuousReadingMode(readingMode.value); if (!isChangeable) { return null; } diff --git a/src/modules/reader/components/viewer/ReaderTransitionPage.tsx b/src/modules/reader/components/viewer/ReaderTransitionPage.tsx index 0095313d..f0f2be93 100644 --- a/src/modules/reader/components/viewer/ReaderTransitionPage.tsx +++ b/src/modules/reader/components/viewer/ReaderTransitionPage.tsx @@ -25,7 +25,10 @@ import { isTransitionPageVisible } from '@/modules/reader/utils/ReaderPager.util import { useBackButton } from '@/modules/core/hooks/useBackButton.ts'; import { useReaderStateMangaContext } from '@/modules/reader/contexts/state/ReaderStateMangaContext.tsx'; import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts'; -import { isContinuousReadingMode } from '@/modules/reader/utils/ReaderSettings.utils.tsx'; +import { + isContinuousReadingMode, + isContinuousVerticalReadingMode, +} from '@/modules/reader/utils/ReaderSettings.utils.tsx'; import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx'; import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; @@ -94,7 +97,7 @@ export const ReaderTransitionPage = ({ ...applyStyles(isContinuousReadingMode(readingMode), { position: 'relative', transform: 'scale(1)', - ...applyStyles(readingMode === ReadingMode.CONTINUOUS_VERTICAL, { + ...applyStyles(isContinuousVerticalReadingMode(readingMode), { maxWidth: '100%', width: '100%', ...applyStyles(!isFitWidthPageScaleMode, { alignItems: 'baseline' }), @@ -120,7 +123,7 @@ export const ReaderTransitionPage = ({ // on small screens with "fit to with" enabled, "left 50%" does not center the element in the // viewport which then causes "translate" to move the element mostly outside the viewport with // only a small part of it being visible - !isFitWidthPageScaleMode && readingMode === ReadingMode.CONTINUOUS_VERTICAL, + !isFitWidthPageScaleMode && isContinuousVerticalReadingMode(readingMode), { left: '50%', transform: 'translateX(-50%)', diff --git a/src/modules/reader/components/viewer/ReaderViewer.tsx b/src/modules/reader/components/viewer/ReaderViewer.tsx index 3ca7dbd6..3cf1587d 100644 --- a/src/modules/reader/components/viewer/ReaderViewer.tsx +++ b/src/modules/reader/components/viewer/ReaderViewer.tsx @@ -45,6 +45,7 @@ const READING_MODE_TO_IN_VIEWPORT_TYPE: Record [ReadingMode.DOUBLE_PAGE]: PageInViewportType.X, [ReadingMode.CONTINUOUS_VERTICAL]: PageInViewportType.Y, [ReadingMode.CONTINUOUS_HORIZONTAL]: PageInViewportType.X, + [ReadingMode.WEBTOON]: PageInViewportType.Y, }; export const ReaderViewer = forwardRef((_, ref: ForwardedRef) => { @@ -111,6 +112,7 @@ export const ReaderViewer = forwardRef((_, ref: ForwardedRef { const { currentPageIndex, totalPages } = props; - const { pageGap } = ReaderService.useSettings(); + const { readingMode, pageGap } = ReaderService.useSettings(); + const isWebtoonMode = readingMode.value === ReadingMode.WEBTOON; + const actualPageGap = isWebtoonMode ? 0 : pageGap; return ( , }, + [ReadingMode.WEBTOON]: { + title: 'reader.settings.reader_type.label.webtoon', + icon: , + }, } satisfies ValueToDisplayData; export const READING_MODE_VALUES = Object.values(ReadingMode).filter((value) => typeof value === 'number'); diff --git a/src/modules/reader/types/Reader.types.ts b/src/modules/reader/types/Reader.types.ts index ea3df163..d789b30e 100644 --- a/src/modules/reader/types/Reader.types.ts +++ b/src/modules/reader/types/Reader.types.ts @@ -33,6 +33,7 @@ export enum ReadingMode { DOUBLE_PAGE, CONTINUOUS_VERTICAL, CONTINUOUS_HORIZONTAL, + WEBTOON, } export enum ReaderPageScaleMode { diff --git a/src/modules/reader/utils/ReaderPager.utils.tsx b/src/modules/reader/utils/ReaderPager.utils.tsx index f2bbd77b..863ef956 100644 --- a/src/modules/reader/utils/ReaderPager.utils.tsx +++ b/src/modules/reader/utils/ReaderPager.utils.tsx @@ -17,7 +17,11 @@ import { ReadingMode, } from '@/modules/reader/types/Reader.types.ts'; import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts'; -import { isContinuousReadingMode, isReaderWidthEditable } from '@/modules/reader/utils/ReaderSettings.utils.tsx'; +import { + isContinuousReadingMode, + isContinuousVerticalReadingMode, + isReaderWidthEditable, +} from '@/modules/reader/utils/ReaderSettings.utils.tsx'; import { ReaderStatePages } from '@/modules/reader/types/ReaderProgressBar.types.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { ReaderPage } from '@/modules/reader/components/viewer/ReaderPage.tsx'; @@ -71,6 +75,10 @@ export const getImagePlaceholderStyling = ( minWidth: DEFAULT_SINGLE_PAGE_WIDTH, minHeight: `calc(${DEFAULT_SINGLE_PAGE_HEIGHT} - ${scrollbarXSize}px)`, }, + [ReadingMode.WEBTOON]: { + minWidth: `calc(${DEFAULT_SINGLE_PAGE_WIDTH} - ${scrollbarYSize}px)`, + minHeight: '100vh', + }, }; const defaultStyling = READING_MODE_TO_PLACEHOLDER_SIZE[readingMode]; const minWidthForStretch = isDoublePage ? '50%' : '100%'; @@ -91,7 +99,7 @@ export const getImagePlaceholderStyling = ( ...defaultStyling, ...applyStyles(shouldStretchPage, { minHeight: `calc(100vh - ${scrollbarXSize}px)`, - ...applyStyles(readingMode === ReadingMode.CONTINUOUS_VERTICAL, { + ...applyStyles(isContinuousVerticalReadingMode(readingMode), { minHeight: '100vh', }), }), @@ -105,7 +113,7 @@ export const getImagePlaceholderStyling = ( ...applyStyles(shouldStretchPage, { minWidth: minWidthForStretch, minHeight: `calc(100vh - ${scrollbarXSize}px)`, - ...applyStyles(readingMode === ReadingMode.CONTINUOUS_VERTICAL, { + ...applyStyles(isContinuousVerticalReadingMode(readingMode), { minHeight: '100vh', }), }), @@ -160,7 +168,7 @@ export const getImageWidthStyling = ( minWidth: 'unset', minHeight: '100%', }), - ...applyStyles(readingMode === ReadingMode.CONTINUOUS_VERTICAL, { + ...applyStyles(isContinuousVerticalReadingMode(readingMode), { minWidth: width, minHeight: 'unset', }), diff --git a/src/modules/reader/utils/ReaderSettings.utils.tsx b/src/modules/reader/utils/ReaderSettings.utils.tsx index 83f216f8..5a8c8d28 100644 --- a/src/modules/reader/utils/ReaderSettings.utils.tsx +++ b/src/modules/reader/utils/ReaderSettings.utils.tsx @@ -15,4 +15,7 @@ export const isReaderWidthEditable = (pageScaleMode: IReaderSettings['pageScaleM [ReaderPageScaleMode.WIDTH, ReaderPageScaleMode.SCREEN].includes(pageScaleMode); export const isContinuousReadingMode = (readingMode: IReaderSettings['readingMode']): boolean => - [ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.CONTINUOUS_HORIZONTAL].includes(readingMode); + [ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.CONTINUOUS_HORIZONTAL, ReadingMode.WEBTOON].includes(readingMode); + +export const isContinuousVerticalReadingMode = (readingMode: IReaderSettings['readingMode']): boolean => + [ReadingMode.CONTINUOUS_VERTICAL, ReadingMode.WEBTOON].includes(readingMode);