diff --git a/public/locales/en.json b/public/locales/en.json index 9a9ad724..860574e8 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -217,7 +217,7 @@ "call_timeout": "Call timeout", "compression_level": "Compression level", "connect_timeout": "Connect timeout", - "description": "In case no MIME-Type is defined, the \"default\" one will be used for the conversion.\nSet \"{{value}}\" as the target type to disable conversion for a MIME-Type", + "description": "In case no MIME-Type is defined, the \"default\" one will be used for the processing.\nSet \"{{value}}\" as the target type to disable processing for a MIME-Type", "headers": { "button": "Headers ({{count}})", "name": "Name", @@ -237,7 +237,7 @@ "title": "URL" } }, - "title": "Download conversion" + "title": "Downloaded image processing" }, "delete_chapters": { "label": { @@ -1320,6 +1320,12 @@ "device": "Device" } }, + "images": { + "processing": { + "title": "Image processing" + }, + "title": "Images" + }, "label": { "hide_library_entries": "Hide entries already in library", "language_description": "Feel free to translate the project on", diff --git a/src/App.tsx b/src/App.tsx index 2cfaa842..cf2ffd8f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -60,8 +60,9 @@ const { DownloadSettings } = loadable( () => import('@/features/downloads/screens/DownloadSettings.tsx'), lazyLoadFallback, ); -const { DownloadConversionSettings } = loadable( - () => import('@/features/downloads/screens/DownloadConversionSettings.tsx'), +const { ImagesSettings } = loadable(() => import('@/features/settings/screens/ImagesSettings.tsx'), lazyLoadFallback); +const { ImageProcessingSetting } = loadable( + () => import('@/features/settings/screens/ImageProcessingSetting.tsx'), lazyLoadFallback, ); const { ServerSettings } = loadable(() => import('@/features/settings/screens/ServerSettings.tsx'), lazyLoadFallback); @@ -227,9 +228,25 @@ const MainApp = () => { } /> + {/* TODO: deprecated - got moved to "settings/images/processing/downloads" */} } + element={ + + } + /> + + + } /> + } /> } /> @@ -255,6 +272,7 @@ const MainApp = () => { } /> + {/* TODO: deprecated - "source" and "extension" page got merged into "browse" */} } diff --git a/src/base/AppRoute.constants.ts b/src/base/AppRoute.constants.ts index 57a1a8e3..adbd42dc 100644 --- a/src/base/AppRoute.constants.ts +++ b/src/base/AppRoute.constants.ts @@ -70,12 +70,23 @@ export const AppRoutes = { match: 'download', path: '/settings/download', childRoutes: { + // TODO: deprecated - got moved to "settings/images/processing/downloads" conversions: { match: 'conversions', path: '/settings/download/conversions', }, }, }, + images: { + match: 'images', + path: '/settings/images', + childRoutes: { + processingDownloads: { + match: 'processing/downloads', + path: '/settings/images/processing/downloads', + }, + }, + }, backup: { match: 'backup', path: '/settings/backup', diff --git a/src/features/downloads/Downloads.constants.ts b/src/features/downloads/Downloads.constants.ts index e7cc16ee..d1f10059 100644 --- a/src/features/downloads/Downloads.constants.ts +++ b/src/features/downloads/Downloads.constants.ts @@ -6,29 +6,9 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { d } from 'koration'; - export const DOWNLOAD_AHEAD = { min: 2, max: 10, default: 2, step: 1, }; - -export const DOWNLOAD_CONVERSION_COMPRESSION = { - min: 0, - max: 1, - step: 0.01, -}; - -export const IMAGE_CONVERSION_CALL_TIMEOUT = { - min: d(10).seconds.inWholeSeconds, - max: d(10).minutes.inWholeSeconds, - step: d(10).seconds.inWholeSeconds, -}; - -export const IMAGE_CONVERSION_CONNECT_TIMEOUT = { - min: d(10).seconds.inWholeSeconds, - max: d(10).minutes.inWholeSeconds, - step: d(10).seconds.inWholeSeconds, -}; diff --git a/src/features/downloads/screens/DownloadConversionSettings.tsx b/src/features/downloads/screens/DownloadConversionSettings.tsx deleted file mode 100644 index 9942bad1..00000000 --- a/src/features/downloads/screens/DownloadConversionSettings.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts'; -import { requestManager } from '@/lib/requests/RequestManager.ts'; -import { getErrorMessage } from '@/lib/HelperFunctions.ts'; -import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx'; -import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx'; -import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { DownloadConversionSetting } from '@/features/downloads/components/DownloadConversionSetting.tsx'; -import { makeToast } from '@/base/utils/Toast.ts'; -import { ServerSettings } from '@/features/settings/Settings.types.ts'; - -export const DownloadConversionSettings = () => { - const { t } = useTranslation(); - - useAppTitle(t('download.title.download')); - - const { data, loading, error, refetch } = requestManager.useGetServerSettings({ - notifyOnNetworkStatusChange: true, - }); - const [mutateSettings] = requestManager.useUpdateServerSettings(); - - const updateSetting = (value: ServerSettings['downloadConversions']): Promise => { - const mutation = mutateSettings({ variables: { input: { settings: { downloadConversions: value } } } }); - mutation.catch((e) => makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e))); - - return mutation; - }; - - if (loading) { - return ; - } - - if (error) { - return ( - refetch().catch(defaultPromiseErrorHandler('DownloadConversionSetting::refetch'))} - /> - ); - } - - return ; -}; diff --git a/src/features/downloads/screens/DownloadSettings.tsx b/src/features/downloads/screens/DownloadSettings.tsx index 60293732..e6ffcf0b 100644 --- a/src/features/downloads/screens/DownloadSettings.tsx +++ b/src/features/downloads/screens/DownloadSettings.tsx @@ -129,7 +129,7 @@ export const DownloadSettings = () => { onChange={(e) => updateSetting('downloadAsCbz', e.target.checked)} /> - + isValidNumberSetting( timeout ? d(timeout).seconds.inWholeSeconds : null, - IMAGE_CONVERSION_CALL_TIMEOUT.min, - IMAGE_CONVERSION_CALL_TIMEOUT.max, + IMAGE_PROCESSING_CALL_TIMEOUT.min, + IMAGE_PROCESSING_CALL_TIMEOUT.max, ); const isValidConnectTimeoutSetting = (timeout: string | null | undefined): boolean => isValidNumberSetting( timeout ? d(timeout).seconds.inWholeSeconds : null, - IMAGE_CONVERSION_CONNECT_TIMEOUT.min, - IMAGE_CONVERSION_CONNECT_TIMEOUT.max, + IMAGE_PROCESSING_CONNECT_TIMEOUT.min, + IMAGE_PROCESSING_CONNECT_TIMEOUT.max, ); const isValidCompressionLevel = (compression: number | null | undefined): boolean => - isValidNumberSetting(compression, DOWNLOAD_CONVERSION_COMPRESSION.min, DOWNLOAD_CONVERSION_COMPRESSION.max); + isValidNumberSetting(compression, IMAGE_PROCESSING_COMPRESSION.min, IMAGE_PROCESSING_COMPRESSION.max); const isUnsetConversion = (mimeType: string, target: string): boolean => mimeType === '' && target === ''; @@ -521,7 +530,7 @@ const Conversion = ({ helperText={!isCompressionLevelValid ? t('global.error.label.invalid_input') : ''} slotProps={{ input: { - inputProps: DOWNLOAD_CONVERSION_COMPRESSION, + inputProps: IMAGE_PROCESSING_COMPRESSION, }, }} onChange={(e) => { @@ -542,7 +551,7 @@ const Conversion = ({ helperText={!isCallTimeoutValid ? t('global.error.label.invalid_input') : ''} slotProps={{ input: { - inputProps: IMAGE_CONVERSION_CALL_TIMEOUT, + inputProps: IMAGE_PROCESSING_CALL_TIMEOUT, endAdornment: ( {t('global.date.label.second_other')} @@ -568,7 +577,7 @@ const Conversion = ({ helperText={!isConnectTimeoutValid ? t('global.error.label.invalid_input') : ''} slotProps={{ input: { - inputProps: IMAGE_CONVERSION_CONNECT_TIMEOUT, + inputProps: IMAGE_PROCESSING_CONNECT_TIMEOUT, endAdornment: ( {t('global.date.label.second_other')} @@ -622,15 +631,34 @@ const Conversion = ({ ); }; -export const DownloadConversionSetting = ({ - conversions, - updateSetting, -}: { - conversions: SettingsDownloadConversion[]; - updateSetting: (conversions: SettingsDownloadConversion[]) => Promise; -}) => { +export const ImageProcessingSetting = () => { const { t } = useTranslation(); + useAppTitle(t('download.settings.conversion.title')); + + const { data, loading, error, refetch } = requestManager.useGetServerSettings({ + notifyOnNetworkStatusChange: true, + }); + const [mutateSettings] = requestManager.useUpdateServerSettings(); + + if (loading) { + return ; + } + + if (error) { + return ( + refetch().catch(defaultPromiseErrorHandler('DownloadConversionSetting::refetch'))} + /> + ); + } + + assertIsDefined(data?.settings?.downloadConversions); + + const conversions = data?.settings?.downloadConversions; + const [tmpConversions, setTmpConversions] = useState( normalizeConversions(maybeAddDefault(addStableIdToConversions(conversions))), ); @@ -641,6 +669,13 @@ export const DownloadConversionSetting = ({ tmpConversions, ); + const updateSetting = (value: ServerSettings['downloadConversions']): Promise => { + const mutation = mutateSettings({ variables: { input: { settings: { downloadConversions: value } } } }); + mutation.catch((e) => makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e))); + + return mutation; + }; + const onSubmit = async () => { try { await updateSetting(toValidServerConversions(tmpConversions)); diff --git a/src/features/settings/screens/ImagesSettings.tsx b/src/features/settings/screens/ImagesSettings.tsx new file mode 100644 index 00000000..5f16985c --- /dev/null +++ b/src/features/settings/screens/ImagesSettings.tsx @@ -0,0 +1,36 @@ +/* + * 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 List from '@mui/material/List'; +import ListItemText from '@mui/material/ListItemText'; +import ListSubheader from '@mui/material/ListSubheader'; +import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts'; +import { ListItemLink } from '@/base/components/lists/ListItemLink.tsx'; +import { AppRoutes } from '@/base/AppRoute.constants.ts'; + +export const ImagesSettings = () => { + const { t } = useTranslation(); + + useAppTitle(t('settings.images.title')); + + return ( + + {t('settings.images.processing.title')} + + } + > + + + + + ); +}; diff --git a/src/features/settings/screens/Settings.tsx b/src/features/settings/screens/Settings.tsx index a59a5902..daf0eedb 100644 --- a/src/features/settings/screens/Settings.tsx +++ b/src/features/settings/screens/Settings.tsx @@ -23,6 +23,7 @@ import DevicesIcon from '@mui/icons-material/Devices'; import SyncIcon from '@mui/icons-material/Sync'; import PaletteIcon from '@mui/icons-material/Palette'; import HistoryIcon from '@mui/icons-material/History'; +import ImageIcon from '@mui/icons-material/Image'; import { ListItemLink } from '@/base/components/lists/ListItemLink.tsx'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { makeToast } from '@/base/utils/Toast.ts'; @@ -73,6 +74,12 @@ export function Settings() { + + + + + +