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);