/* * 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 Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import DialogTitle from '@mui/material/DialogTitle'; 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 { useTranslation } from 'react-i18next'; import ListItemButton from '@mui/material/ListItemButton'; import * as React from 'react'; import ListItemIcon from '@mui/material/ListItemIcon'; import Slider from '@mui/material/Slider'; import DialogContentText from '@mui/material/DialogContentText'; import InfoIcon from '@mui/icons-material/Info'; type BaseProps = { settingTitle: string; settingValue?: string; settingIcon?: React.ReactNode; value: number; defaultValue?: number; minValue?: number; maxValue?: number; stepSize?: number; dialogTitle: string; dialogDescription?: string; dialogDisclaimer?: string; valueUnit: string; handleUpdate: (value: number) => void; showSlider?: never; disabled?: boolean; listItemTextSx?: SxProps; }; type PropsWithSlider = Omit & Required> & { showSlider: true }; type Props = BaseProps | PropsWithSlider; export const NumberSetting = ({ settingTitle, settingValue, settingIcon, dialogDescription, dialogDisclaimer, value, defaultValue, minValue, maxValue, stepSize, dialogTitle, valueUnit, handleUpdate, showSlider, disabled = false, listItemTextSx: sx, }: Props) => { const { t } = useTranslation(); const [isDialogOpen, setIsDialogOpen] = useState(false); const [dialogValue, setDialogValue] = useState(value); const closeDialog = useCallback( (resetValue: boolean) => { setIsDialogOpen(false); 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]); return ( <> setIsDialogOpen(true)}> {settingIcon ? {settingIcon} : null} {dialogTitle} {(!!dialogDescription || !!dialogDisclaimer) && ( {dialogDescription && ( {dialogDescription} )} {dialogDisclaimer && ( {dialogDisclaimer} )} )} {valueUnit}, }} autoFocus value={dialogValue} type="number" onChange={(e) => setDialogValue(Number(e.target.value))} /> {showSlider ? ( setDialogValue(newValue as number)} /> ) : null} {defaultValue !== undefined ? ( ) : null} ); };