diff --git a/src/components/navbar/ReaderNavBar.tsx b/src/components/navbar/ReaderNavBar.tsx index 096bd9bb..990e4d26 100644 --- a/src/components/navbar/ReaderNavBar.tsx +++ b/src/components/navbar/ReaderNavBar.tsx @@ -118,7 +118,7 @@ const OpenDrawerButton = styled(IconButton)(({ theme }) => ({ interface IProps { settings: IReaderSettings; - setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => void; + setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist?: boolean) => void; manga: TManga; chapter: TChapter; curPage: number; @@ -150,10 +150,10 @@ export function ReaderNavBar(props: IProps) { const disableChapterNavButtons = retrievingNextChapter; - const updateSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => { + const updateSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist?: boolean) => { // prevent closing the navBar when updating the "staticNav" setting setUpdateDrawerOnRender(key !== 'staticNav'); - setSettingValue(key, value); + setSettingValue(key, value, persist); }; const updateDrawer = (open: boolean) => { diff --git a/src/components/reader/ReaderSettingsOptions.tsx b/src/components/reader/ReaderSettingsOptions.tsx index 38e82fc1..d0303f62 100644 --- a/src/components/reader/ReaderSettingsOptions.tsx +++ b/src/components/reader/ReaderSettingsOptions.tsx @@ -15,7 +15,7 @@ import { NumberSetting } from '@/components/settings/NumberSetting.tsx'; import { isHorizontalReaderType } from '@/components/reader/Page.tsx'; interface IProps extends IReaderSettings { - setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => void; + setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist?: boolean) => void; } export function ReaderSettingsOptions({ @@ -107,6 +107,7 @@ export function ReaderSettingsOptions({ valueUnit="%" showSlider handleUpdate={(width: number) => setSettingValue('readerWidth', width)} + handleLiveUpdate={(width: number) => setSettingValue('readerWidth', width, false)} listItemTextSx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }} /> )} diff --git a/src/components/settings/NumberSetting.tsx b/src/components/settings/NumberSetting.tsx index 48192976..1729f9cb 100644 --- a/src/components/settings/NumberSetting.tsx +++ b/src/components/settings/NumberSetting.tsx @@ -13,7 +13,7 @@ import TextField from '@mui/material/TextField'; import { InputAdornment, ListItemText, Stack, SxProps, Typography, Theme } from '@mui/material'; import DialogActions from '@mui/material/DialogActions'; import Button from '@mui/material/Button'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import ListItemButton from '@mui/material/ListItemButton'; import * as React from 'react'; @@ -39,6 +39,7 @@ type BaseProps = { showSlider?: never; disabled?: boolean; listItemTextSx?: SxProps; + handleLiveUpdate?: (value: number) => void; }; type PropsWithSlider = Omit & @@ -62,45 +63,49 @@ export const NumberSetting = ({ handleUpdate, showSlider, disabled = false, + handleLiveUpdate, listItemTextSx: sx, }: Props) => { const { t } = useTranslation(); const [isDialogOpen, setIsDialogOpen] = useState(false); const [dialogValue, setDialogValue] = useState(value); + const [originalValue, setOriginalValue] = useState(value); - const closeDialog = useCallback( - (resetValue: boolean) => { + const updateValue = useCallback( + (newValue: number, persist: boolean) => { + setDialogValue(newValue); + const didValueChange = newValue !== originalValue; + // Call handleUpdate if the value changed and 'persist' is true, + // otherwise call handleLiveUpdate if it's defined. + if (persist && didValueChange) { + handleUpdate(newValue); + } else if (handleLiveUpdate) { + handleLiveUpdate(newValue); + } + }, + [originalValue, setDialogValue, handleLiveUpdate, handleUpdate], + ); + + const cancel = useCallback(() => { + updateValue(originalValue, true); + setOriginalValue(originalValue); + setIsDialogOpen(false); + }, [originalValue, handleUpdate]); + + const resetToDefault = useCallback(() => { + if (defaultValue !== undefined) { + updateValue(defaultValue, true); + setOriginalValue(defaultValue); setIsDialogOpen(false); + } + }, [defaultValue, handleUpdate]); - if (resetValue) { - setDialogValue(value); - } - }, - [value], - ); - - const closeDialogWithReset = useCallback(() => closeDialog(true), [closeDialog]); - - const updateSetting = useCallback( - (newValue: number, shouldCloseDialog: boolean = true) => { - if (shouldCloseDialog) { - closeDialog(false); - } - - const didValueChange = value !== newValue; - if (!didValueChange) { - return; - } - - handleUpdate(newValue); - }, - [value, handleUpdate, closeDialog], - ); - - useEffect(() => { - setDialogValue(value); - }, [value]); + const submit = () => { + updateValue(dialogValue, true); + setOriginalValue(dialogValue); + setIsDialogOpen(false); + }; return ( <> @@ -114,7 +119,7 @@ export const NumberSetting = ({ /> - + {dialogTitle} {(!!dialogDescription || !!dialogDisclaimer) && ( @@ -158,7 +163,10 @@ export const NumberSetting = ({ autoFocus value={dialogValue} type="number" - onChange={(e) => setDialogValue(Number(e.target.value))} + onChange={(e) => { + const newValue = Number(e.target.value); + updateValue(newValue, false); + }} /> {showSlider ? ( setDialogValue(newValue as number)} + onChange={(_, newValue) => { + updateValue(newValue as number, false); + }} /> ) : null} {defaultValue !== undefined ? ( - ) : null} - - diff --git a/src/screens/Reader.tsx b/src/screens/Reader.tsx index 42588e63..7b5f1a3b 100644 --- a/src/screens/Reader.tsx +++ b/src/screens/Reader.tsx @@ -257,11 +257,13 @@ export function Reader() { .response.catch(); }; - const setSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => { + const setSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist: boolean = true) => { setSettings({ ...settings, [key]: value }); - requestUpdateMangaMetadata(manga, [[key, value]]).catch(() => - makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'), - ); + if (persist) { + requestUpdateMangaMetadata(manga, [[key, value]]).catch(() => + makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'), + ); + } }; const openNextChapter = useCallback( diff --git a/src/screens/settings/DefaultReaderSettings.tsx b/src/screens/settings/DefaultReaderSettings.tsx index de972cc7..e6667926 100644 --- a/src/screens/settings/DefaultReaderSettings.tsx +++ b/src/screens/settings/DefaultReaderSettings.tsx @@ -39,10 +39,12 @@ export function DefaultReaderSettings() { useSetDefaultBackTo('settings'); - const setSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => { - requestUpdateServerMetadata([[key, value]]).catch(() => - makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'), - ); + const setSettingValue = (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist: boolean = true) => { + if (persist) { + requestUpdateServerMetadata([[key, value]]).catch(() => + makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'), + ); + } }; if (loading) {