2024-03-06 23:07:48 +01:00
/ *
* 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/.
* /
2024-04-14 15:50:12 +02:00
import List from '@mui/material/List' ;
import ListItem from '@mui/material/ListItem' ;
import ListItemText from '@mui/material/ListItemText' ;
import MenuItem from '@mui/material/MenuItem' ;
2026-01-10 19:45:02 +01:00
import { useLingui } from '@lingui/react/macro' ;
2024-10-05 22:53:22 +02:00
import {
updateMetadataServerSettings ,
useMetadataServerSettings ,
2025-08-15 22:02:58 +02:00
} from '@/features/settings/services/ServerSettingsMetadata.ts' ;
2025-08-16 02:48:46 +02:00
import { makeToast } from '@/base/utils/Toast.ts' ;
import { MutableListSetting } from '@/base/components/settings/MutableListSetting.tsx' ;
2025-08-16 02:14:49 +02:00
import { useDeviceContext } from '@/features/device/DeviceContext.tsx' ;
2025-08-16 02:48:46 +02:00
import { Select } from '@/base/components/inputs/Select.tsx' ;
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx' ;
import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx' ;
2024-10-05 16:09:34 +02:00
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts' ;
2025-08-15 22:02:58 +02:00
import { DEFAULT_DEVICE } from '@/features/device/services/Device.ts' ;
2026-03-11 00:11:29 +01:00
import type { MetadataServerSettingKeys , MetadataServerSettings } from '@/features/settings/Settings.types.ts' ;
2024-12-20 17:24:40 +01:00
import { getErrorMessage } from '@/lib/HelperFunctions.ts' ;
2025-08-15 22:02:58 +02:00
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts' ;
2024-03-06 23:07:48 +01:00
export const DeviceSetting = ( ) = > {
2026-01-10 19:45:02 +01:00
const { t } = useLingui ( ) ;
2025-05-03 13:00:03 +02:00
2026-01-10 19:45:02 +01:00
useAppTitle ( t ` Device ` ) ;
2024-03-06 23:07:48 +01:00
const {
metadata ,
2024-03-07 01:12:35 +01:00
settings : { devices } ,
2024-04-27 16:24:55 +02:00
loading ,
2024-04-27 22:28:55 +02:00
request : { error , refetch } ,
2024-03-06 23:07:48 +01:00
} = useMetadataServerSettings ( ) ;
2025-05-03 12:39:53 +02:00
const { activeDevice , setActiveDevice } = useDeviceContext ( ) ;
2024-03-07 01:12:35 +01:00
const updateMetadataSetting = < Setting extends MetadataServerSettingKeys > (
2024-03-06 23:07:48 +01:00
setting : Setting ,
value : MetadataServerSettings [ Setting ] ,
) = > {
if ( ! metadata ) {
return ;
}
const wasActiveDeviceDeleted = setting === 'devices' && ! ( value as string [ ] ) . includes ( activeDevice ) ;
if ( wasActiveDeviceDeleted ) {
2024-03-07 01:12:35 +01:00
setActiveDevice ( DEFAULT_DEVICE ) ;
2024-03-06 23:07:48 +01:00
}
2024-12-20 17:24:40 +01:00
updateMetadataServerSettings ( setting , value ) . catch ( ( e ) = >
2026-01-10 19:45:02 +01:00
makeToast ( t ` Failed to save changes ` , 'error' , getErrorMessage ( e ) ) ,
2024-03-16 16:21:15 +01:00
) ;
2024-03-06 23:07:48 +01:00
} ;
2024-04-27 16:24:55 +02:00
if ( loading ) {
return < LoadingPlaceholder / > ;
}
2024-04-27 22:28:55 +02:00
if ( error ) {
return (
2024-04-29 15:29:33 +02:00
< EmptyViewAbsoluteCentered
2026-01-10 19:45:02 +01:00
message = { t ` Unable to load data ` }
2024-12-21 23:27:03 +01:00
messageExtra = { getErrorMessage ( error ) }
2024-04-27 22:28:55 +02:00
retry = { ( ) = > refetch ( ) . catch ( defaultPromiseErrorHandler ( 'DeviceSetting::refetch' ) ) }
/ >
) ;
}
2024-03-06 23:07:48 +01:00
return (
2024-09-05 00:34:13 +02:00
< List sx = { { pt : 0 } } >
2024-03-06 23:07:48 +01:00
< MutableListSetting
2026-01-10 19:45:02 +01:00
settingName = { t ` Devices ` }
description = { t ` Manage your existing devices. \ nUI specific settings that are stored on the server are per device. \ nThis makes it possible to have e.g. different settings on a desktop and a smartphone ` }
2024-03-06 23:07:48 +01:00
handleChange = { ( deviceList ) = > {
2024-11-01 19:30:03 +01:00
updateMetadataSetting ( 'devices' , [
2026-01-10 19:45:02 +01:00
. . . new Set ( [ DEFAULT_DEVICE , . . . deviceList ] . filter ( ( device ) = > device !== t ` Default ` ) ) ,
2024-11-01 19:30:03 +01:00
] ) ;
2024-03-06 23:07:48 +01:00
} }
2024-11-01 19:30:03 +01:00
valueInfos = { devices . map ( ( device ) = > [
2026-01-10 19:45:02 +01:00
device === DEFAULT_DEVICE ? t ` Default ` : device ,
2024-11-01 19:30:03 +01:00
{ mutable : false , deletable : device !== DEFAULT_DEVICE } ,
] ) }
2026-01-10 19:45:02 +01:00
addItemButtonTitle = { t ` Create ` }
2024-03-06 23:44:05 +01:00
validateItem = { ( device ) = > device . length <= 16 && ! ! device . match ( /^[a-zA-Z0-9\-_]+$/g ) }
2026-01-10 19:45:02 +01:00
placeholder = { t ` Smartphone_Name-1 | length: 16, chars: letters, numbers, -, _ ` }
2024-03-06 23:07:48 +01:00
/ >
< ListItem >
< ListItemText
2026-01-10 19:45:02 +01:00
primary = { t ` Active device ` }
secondary = { t ` Select a device to use its server stored UI settings ` }
2024-03-06 23:07:48 +01:00
/ >
2024-03-29 18:57:52 +01:00
< Select value = { activeDevice } onChange = { ( { target : { value : device } } ) = > setActiveDevice ( device ) } >
2024-03-06 23:07:48 +01:00
{ devices . map ( ( device ) = > (
< MenuItem key = { device } value = { device } >
2026-01-10 19:45:02 +01:00
{ device === DEFAULT_DEVICE ? t ` Default ` : device }
2024-03-06 23:07:48 +01:00
< / MenuItem >
) ) }
< / Select >
< / ListItem >
< / List >
) ;
} ;