Add "images" settings page
This commit is contained in:
@@ -217,7 +217,7 @@
|
|||||||
"call_timeout": "Call timeout",
|
"call_timeout": "Call timeout",
|
||||||
"compression_level": "Compression level",
|
"compression_level": "Compression level",
|
||||||
"connect_timeout": "Connect timeout",
|
"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": {
|
"headers": {
|
||||||
"button": "Headers ({{count}})",
|
"button": "Headers ({{count}})",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
"title": "URL"
|
"title": "URL"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"title": "Download conversion"
|
"title": "Downloaded image processing"
|
||||||
},
|
},
|
||||||
"delete_chapters": {
|
"delete_chapters": {
|
||||||
"label": {
|
"label": {
|
||||||
@@ -1320,6 +1320,12 @@
|
|||||||
"device": "Device"
|
"device": "Device"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"images": {
|
||||||
|
"processing": {
|
||||||
|
"title": "Image processing"
|
||||||
|
},
|
||||||
|
"title": "Images"
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"hide_library_entries": "Hide entries already in library",
|
"hide_library_entries": "Hide entries already in library",
|
||||||
"language_description": "Feel free to translate the project on",
|
"language_description": "Feel free to translate the project on",
|
||||||
|
|||||||
24
src/App.tsx
24
src/App.tsx
@@ -60,8 +60,9 @@ const { DownloadSettings } = loadable(
|
|||||||
() => import('@/features/downloads/screens/DownloadSettings.tsx'),
|
() => import('@/features/downloads/screens/DownloadSettings.tsx'),
|
||||||
lazyLoadFallback,
|
lazyLoadFallback,
|
||||||
);
|
);
|
||||||
const { DownloadConversionSettings } = loadable(
|
const { ImagesSettings } = loadable(() => import('@/features/settings/screens/ImagesSettings.tsx'), lazyLoadFallback);
|
||||||
() => import('@/features/downloads/screens/DownloadConversionSettings.tsx'),
|
const { ImageProcessingSetting } = loadable(
|
||||||
|
() => import('@/features/settings/screens/ImageProcessingSetting.tsx'),
|
||||||
lazyLoadFallback,
|
lazyLoadFallback,
|
||||||
);
|
);
|
||||||
const { ServerSettings } = loadable(() => import('@/features/settings/screens/ServerSettings.tsx'), lazyLoadFallback);
|
const { ServerSettings } = loadable(() => import('@/features/settings/screens/ServerSettings.tsx'), lazyLoadFallback);
|
||||||
@@ -227,9 +228,25 @@ const MainApp = () => {
|
|||||||
</Route>
|
</Route>
|
||||||
<Route path={AppRoutes.settings.childRoutes.download.match}>
|
<Route path={AppRoutes.settings.childRoutes.download.match}>
|
||||||
<Route index element={<DownloadSettings />} />
|
<Route index element={<DownloadSettings />} />
|
||||||
|
{/* TODO: deprecated - got moved to "settings/images/processing/downloads" */}
|
||||||
<Route
|
<Route
|
||||||
path={AppRoutes.settings.childRoutes.download.childRoutes.conversions.match}
|
path={AppRoutes.settings.childRoutes.download.childRoutes.conversions.match}
|
||||||
element={<DownloadConversionSettings />}
|
element={
|
||||||
|
<Navigate
|
||||||
|
to={
|
||||||
|
AppRoutes.settings.childRoutes.images.childRoutes.processingDownloads
|
||||||
|
.path
|
||||||
|
}
|
||||||
|
replace
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
<Route path={AppRoutes.settings.childRoutes.images.match}>
|
||||||
|
<Route index element={<ImagesSettings />} />
|
||||||
|
<Route
|
||||||
|
path={AppRoutes.settings.childRoutes.images.childRoutes.processingDownloads.match}
|
||||||
|
element={<ImageProcessingSetting />}
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path={AppRoutes.settings.childRoutes.backup.match} element={<Backup />} />
|
<Route path={AppRoutes.settings.childRoutes.backup.match} element={<Backup />} />
|
||||||
@@ -255,6 +272,7 @@ const MainApp = () => {
|
|||||||
<Route path={AppRoutes.sources.childRoutes.searchAll.match} element={<SearchAll />} />
|
<Route path={AppRoutes.sources.childRoutes.searchAll.match} element={<SearchAll />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path={AppRoutes.extension.match}>
|
<Route path={AppRoutes.extension.match}>
|
||||||
|
{/* TODO: deprecated - "source" and "extension" page got merged into "browse" */}
|
||||||
<Route
|
<Route
|
||||||
index
|
index
|
||||||
element={<Navigate to={AppRoutes.browse.path(BrowseTab.EXTENSIONS)} replace />}
|
element={<Navigate to={AppRoutes.browse.path(BrowseTab.EXTENSIONS)} replace />}
|
||||||
|
|||||||
@@ -70,12 +70,23 @@ export const AppRoutes = {
|
|||||||
match: 'download',
|
match: 'download',
|
||||||
path: '/settings/download',
|
path: '/settings/download',
|
||||||
childRoutes: {
|
childRoutes: {
|
||||||
|
// TODO: deprecated - got moved to "settings/images/processing/downloads"
|
||||||
conversions: {
|
conversions: {
|
||||||
match: 'conversions',
|
match: 'conversions',
|
||||||
path: '/settings/download/conversions',
|
path: '/settings/download/conversions',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
images: {
|
||||||
|
match: 'images',
|
||||||
|
path: '/settings/images',
|
||||||
|
childRoutes: {
|
||||||
|
processingDownloads: {
|
||||||
|
match: 'processing/downloads',
|
||||||
|
path: '/settings/images/processing/downloads',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
backup: {
|
backup: {
|
||||||
match: 'backup',
|
match: 'backup',
|
||||||
path: '/settings/backup',
|
path: '/settings/backup',
|
||||||
|
|||||||
@@ -6,29 +6,9 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { d } from 'koration';
|
|
||||||
|
|
||||||
export const DOWNLOAD_AHEAD = {
|
export const DOWNLOAD_AHEAD = {
|
||||||
min: 2,
|
min: 2,
|
||||||
max: 10,
|
max: 10,
|
||||||
default: 2,
|
default: 2,
|
||||||
step: 1,
|
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,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -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<any> => {
|
|
||||||
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 <LoadingPlaceholder />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<EmptyViewAbsoluteCentered
|
|
||||||
message={t('global.error.label.failed_to_load_data')}
|
|
||||||
messageExtra={getErrorMessage(error)}
|
|
||||||
retry={() => refetch().catch(defaultPromiseErrorHandler('DownloadConversionSetting::refetch'))}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <DownloadConversionSetting conversions={data!.settings.downloadConversions} updateSetting={updateSetting} />;
|
|
||||||
};
|
|
||||||
@@ -129,7 +129,7 @@ export const DownloadSettings = () => {
|
|||||||
onChange={(e) => updateSetting('downloadAsCbz', e.target.checked)}
|
onChange={(e) => updateSetting('downloadAsCbz', e.target.checked)}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItemLink to={AppRoutes.settings.childRoutes.download.childRoutes.conversions.path}>
|
<ListItemLink to={AppRoutes.settings.childRoutes.images.childRoutes.processingDownloads.path}>
|
||||||
<ListItemText primary={t('download.settings.conversion.title')} />
|
<ListItemText primary={t('download.settings.conversion.title')} />
|
||||||
</ListItemLink>
|
</ListItemLink>
|
||||||
<List
|
<List
|
||||||
|
|||||||
@@ -256,3 +256,19 @@ export const KOREADER_SYNC_CHECKSUM_METHOD_SELECT_VALUES: SelectSettingValue<Kor
|
|||||||
method,
|
method,
|
||||||
KOREADER_SYNC_CHECKSUM_METHOD_TO_TRANSLATION_KEYS[method],
|
KOREADER_SYNC_CHECKSUM_METHOD_TO_TRANSLATION_KEYS[method],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const IMAGE_PROCESSING_COMPRESSION = {
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
step: 0.01,
|
||||||
|
};
|
||||||
|
export const IMAGE_PROCESSING_CALL_TIMEOUT = {
|
||||||
|
min: d(10).seconds.inWholeSeconds,
|
||||||
|
max: d(10).minutes.inWholeSeconds,
|
||||||
|
step: d(10).seconds.inWholeSeconds,
|
||||||
|
};
|
||||||
|
export const IMAGE_PROCESSING_CONNECT_TIMEOUT = {
|
||||||
|
min: d(10).seconds.inWholeSeconds,
|
||||||
|
max: d(10).minutes.inWholeSeconds,
|
||||||
|
step: d(10).seconds.inWholeSeconds,
|
||||||
|
};
|
||||||
|
|||||||
@@ -24,11 +24,6 @@ import Collapse from '@mui/material/Collapse';
|
|||||||
import { useElementSize } from '@mantine/hooks';
|
import { useElementSize } from '@mantine/hooks';
|
||||||
import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx';
|
import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx';
|
||||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||||
import {
|
|
||||||
DOWNLOAD_CONVERSION_COMPRESSION,
|
|
||||||
IMAGE_CONVERSION_CALL_TIMEOUT,
|
|
||||||
IMAGE_CONVERSION_CONNECT_TIMEOUT,
|
|
||||||
} from '@/features/downloads/Downloads.constants.ts';
|
|
||||||
import {
|
import {
|
||||||
Maybe,
|
Maybe,
|
||||||
SettingsDownloadConversion,
|
SettingsDownloadConversion,
|
||||||
@@ -38,6 +33,20 @@ import {
|
|||||||
import { SelectSettingValue, SelectSettingValueDisplayInfo } from '@/base/components/settings/SelectSetting.tsx';
|
import { SelectSettingValue, SelectSettingValueDisplayInfo } from '@/base/components/settings/SelectSetting.tsx';
|
||||||
import { Select } from '@/base/components/inputs/Select.tsx';
|
import { Select } from '@/base/components/inputs/Select.tsx';
|
||||||
import { TranslationKey } from '@/base/Base.types.ts';
|
import { TranslationKey } from '@/base/Base.types.ts';
|
||||||
|
import {
|
||||||
|
IMAGE_PROCESSING_CALL_TIMEOUT,
|
||||||
|
IMAGE_PROCESSING_COMPRESSION,
|
||||||
|
IMAGE_PROCESSING_CONNECT_TIMEOUT,
|
||||||
|
} from '@/features/settings/Settings.constants.ts';
|
||||||
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
|
import { ServerSettings } from '@/features/settings/Settings.types.ts';
|
||||||
|
import { makeToast } from '@/base/utils/Toast.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 { assertIsDefined } from '@/base/Asserts.ts';
|
||||||
|
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
|
||||||
|
|
||||||
export type TSettingsDownloadConversionHeader = SettingsDownloadConversionHeader & {
|
export type TSettingsDownloadConversionHeader = SettingsDownloadConversionHeader & {
|
||||||
/**
|
/**
|
||||||
@@ -108,19 +117,19 @@ const isValidNumberSetting = (value: number | null | undefined, min: number, max
|
|||||||
const isValidCallTimeoutSetting = (timeout: string | null | undefined): boolean =>
|
const isValidCallTimeoutSetting = (timeout: string | null | undefined): boolean =>
|
||||||
isValidNumberSetting(
|
isValidNumberSetting(
|
||||||
timeout ? d(timeout).seconds.inWholeSeconds : null,
|
timeout ? d(timeout).seconds.inWholeSeconds : null,
|
||||||
IMAGE_CONVERSION_CALL_TIMEOUT.min,
|
IMAGE_PROCESSING_CALL_TIMEOUT.min,
|
||||||
IMAGE_CONVERSION_CALL_TIMEOUT.max,
|
IMAGE_PROCESSING_CALL_TIMEOUT.max,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isValidConnectTimeoutSetting = (timeout: string | null | undefined): boolean =>
|
const isValidConnectTimeoutSetting = (timeout: string | null | undefined): boolean =>
|
||||||
isValidNumberSetting(
|
isValidNumberSetting(
|
||||||
timeout ? d(timeout).seconds.inWholeSeconds : null,
|
timeout ? d(timeout).seconds.inWholeSeconds : null,
|
||||||
IMAGE_CONVERSION_CONNECT_TIMEOUT.min,
|
IMAGE_PROCESSING_CONNECT_TIMEOUT.min,
|
||||||
IMAGE_CONVERSION_CONNECT_TIMEOUT.max,
|
IMAGE_PROCESSING_CONNECT_TIMEOUT.max,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isValidCompressionLevel = (compression: number | null | undefined): boolean =>
|
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 === '';
|
const isUnsetConversion = (mimeType: string, target: string): boolean => mimeType === '' && target === '';
|
||||||
|
|
||||||
@@ -521,7 +530,7 @@ const Conversion = ({
|
|||||||
helperText={!isCompressionLevelValid ? t('global.error.label.invalid_input') : ''}
|
helperText={!isCompressionLevelValid ? t('global.error.label.invalid_input') : ''}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
inputProps: DOWNLOAD_CONVERSION_COMPRESSION,
|
inputProps: IMAGE_PROCESSING_COMPRESSION,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -542,7 +551,7 @@ const Conversion = ({
|
|||||||
helperText={!isCallTimeoutValid ? t('global.error.label.invalid_input') : ''}
|
helperText={!isCallTimeoutValid ? t('global.error.label.invalid_input') : ''}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
inputProps: IMAGE_CONVERSION_CALL_TIMEOUT,
|
inputProps: IMAGE_PROCESSING_CALL_TIMEOUT,
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
{t('global.date.label.second_other')}
|
{t('global.date.label.second_other')}
|
||||||
@@ -568,7 +577,7 @@ const Conversion = ({
|
|||||||
helperText={!isConnectTimeoutValid ? t('global.error.label.invalid_input') : ''}
|
helperText={!isConnectTimeoutValid ? t('global.error.label.invalid_input') : ''}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
inputProps: IMAGE_CONVERSION_CONNECT_TIMEOUT,
|
inputProps: IMAGE_PROCESSING_CONNECT_TIMEOUT,
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
{t('global.date.label.second_other')}
|
{t('global.date.label.second_other')}
|
||||||
@@ -622,15 +631,34 @@ const Conversion = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DownloadConversionSetting = ({
|
export const ImageProcessingSetting = () => {
|
||||||
conversions,
|
|
||||||
updateSetting,
|
|
||||||
}: {
|
|
||||||
conversions: SettingsDownloadConversion[];
|
|
||||||
updateSetting: (conversions: SettingsDownloadConversion[]) => Promise<void>;
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation();
|
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 <LoadingPlaceholder />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<EmptyViewAbsoluteCentered
|
||||||
|
message={t('global.error.label.failed_to_load_data')}
|
||||||
|
messageExtra={getErrorMessage(error)}
|
||||||
|
retry={() => refetch().catch(defaultPromiseErrorHandler('DownloadConversionSetting::refetch'))}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertIsDefined(data?.settings?.downloadConversions);
|
||||||
|
|
||||||
|
const conversions = data?.settings?.downloadConversions;
|
||||||
|
|
||||||
const [tmpConversions, setTmpConversions] = useState(
|
const [tmpConversions, setTmpConversions] = useState(
|
||||||
normalizeConversions(maybeAddDefault(addStableIdToConversions(conversions))),
|
normalizeConversions(maybeAddDefault(addStableIdToConversions(conversions))),
|
||||||
);
|
);
|
||||||
@@ -641,6 +669,13 @@ export const DownloadConversionSetting = ({
|
|||||||
tmpConversions,
|
tmpConversions,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const updateSetting = (value: ServerSettings['downloadConversions']): Promise<any> => {
|
||||||
|
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 () => {
|
const onSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
await updateSetting(toValidServerConversions(tmpConversions));
|
await updateSetting(toValidServerConversions(tmpConversions));
|
||||||
36
src/features/settings/screens/ImagesSettings.tsx
Normal file
36
src/features/settings/screens/ImagesSettings.tsx
Normal file
@@ -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 (
|
||||||
|
<List
|
||||||
|
sx={{ pt: 0 }}
|
||||||
|
subheader={
|
||||||
|
<ListSubheader component="div" id="image-processing-settings">
|
||||||
|
{t('settings.images.processing.title')}
|
||||||
|
</ListSubheader>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemLink to={AppRoutes.settings.childRoutes.images.childRoutes.processingDownloads.path}>
|
||||||
|
<ListItemText primary={t('download.settings.conversion.title')} />
|
||||||
|
</ListItemLink>
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -23,6 +23,7 @@ import DevicesIcon from '@mui/icons-material/Devices';
|
|||||||
import SyncIcon from '@mui/icons-material/Sync';
|
import SyncIcon from '@mui/icons-material/Sync';
|
||||||
import PaletteIcon from '@mui/icons-material/Palette';
|
import PaletteIcon from '@mui/icons-material/Palette';
|
||||||
import HistoryIcon from '@mui/icons-material/History';
|
import HistoryIcon from '@mui/icons-material/History';
|
||||||
|
import ImageIcon from '@mui/icons-material/Image';
|
||||||
import { ListItemLink } from '@/base/components/lists/ListItemLink.tsx';
|
import { ListItemLink } from '@/base/components/lists/ListItemLink.tsx';
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { makeToast } from '@/base/utils/Toast.ts';
|
import { makeToast } from '@/base/utils/Toast.ts';
|
||||||
@@ -73,6 +74,12 @@ export function Settings() {
|
|||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary={t('download.title.download')} />
|
<ListItemText primary={t('download.title.download')} />
|
||||||
</ListItemLink>
|
</ListItemLink>
|
||||||
|
<ListItemLink to={AppRoutes.settings.childRoutes.images.path}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<ImageIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={t('settings.images.title')} />
|
||||||
|
</ListItemLink>
|
||||||
<ListItemLink to={AppRoutes.settings.childRoutes.tracking.path}>
|
<ListItemLink to={AppRoutes.settings.childRoutes.tracking.path}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<SyncIcon />
|
<SyncIcon />
|
||||||
|
|||||||
Reference in New Issue
Block a user