/* * 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 { useState } from 'react'; import TextField from '@mui/material/TextField'; import Stack from '@mui/material/Stack'; import DeleteIcon from '@mui/icons-material/Delete'; import IconButton from '@mui/material/IconButton'; import InputAdornment from '@mui/material/InputAdornment'; import Button from '@mui/material/Button'; import { useTheme } from '@mui/material/styles'; import MenuItem from '@mui/material/MenuItem'; import InputLabel from '@mui/material/InputLabel'; import FormControl from '@mui/material/FormControl'; import { d } from 'koration'; import { useElementSize } from '@mantine/hooks'; import { useLingui } from '@lingui/react/macro'; import type { MessageDescriptor } from '@lingui/core'; import { KeyValueItems } from '@/features/settings/components/images/KeyValueItems.tsx'; import { CustomTooltip } from '@/base/components/CustomTooltip.tsx'; import { IMAGE_PROCESSING_CALL_TIMEOUT, IMAGE_PROCESSING_COMPRESSION, IMAGE_PROCESSING_CONNECT_TIMEOUT, IMAGE_PROCESSING_INPUT_WIDTH, IMAGE_PROCESSING_TARGET_MODES_SELECT_VALUES, TARGET_DISABLED, } from '@/features/settings/Settings.constants.ts'; import { Select } from '@/base/components/inputs/Select.tsx'; import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx'; import { MimeTypeTextField } from '@/features/settings/components/images/MimeTypeTextField.tsx'; import type { TSettingsDownloadConversion } from '@/features/settings/Settings.types.ts'; import { ImageProcessingTargetMode } from '@/features/settings/Settings.types.ts'; import { getUpdatedSearchParams, isDefaultMimeType, isUrlTargetMode, isValidCallTimeoutSetting, isValidCompressionLevel, isValidConnectTimeoutSetting, } from '@/features/settings/ImageProcessing.utils.ts'; import { UrlUtil } from '@/lib/UrlUtil.ts'; export const Processing = ({ conversion, conversion: { mode, mimeType, target, compressionLevel, headers, searchParams, callTimeout, connectTimeout }, onChange, isDuplicate, }: { conversion: TSettingsDownloadConversion; onChange: (newConversion: TSettingsDownloadConversion | null) => void; isDuplicate: boolean; }) => { const { t } = useLingui(); const theme = useTheme(); const { ref: textFieldRef, height: textFieldHeight } = useElementSize(); const [areSearchParamsCollapsed, setAreSearchParamsCollapsed] = useState(true); const [areHeadersCollapsed, setAreHeadersCollapsed] = useState(true); const isDisabledMode = mode === ImageProcessingTargetMode.DISABLED; const isImageMode = mode === ImageProcessingTargetMode.IMAGE; const isUrlMode = mode === ImageProcessingTargetMode.URL; const isCallTimeoutValid = isValidCallTimeoutSetting(callTimeout); const isConnectTimeoutValid = isValidConnectTimeoutSetting(connectTimeout); const isCompressionLevelValid = isValidCompressionLevel(compressionLevel); const isDefault = isDefaultMimeType(mimeType) && !isDuplicate; const isDisabled = isDefault && !target && compressionLevel == null; return ( { onChange({ ...conversion, mimeType: value, }); }} /> {t`Target mode`} {!isDisabledMode && ( { onChange({ ...conversion, target: value, searchParams: isImageMode ? null : getUpdatedSearchParams(value, searchParams), }); }} /> )} {(() => { if (isDisabledMode) { return null; } if (isImageMode) { return ( { onChange({ ...conversion, compressionLevel: e.target.value ? Number(e.target.value) : null, }); }} /> ); } return ( <> {t`Second`}, }, }} onChange={(e) => { onChange({ ...conversion, callTimeout: e.target.value ? d(Number(e.target.value)).seconds.toISOString() : null, }); }} /> {t`Second`}, }, }} onChange={(e) => { onChange({ ...conversion, connectTimeout: e.target.value ? d(Number(e.target.value)).seconds.toISOString() : null, }); }} /> ); })()} { onChange(null); }} > { const baseUrl = target?.split('?')[0] ?? ''; const updatedParams = Object.fromEntries(params?.map(({ name, value }) => [name, value]) ?? []); onChange({ ...conversion, target: UrlUtil.addParams(baseUrl, updatedParams), searchParams: params, }); }} /> onChange({ ...conversion, headers: updatedHeaders, }) } /> ); };