From 5032a0ae94d32fdf9e6d4239df9e5e448a1719cf Mon Sep 17 00:00:00 2001 From: Chance Zibolski Date: Sun, 21 Jan 2024 13:33:13 -0800 Subject: [PATCH] Make reader width configurable (#565) Signed-off-by: Chance Zibolski --- src/components/navbar/ReaderNavBar.tsx | 7 ++-- src/components/reader/Page.tsx | 19 +++++----- .../reader/ReaderSettingsOptions.tsx | 38 ++++++++++++------- src/components/settings/NumberSetting.tsx | 7 +++- src/i18n/locale/en.json | 3 +- src/screens/Reader.tsx | 12 +++++- .../settings/DefaultReaderSettings.tsx | 5 ++- src/typings.ts | 1 + src/util/readerSettings.ts | 2 + 9 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/components/navbar/ReaderNavBar.tsx b/src/components/navbar/ReaderNavBar.tsx index b3a92f42..d02bc2fd 100644 --- a/src/components/navbar/ReaderNavBar.tsx +++ b/src/components/navbar/ReaderNavBar.tsx @@ -23,7 +23,7 @@ import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import Collapse from '@mui/material/Collapse'; import { useTranslation } from 'react-i18next'; -import { ChapterOffset, IReaderSettings, TChapter, TManga } from '@/typings'; +import { AllowedMetadataValueTypes, ChapterOffset, IReaderSettings, TChapter, TManga } from '@/typings'; import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions'; const Root = styled('div')(({ theme }) => ({ @@ -112,7 +112,7 @@ const OpenDrawerButton = styled(IconButton)(({ theme }) => ({ interface IProps { settings: IReaderSettings; - setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void; + setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => void; manga: TManga; chapter: TChapter; curPage: number; @@ -141,7 +141,7 @@ export function ReaderNavBar(props: IProps) { const disableChapterNavButtons = retrievingNextChapter; - const updateSettingValue = (key: keyof IReaderSettings, value: string | boolean) => { + const updateSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => { // prevent closing the navBar when updating the "staticNav" setting setUpdateDrawerOnRender(key !== 'staticNav'); setSettingValue(key, value); @@ -269,6 +269,7 @@ export function ReaderNavBar(props: IProps) { fitPageToWindow={settings.fitPageToWindow} readerType={settings.readerType} offsetFirstPage={settings.offsetFirstPage} + readerWidth={settings.readerWidth} /> diff --git a/src/components/reader/Page.tsx b/src/components/reader/Page.tsx index d5d487c9..f02eb25f 100644 --- a/src/components/reader/Page.tsx +++ b/src/components/reader/Page.tsx @@ -8,9 +8,12 @@ import { useState, useEffect, forwardRef, useRef } from 'react'; import Box from '@mui/material/Box'; -import { IReaderSettings } from '@/typings'; +import { IReaderSettings, ReaderType } from '@/typings'; import { SpinnerImage } from '@/components/util/SpinnerImage'; +export const isFillsPageReaderType = (readerType: ReaderType): boolean => + ['DoubleRTL', 'DoubleLTR', 'ContinuesHorizontalLTR', 'ContinuesHorizontalRTL'].includes(readerType); + function imageStyle(settings: IReaderSettings): any { const [dimensions, setDimensions] = useState({ height: window.innerHeight, @@ -29,13 +32,7 @@ function imageStyle(settings: IReaderSettings): any { window.removeEventListener('resize', handleResize); }; }, []); - if ( - settings.fitPageToWindow || - settings.readerType === 'DoubleLTR' || - settings.readerType === 'DoubleRTL' || - settings.readerType === 'ContinuesHorizontalLTR' || - settings.readerType === 'ContinuesHorizontalRTL' - ) { + if (settings.fitPageToWindow || isFillsPageReaderType(settings.readerType)) { return { display: 'block', marginLeft: '7px', @@ -51,9 +48,11 @@ function imageStyle(settings: IReaderSettings): any { return { display: 'block', marginBottom: settings.readerType === 'ContinuesVertical' ? '15px' : 0, - minWidth: '50vw', - width: dimensions.width < dimensions.height ? '100vw' : '100%', + minWidth: '10vw', + width: dimensions.width < dimensions.height ? '100vw' : `${settings.readerWidth}%`, maxWidth: '100%', + marginLeft: 'auto', + marginRight: 'auto', }; } diff --git a/src/components/reader/ReaderSettingsOptions.tsx b/src/components/reader/ReaderSettingsOptions.tsx index f738c92d..9c7cd232 100644 --- a/src/components/reader/ReaderSettingsOptions.tsx +++ b/src/components/reader/ReaderSettingsOptions.tsx @@ -10,10 +10,12 @@ import { List, ListItem, ListItemText, Switch } from '@mui/material'; import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { useTranslation } from 'react-i18next'; -import { IReaderSettings } from '@/typings'; +import { AllowedMetadataValueTypes, IReaderSettings } from '@/typings'; +import { NumberSetting } from '@/components/settings/NumberSetting.tsx'; +import { isFillsPageReaderType } from '@/components/reader/Page.tsx'; interface IProps extends IReaderSettings { - setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void; + setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => void; } export function ReaderSettingsOptions({ @@ -25,15 +27,10 @@ export function ReaderSettingsOptions({ setSettingValue, fitPageToWindow, offsetFirstPage, + readerWidth, }: IProps) { const { t } = useTranslation(); - const fitPageToWindowEligible = [ - 'ContinuesVertical', - 'Webtoon', - 'SingleVertical', - 'SingleRTL', - 'SingleLTR', - ].includes(readerType); + const fitPageToWindowEligible = !isFillsPageReaderType(readerType); return ( @@ -68,7 +65,7 @@ export function ReaderSettingsOptions({ onChange={(e) => setSettingValue('skipDupChapters', e.target.checked)} /> - {fitPageToWindowEligible ? ( + {fitPageToWindowEligible && ( setSettingValue('fitPageToWindow', e.target.checked)} /> - ) : null} - {readerType === 'DoubleLTR' || readerType === 'DoubleRTL' ? ( + )} + {(readerType === 'DoubleLTR' || readerType === 'DoubleRTL') && ( setSettingValue('offsetFirstPage', e.target.checked)} /> - ) : null} + )} + {fitPageToWindowEligible && !fitPageToWindow && ( + setSettingValue('readerWidth', width)} + listItemTextSx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }} + /> + )}