Reader settings
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 Stack from '@mui/material/Stack';
|
||||
import { ContextType } from 'react';
|
||||
import { ReaderSettingReadingMode } from '@/modules/reader/components/settings/layout/ReaderSettingReadingMode.tsx';
|
||||
import { ReaderSettingReadingDirection } from '@/modules/reader/components/settings/layout/ReaderSettingReadingDirection.tsx';
|
||||
import { ReaderSettingTapZoneLayout } from '@/modules/reader/components/settings/layout/ReaderSettingTapZoneLayout.tsx';
|
||||
import { ReaderTapZoneContext } from '@/modules/reader/contexts/ReaderTapZoneContext.tsx';
|
||||
import { ReaderSettingTapZoneInvertMode } from '@/modules/reader/components/settings/layout/ReaderSettingTapZoneInvertMode.tsx';
|
||||
import { ReaderSettingPageScaleMode } from '@/modules/reader/components/settings/layout/ReaderSettingPageScaleMode.tsx';
|
||||
import { ReaderSettingStretchPage } from '@/modules/reader/components/settings/layout/ReaderSettingStretchPage.tsx';
|
||||
import { ReaderSettingsTypeProps } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { ReaderSettingPageGap } from '@/modules/reader/components/settings/layout/ReaderSettingPageGap.tsx';
|
||||
import { ReaderSettingWidth } from '@/modules/reader/components/settings/layout/ReaderSettingWidth.tsx';
|
||||
|
||||
export const ReaderLayoutSettings = ({
|
||||
setShowPreview,
|
||||
settings,
|
||||
updateSetting,
|
||||
isDefaultable,
|
||||
onDefault,
|
||||
}: ReaderSettingsTypeProps & {
|
||||
setShowPreview: ContextType<typeof ReaderTapZoneContext>['setShowPreview'];
|
||||
}) => (
|
||||
<Stack sx={{ gap: 2 }}>
|
||||
<ReaderSettingReadingMode
|
||||
readingMode={settings.readingMode}
|
||||
setReadingMode={(value) => updateSetting('readingMode', value)}
|
||||
isDefaultable={isDefaultable}
|
||||
onDefault={() => onDefault?.('readingMode')}
|
||||
/>
|
||||
<ReaderSettingPageGap
|
||||
pageGap={settings.pageGap}
|
||||
readingMode={settings.readingMode}
|
||||
updateSetting={(...args) => updateSetting('pageGap', ...args)}
|
||||
/>
|
||||
<ReaderSettingReadingDirection
|
||||
readingDirection={settings.readingDirection}
|
||||
setReadingDirection={(value) => updateSetting('readingDirection', value)}
|
||||
isDefaultable={isDefaultable}
|
||||
onDefault={() => onDefault?.('readingDirection')}
|
||||
/>
|
||||
<ReaderSettingTapZoneLayout
|
||||
tapZoneLayout={settings.tapZoneLayout}
|
||||
setTapZoneLayout={(value) => {
|
||||
setShowPreview(true);
|
||||
updateSetting('tapZoneLayout', value);
|
||||
}}
|
||||
isDefaultable={isDefaultable}
|
||||
onDefault={() => {
|
||||
setShowPreview(true);
|
||||
onDefault?.('tapZoneLayout');
|
||||
}}
|
||||
/>
|
||||
<ReaderSettingTapZoneInvertMode
|
||||
tapZoneInvertMode={settings.tapZoneInvertMode}
|
||||
setTapZoneInvertMode={(value) => {
|
||||
setShowPreview(true);
|
||||
updateSetting('tapZoneInvertMode', value);
|
||||
}}
|
||||
isDefaultable={isDefaultable}
|
||||
onDefault={() => {
|
||||
setShowPreview(true);
|
||||
onDefault?.('tapZoneInvertMode');
|
||||
}}
|
||||
/>
|
||||
<ReaderSettingPageScaleMode
|
||||
pageScaleMode={settings.pageScaleMode}
|
||||
setPageScaleMode={(value) => updateSetting('pageScaleMode', value)}
|
||||
isDefaultable={isDefaultable}
|
||||
onDefault={() => onDefault?.('pageScaleMode')}
|
||||
/>
|
||||
<ReaderSettingStretchPage
|
||||
pageScaleMode={settings.pageScaleMode.value}
|
||||
shouldStretchPage={settings.shouldStretchPage.value}
|
||||
setShouldStretchPage={(value) => updateSetting('shouldStretchPage', value)}
|
||||
/>
|
||||
<ReaderSettingWidth
|
||||
readerWidth={settings.readerWidth.value}
|
||||
pageScaleMode={settings.pageScaleMode.value}
|
||||
updateSetting={(...args) => updateSetting(...args)}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 Stack from '@mui/material/Stack';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IReaderSettingsWithDefaultFlag, ReadingMode } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { SliderInput } from '@/modules/core/components/inputs/SliderInput.tsx';
|
||||
import { DEFAULT_READER_SETTINGS } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
|
||||
|
||||
export const ReaderSettingPageGap = ({
|
||||
pageGap,
|
||||
readingMode,
|
||||
updateSetting,
|
||||
}: Pick<IReaderSettingsWithDefaultFlag, 'pageGap' | 'readingMode'> & {
|
||||
updateSetting: (gap: number, commit: boolean) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
{[ReadingMode.CONTINUOUS_HORIZONTAL, ReadingMode.CONTINUOUS_VERTICAL].includes(readingMode.value) && (
|
||||
<SliderInput
|
||||
label={t('reader.settings.label.page_gap')}
|
||||
value={t('global.value', { value: pageGap.value, unit: t('global.unit.px') })}
|
||||
slotProps={{
|
||||
slider: {
|
||||
defaultValue: DEFAULT_READER_SETTINGS.readerWidth.value,
|
||||
value: pageGap.value,
|
||||
step: 1,
|
||||
min: 0,
|
||||
max: 20,
|
||||
onChange: (_, value) => {
|
||||
updateSetting(value as number, false);
|
||||
},
|
||||
onChangeCommitted: (_, value) => {
|
||||
updateSetting(value as number, true);
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
IReaderSettings,
|
||||
IReaderSettingsWithDefaultFlag,
|
||||
ReadingDirection,
|
||||
} from '@/modules/reader/types/Reader.types.ts';
|
||||
import {
|
||||
PAGE_SCALE_VALUE_TO_DISPLAY_DATA,
|
||||
READER_PAGE_SCALE_MODE_VALUES,
|
||||
} from '@/modules/reader/constants/ReaderSettings.constants.tsx';
|
||||
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
||||
import { MultiValueButtonDefaultableProps } from '@/modules/core/Core.types.ts';
|
||||
|
||||
export const ReaderSettingPageScaleMode = ({
|
||||
pageScaleMode,
|
||||
setPageScaleMode,
|
||||
...buttonSelectInputProps
|
||||
}: Pick<IReaderSettingsWithDefaultFlag, 'pageScaleMode'> &
|
||||
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
|
||||
setPageScaleMode: (mode: IReaderSettings['pageScaleMode']) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ButtonSelectInput
|
||||
{...buttonSelectInputProps}
|
||||
label={t('reader.settings.page_scale.title')}
|
||||
value={pageScaleMode.isDefault ? undefined : pageScaleMode.value}
|
||||
values={READER_PAGE_SCALE_MODE_VALUES}
|
||||
setValue={setPageScaleMode}
|
||||
valueToDisplayData={PAGE_SCALE_VALUE_TO_DISPLAY_DATA}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 ArrowCircleLeftIcon from '@mui/icons-material/ArrowCircleLeft';
|
||||
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IReaderSettingsWithDefaultFlag, ReadingDirection } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { MultiValueButtonDefaultableProps, ValueToDisplayData } from '@/modules/core/Core.types.ts';
|
||||
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
||||
|
||||
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReadingDirection> = {
|
||||
[ReadingDirection.LTR]: {
|
||||
title: 'reader.settings.reading_direction.ltr',
|
||||
icon: <ArrowCircleRightIcon />,
|
||||
},
|
||||
[ReadingDirection.RTL]: {
|
||||
title: 'reader.settings.reading_direction.rtl',
|
||||
icon: <ArrowCircleLeftIcon />,
|
||||
},
|
||||
};
|
||||
|
||||
const READING_DIRECTION_VALUES = Object.values(ReadingDirection).filter((value) => typeof value === 'number');
|
||||
|
||||
export const ReaderSettingReadingDirection = ({
|
||||
readingDirection,
|
||||
setReadingDirection,
|
||||
...buttonSelectInputProps
|
||||
}: Pick<IReaderSettingsWithDefaultFlag, 'readingDirection'> &
|
||||
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
|
||||
setReadingDirection: (readingDirection: ReadingDirection) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ButtonSelectInput
|
||||
{...buttonSelectInputProps}
|
||||
label={t('reader.settings.label.reading_direction')}
|
||||
value={readingDirection.isDefault ? undefined : readingDirection.value}
|
||||
values={READING_DIRECTION_VALUES}
|
||||
setValue={setReadingDirection}
|
||||
valueToDisplayData={VALUE_TO_DISPLAY_DATA}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 { useTranslation } from 'react-i18next';
|
||||
import { IReaderSettingsWithDefaultFlag, ReadingMode } from '@/modules/reader/types/Reader.types.ts';
|
||||
import {
|
||||
READING_MODE_VALUE_TO_DISPLAY_DATA,
|
||||
READING_MODE_VALUES,
|
||||
} from '@/modules/reader/constants/ReaderSettings.constants.tsx';
|
||||
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
||||
import { MultiValueButtonDefaultableProps } from '@/modules/core/Core.types.ts';
|
||||
|
||||
export const ReaderSettingReadingMode = ({
|
||||
readingMode,
|
||||
setReadingMode,
|
||||
...buttonSelectInputProps
|
||||
}: Pick<IReaderSettingsWithDefaultFlag, 'readingMode'> &
|
||||
Pick<MultiValueButtonDefaultableProps<ReadingMode>, 'isDefaultable' | 'onDefault'> & {
|
||||
setReadingMode: (mode: ReadingMode) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ButtonSelectInput
|
||||
{...buttonSelectInputProps}
|
||||
label={t('reader.settings.label.reading_mode')}
|
||||
value={readingMode.isDefault ? undefined : readingMode.value}
|
||||
values={READING_MODE_VALUES}
|
||||
setValue={setReadingMode}
|
||||
valueToDisplayData={READING_MODE_VALUE_TO_DISPLAY_DATA}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 { useTranslation } from 'react-i18next';
|
||||
import Button from '@mui/material/Button';
|
||||
import Box from '@mui/material/Box';
|
||||
import { IReaderSettings } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { READER_PAGE_SCALE_MODE_TO_SCALING_ALLOWED } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
|
||||
|
||||
export const ReaderSettingStretchPage = ({
|
||||
pageScaleMode,
|
||||
shouldStretchPage,
|
||||
setShouldStretchPage,
|
||||
}: Pick<IReaderSettings, 'pageScaleMode' | 'shouldStretchPage'> & {
|
||||
setShouldStretchPage: (mode: IReaderSettings['shouldStretchPage']) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!READER_PAGE_SCALE_MODE_TO_SCALING_ALLOWED[pageScaleMode]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Button
|
||||
onClick={() => setShouldStretchPage(!shouldStretchPage)}
|
||||
variant={shouldStretchPage ? 'contained' : 'outlined'}
|
||||
>
|
||||
{t('reader.settings.page_scale.stretch')}
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 { useTranslation } from 'react-i18next';
|
||||
import { MultiValueButtonDefaultableProps, ValueToDisplayData } from '@/modules/core/Core.types.ts';
|
||||
import {
|
||||
IReaderSettings,
|
||||
IReaderSettingsWithDefaultFlag,
|
||||
ReadingDirection,
|
||||
} from '@/modules/reader/types/Reader.types.ts';
|
||||
import { TapZoneInvertMode } from '@/modules/reader/types/TapZoneLayout.types.ts';
|
||||
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
||||
|
||||
enum TapZonesInvertOption {
|
||||
NONE,
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
BOTH,
|
||||
}
|
||||
|
||||
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<TapZonesInvertOption> = {
|
||||
[TapZonesInvertOption.NONE]: {
|
||||
title: 'global.label.none',
|
||||
icon: null,
|
||||
},
|
||||
[TapZonesInvertOption.HORIZONTAL]: {
|
||||
title: 'global.label.horizontal',
|
||||
icon: null,
|
||||
},
|
||||
[TapZonesInvertOption.VERTICAL]: {
|
||||
title: 'global.label.vertical',
|
||||
icon: null,
|
||||
},
|
||||
[TapZonesInvertOption.BOTH]: {
|
||||
title: 'global.label.both',
|
||||
icon: null,
|
||||
},
|
||||
};
|
||||
|
||||
const TAP_ZONES_INVERT_OPTION_VALUES = Object.values(TapZonesInvertOption).filter((value) => typeof value === 'number');
|
||||
|
||||
const TAP_ZONES_INVERT_OPTION_TO_SETTING: Record<TapZonesInvertOption, TapZoneInvertMode> = {
|
||||
[TapZonesInvertOption.NONE]: {
|
||||
vertical: false,
|
||||
horizontal: false,
|
||||
},
|
||||
[TapZonesInvertOption.HORIZONTAL]: {
|
||||
vertical: false,
|
||||
horizontal: true,
|
||||
},
|
||||
[TapZonesInvertOption.VERTICAL]: {
|
||||
vertical: true,
|
||||
horizontal: false,
|
||||
},
|
||||
[TapZonesInvertOption.BOTH]: {
|
||||
vertical: true,
|
||||
horizontal: true,
|
||||
},
|
||||
};
|
||||
|
||||
const convertTapZoneInvertModeToOption = ({ vertical, horizontal }: TapZoneInvertMode): TapZonesInvertOption => {
|
||||
if (vertical && horizontal) {
|
||||
return TapZonesInvertOption.BOTH;
|
||||
}
|
||||
|
||||
if (vertical) {
|
||||
return TapZonesInvertOption.VERTICAL;
|
||||
}
|
||||
|
||||
if (horizontal) {
|
||||
return TapZonesInvertOption.HORIZONTAL;
|
||||
}
|
||||
|
||||
return TapZonesInvertOption.NONE;
|
||||
};
|
||||
|
||||
export const ReaderSettingTapZoneInvertMode = ({
|
||||
tapZoneInvertMode,
|
||||
setTapZoneInvertMode,
|
||||
...buttonSelectInputProps
|
||||
}: Pick<IReaderSettingsWithDefaultFlag, 'tapZoneInvertMode'> &
|
||||
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
|
||||
setTapZoneInvertMode: (invert: IReaderSettings['tapZoneInvertMode']) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ButtonSelectInput
|
||||
{...buttonSelectInputProps}
|
||||
label={t('reader.settings.tap_zones.invert')}
|
||||
value={tapZoneInvertMode.isDefault ? undefined : convertTapZoneInvertModeToOption(tapZoneInvertMode.value)}
|
||||
values={TAP_ZONES_INVERT_OPTION_VALUES}
|
||||
setValue={(value) => setTapZoneInvertMode(TAP_ZONES_INVERT_OPTION_TO_SETTING[value])}
|
||||
valueToDisplayData={VALUE_TO_DISPLAY_DATA}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -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 { useTranslation } from 'react-i18next';
|
||||
import { TapZoneLayouts } from '@/modules/reader/types/TapZoneLayout.types.ts';
|
||||
import { MultiValueButtonDefaultableProps, ValueToDisplayData } from '@/modules/core/Core.types.ts';
|
||||
import { IReaderSettingsWithDefaultFlag, ReadingDirection } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
||||
|
||||
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<TapZoneLayouts> = {
|
||||
[TapZoneLayouts.EDGE]: {
|
||||
title: 'reader.settings.tap_zones.edge',
|
||||
icon: null,
|
||||
},
|
||||
[TapZoneLayouts.KINDLE]: {
|
||||
title: 'reader.settings.tap_zones.kindle',
|
||||
icon: null,
|
||||
},
|
||||
[TapZoneLayouts.L_SHAPE]: {
|
||||
title: 'reader.settings.tap_zones.l_shape',
|
||||
icon: null,
|
||||
},
|
||||
[TapZoneLayouts.RIGHT_LEFT]: {
|
||||
title: 'reader.settings.tap_zones.right_left',
|
||||
icon: null,
|
||||
},
|
||||
};
|
||||
|
||||
const READER_TAP_ZONE_LAYOUT_VALUES = Object.values(TapZoneLayouts).filter((value) => typeof value === 'number');
|
||||
|
||||
export const ReaderSettingTapZoneLayout = ({
|
||||
tapZoneLayout,
|
||||
setTapZoneLayout,
|
||||
...buttonSelectInputProps
|
||||
}: Pick<IReaderSettingsWithDefaultFlag, 'tapZoneLayout'> &
|
||||
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
|
||||
setTapZoneLayout: (layout: TapZoneLayouts) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ButtonSelectInput
|
||||
{...buttonSelectInputProps}
|
||||
label={t('reader.settings.tap_zones.title')}
|
||||
value={tapZoneLayout.isDefault ? undefined : tapZoneLayout.value}
|
||||
values={READER_TAP_ZONE_LAYOUT_VALUES}
|
||||
setValue={setTapZoneLayout}
|
||||
valueToDisplayData={VALUE_TO_DISPLAY_DATA}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 Stack from '@mui/material/Stack';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IReaderSettings } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { CheckboxInput } from '@/modules/core/components/inputs/CheckboxInput.tsx';
|
||||
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
||||
import { SliderInput } from '@/modules/core/components/inputs/SliderInput.tsx';
|
||||
import { DEFAULT_READER_SETTINGS } from '@/modules/reader/constants/ReaderSettings.constants.tsx';
|
||||
import { isReaderWidthEditable } from '@/modules/reader/utils/ReaderSettings.utils.tsx';
|
||||
|
||||
export const ReaderSettingWidth = ({
|
||||
readerWidth,
|
||||
pageScaleMode,
|
||||
updateSetting,
|
||||
}: Pick<IReaderSettings, 'readerWidth' | 'pageScaleMode'> & {
|
||||
updateSetting: (...args: OmitFirst<Parameters<typeof ReaderService.updateSetting>>) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!isReaderWidthEditable(pageScaleMode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<CheckboxInput
|
||||
label={t('reader.settings.label.limit_reader_width')}
|
||||
checked={readerWidth.enabled}
|
||||
onChange={(_, checked) => updateSetting('readerWidth', { ...readerWidth, enabled: checked }, true)}
|
||||
/>
|
||||
{readerWidth.enabled && (
|
||||
<SliderInput
|
||||
label={t('reader.settings.label.reader_width')}
|
||||
value={t('global.value', { value: readerWidth.value, unit: '%' })}
|
||||
slotProps={{
|
||||
slider: {
|
||||
defaultValue: DEFAULT_READER_SETTINGS.readerWidth.value,
|
||||
value: readerWidth.value,
|
||||
step: 1,
|
||||
min: 10,
|
||||
max: 100,
|
||||
onChange: (_, value) => {
|
||||
updateSetting('readerWidth', { ...readerWidth, value: value as number }, false);
|
||||
},
|
||||
onChangeCommitted: (_, value) => {
|
||||
updateSetting('readerWidth', { ...readerWidth, value: value as number }, true);
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user