From ce4c7aed5e2f9315e62b7e9aa364700d112aebc3 Mon Sep 17 00:00:00 2001 From: Grady Hallenbeck Date: Tue, 17 Oct 2023 17:54:55 -0700 Subject: [PATCH 1/3] feat: (preferences) migrate display settings to react components --- .../experimental/routes/asyncRoutes/user.ts | 3 +- .../experimental/routes/legacyRoutes/user.ts | 6 -- .../user/display/DisplayPreferences.tsx | 95 +++++++++++++++++++ .../user/display/ItemDetailPreferences.tsx | 28 ++++++ .../user/display/LibraryPreferences.tsx | 81 ++++++++++++++++ .../user/display/LocalizationPreferences.tsx | 48 ++++++++++ .../routes/user/display/NextUpPreferences.tsx | 59 ++++++++++++ .../routes/user/display/constants.ts | 79 +++++++++++++++ .../routes/user/display/index.tsx | 43 +++++++++ src/styles/site.scss | 1 + src/themes/theme.ts | 7 ++ 11 files changed, 443 insertions(+), 7 deletions(-) create mode 100644 src/apps/experimental/routes/user/display/DisplayPreferences.tsx create mode 100644 src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx create mode 100644 src/apps/experimental/routes/user/display/LibraryPreferences.tsx create mode 100644 src/apps/experimental/routes/user/display/LocalizationPreferences.tsx create mode 100644 src/apps/experimental/routes/user/display/NextUpPreferences.tsx create mode 100644 src/apps/experimental/routes/user/display/constants.ts create mode 100644 src/apps/experimental/routes/user/display/index.tsx diff --git a/src/apps/experimental/routes/asyncRoutes/user.ts b/src/apps/experimental/routes/asyncRoutes/user.ts index 9f0a74e272..e653bf172d 100644 --- a/src/apps/experimental/routes/asyncRoutes/user.ts +++ b/src/apps/experimental/routes/asyncRoutes/user.ts @@ -8,5 +8,6 @@ export const ASYNC_USER_ROUTES: AsyncRoute[] = [ { path: 'movies.html', page: 'movies', type: AsyncRouteType.Experimental }, { path: 'tv.html', page: 'shows', type: AsyncRouteType.Experimental }, { path: 'music.html', page: 'music', type: AsyncRouteType.Experimental }, - { path: 'livetv.html', page: 'livetv', type: AsyncRouteType.Experimental } + { path: 'livetv.html', page: 'livetv', type: AsyncRouteType.Experimental }, + { path: 'mypreferencesdisplay.html', page: 'user/display', type: AsyncRouteType.Experimental } ]; diff --git a/src/apps/experimental/routes/legacyRoutes/user.ts b/src/apps/experimental/routes/legacyRoutes/user.ts index e6e3fcdfcb..1547f68359 100644 --- a/src/apps/experimental/routes/legacyRoutes/user.ts +++ b/src/apps/experimental/routes/legacyRoutes/user.ts @@ -25,12 +25,6 @@ export const LEGACY_USER_ROUTES: LegacyRoute[] = [ controller: 'user/controls/index', view: 'user/controls/index.html' } - }, { - path: 'mypreferencesdisplay.html', - pageProps: { - controller: 'user/display/index', - view: 'user/display/index.html' - } }, { path: 'mypreferenceshome.html', pageProps: { diff --git a/src/apps/experimental/routes/user/display/DisplayPreferences.tsx b/src/apps/experimental/routes/user/display/DisplayPreferences.tsx new file mode 100644 index 0000000000..a898f0bf36 --- /dev/null +++ b/src/apps/experimental/routes/user/display/DisplayPreferences.tsx @@ -0,0 +1,95 @@ +import Checkbox from '@mui/material/Checkbox'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormHelperText from '@mui/material/FormHelperText'; +import MenuItem from '@mui/material/MenuItem'; +import Select from '@mui/material/Select'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import React from 'react'; + +import globalize from 'scripts/globalize'; + +export function DisplayPreferences() { + return ( + + {globalize.translate('Display')} + + + + + {globalize.translate('DisplayModeHelp')} + {globalize.translate('LabelPleaseRestart')} + + + + + + + + + } + label={globalize.translate('DisableCustomCss')} + /> + + {globalize.translate('LabelDisableCustomCss')} + + + + + + + {globalize.translate('LabelLocalCustomCss')} + + + + {/* TODO: There are some admin-only options here */} + {/* Server Dashboard Theme */} + + + + + + {/* TODO: There are some extra options here related to screensavers */} + + + } + label={globalize.translate('EnableFasterAnimations')} + /> + + {globalize.translate('EnableFasterAnimationsHelp')} + + + + + } + label={globalize.translate('EnableBlurHash')} + /> + + {globalize.translate('EnableBlurHashHelp')} + + + + ); +} diff --git a/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx b/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx new file mode 100644 index 0000000000..409167a657 --- /dev/null +++ b/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx @@ -0,0 +1,28 @@ +import Checkbox from '@mui/material/Checkbox'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormHelperText from '@mui/material/FormHelperText'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import React from 'react'; + +import globalize from 'scripts/globalize'; + +export function ItemDetailPreferences() { + return ( + + {globalize.translate('ItemDetails')} + + + } + label={globalize.translate('EnableDetailsBanner')} + /> + + {globalize.translate('EnableDetailsBannerHelp')} + + + + ); +} diff --git a/src/apps/experimental/routes/user/display/LibraryPreferences.tsx b/src/apps/experimental/routes/user/display/LibraryPreferences.tsx new file mode 100644 index 0000000000..ec13aa4112 --- /dev/null +++ b/src/apps/experimental/routes/user/display/LibraryPreferences.tsx @@ -0,0 +1,81 @@ +import Checkbox from '@mui/material/Checkbox'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormHelperText from '@mui/material/FormHelperText'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import React from 'react'; + +import globalize from 'scripts/globalize'; + +export function LibraryPreferences() { + return ( + + {globalize.translate('HeaderLibraries')} + + + + + {globalize.translate('LabelLibraryPageSizeHelp')} + + + + + } + label={globalize.translate('Backdrops')} + /> + + {globalize.translate('EnableBackdropsHelp')} + + + + + } + label={globalize.translate('ThemeSongs')} + /> + + {globalize.translate('EnableThemeSongsHelp')} + + + + + } + label={globalize.translate('ThemeVideos')} + /> + + {globalize.translate('EnableThemeVideosHelp')} + + + + + } + label={globalize.translate('DisplayMissingEpisodesWithinSeasons')} + /> + + {globalize.translate('DisplayMissingEpisodesWithinSeasonsHelp')} + + + + ); +} diff --git a/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx b/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx new file mode 100644 index 0000000000..50a0b2252d --- /dev/null +++ b/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx @@ -0,0 +1,48 @@ +import FormControl from '@mui/material/FormControl'; +import FormHelperText from '@mui/material/FormHelperText'; +import Link from '@mui/material/Link'; +import MenuItem from '@mui/material/MenuItem'; +import Select from '@mui/material/Select'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import React from 'react'; + +import globalize from 'scripts/globalize'; +import { DATE_LOCALE_OPTIONS, LANGUAGE_OPTIONS } from './constants'; + +export function LocalizationPreferences() { + return ( + + {globalize.translate('Localization')} + + + + + {globalize.translate('LabelDisplayLanguageHelp')} + + {globalize.translate('LearnHowYouCanContribute')} + + + + + + + + + ); +} diff --git a/src/apps/experimental/routes/user/display/NextUpPreferences.tsx b/src/apps/experimental/routes/user/display/NextUpPreferences.tsx new file mode 100644 index 0000000000..eaa32fdafc --- /dev/null +++ b/src/apps/experimental/routes/user/display/NextUpPreferences.tsx @@ -0,0 +1,59 @@ +import Checkbox from '@mui/material/Checkbox'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormHelperText from '@mui/material/FormHelperText'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import React from 'react'; + +import globalize from 'scripts/globalize'; + +export function NextUpPreferences() { + return ( + + {globalize.translate('NextUp')} + + + + + {globalize.translate('LabelMaxDaysForNextUpHelp')} + + + + + } + label={globalize.translate('EnableRewatchingNextUp')} + /> + + {globalize.translate('EnableRewatchingNextUpHelp')} + + + + + } + label={globalize.translate('UseEpisodeImagesInNextUp')} + /> + + {globalize.translate('UseEpisodeImagesInNextUpHelp')} + + + + ); +} diff --git a/src/apps/experimental/routes/user/display/constants.ts b/src/apps/experimental/routes/user/display/constants.ts new file mode 100644 index 0000000000..7ece9aa9c7 --- /dev/null +++ b/src/apps/experimental/routes/user/display/constants.ts @@ -0,0 +1,79 @@ +import globalize from 'scripts/globalize'; + +export const LANGUAGE_OPTIONS = [ + { value: 'auto', label: globalize.translate('Auto') }, + { value: 'af', label: 'Afrikaans' }, + { value: 'ar', label: 'العربية' }, + { value: 'be-BY', label: 'Беларуская' }, + { value: 'bg-BG', label: 'Български' }, + { value: 'bn_BD', label: 'বাংলা (বাংলাদেশ)' }, + { value: 'ca', label: 'Català' }, + { value: 'cs', label: 'Čeština' }, + { value: 'cy', label: 'Cymraeg' }, + { value: 'da', label: 'Dansk' }, + { value: 'de', label: 'Deutsch' }, + { value: 'el', label: 'Ελληνικά' }, + { value: 'en-GB', label: 'English (United Kingdom)' }, + { value: 'en-US', label: 'English' }, + { value: 'eo', label: 'Esperanto' }, + { value: 'es', label: 'Español' }, + { value: 'es_419', label: 'Español americano' }, + { value: 'es-AR', label: 'Español (Argentina)' }, + { value: 'es_DO', label: 'Español (Dominicana)' }, + { value: 'es-MX', label: 'Español (México)' }, + { value: 'et', label: 'Eesti' }, + { value: 'eu', label: 'Euskara' }, + { value: 'fa', label: 'فارسی' }, + { value: 'fi', label: 'Suomi' }, + { value: 'fil', label: 'Filipino' }, + { value: 'fr', label: 'Français' }, + { value: 'fr-CA', label: 'Français (Canada)' }, + { value: 'gl', label: 'Galego' }, + { value: 'gsw', label: 'Schwiizerdütsch' }, + { value: 'he', label: 'עִבְרִית' }, + { value: 'hi-IN', label: 'हिन्दी' }, + { value: 'hr', label: 'Hrvatski' }, + { value: 'hu', label: 'Magyar' }, + { value: 'id', label: 'Bahasa Indonesia' }, + { value: 'is-IS', label: 'Íslenska' }, + { value: 'it', label: 'Italiano' }, + { value: 'ja', label: '日本語' }, + { value: 'kk', label: 'Qazaqşa' }, + { value: 'ko', label: '한국어' }, + { value: 'lt-LT', label: 'Lietuvių' }, + { value: 'lv', label: 'Latviešu' }, + { value: 'mk', label: 'Македонски' }, + { value: 'ml', label: 'മലയാളം' }, + { value: 'mr', label: 'मराठी' }, + { value: 'ms', label: 'Bahasa Melayu' }, + { value: 'nb', label: 'Norsk bokmål' }, + { value: 'ne', label: 'नेपाली' }, + { value: 'nl', label: 'Nederlands' }, + { value: 'nn', label: 'Norsk nynorsk' }, + { value: 'pa', label: 'ਪੰਜਾਬੀ' }, + { value: 'pl', label: 'Polski' }, + { value: 'pr', label: 'Pirate' }, + { value: 'pt', label: 'Português' }, + { value: 'pt-BR', label: 'Português (Brasil)' }, + { value: 'pt-PT', label: 'Português (Portugal)' }, + { value: 'ro', label: 'Românește' }, + { value: 'ru', label: 'Русский' }, + { value: 'sk', label: 'Slovenčina' }, + { value: 'sl-SI', label: 'Slovenščina' }, + { value: 'sq', label: 'Shqip' }, + { value: 'sr', label: 'Српски' }, + { value: 'sv', label: 'Svenska' }, + { value: 'ta', label: 'தமிழ்' }, + { value: 'te', label: 'తెలుగు' }, + { value: 'th', label: 'ภาษาไทย' }, + { value: 'tr', label: 'Türkçe' }, + { value: 'uk', label: 'Українська' }, + { value: 'ur_PK', label: ' اُردُو' }, + { value: 'vi', label: 'Tiếng Việt' }, + { value: 'zh-CN', label: '汉语 (简化字)' }, + { value: 'zh-TW', label: '漢語 (繁体字)' }, + { value: 'zh-HK', label: '廣東話 (香港)' } +]; + +// NOTE: Option `Euskara` (eu) does not exist in legacy date locale options. +export const DATE_LOCALE_OPTIONS = LANGUAGE_OPTIONS.filter(({ value }) => value !== 'eu'); diff --git a/src/apps/experimental/routes/user/display/index.tsx b/src/apps/experimental/routes/user/display/index.tsx new file mode 100644 index 0000000000..8836c16df1 --- /dev/null +++ b/src/apps/experimental/routes/user/display/index.tsx @@ -0,0 +1,43 @@ +import Button from '@mui/material/Button'; +import Stack from '@mui/material/Stack'; +import React from 'react'; + +import Page from 'components/Page'; +import globalize from 'scripts/globalize'; +import theme from 'themes/theme'; +import { DisplayPreferences } from './DisplayPreferences'; +import { LibraryPreferences } from './LibraryPreferences'; +import { LocalizationPreferences } from './LocalizationPreferences'; +import { NextUpPreferences } from './NextUpPreferences'; + +export default function UserDisplayPreferences() { + return ( + +
+
+ + + + + + + + +
+
+
+ ); +} diff --git a/src/styles/site.scss b/src/styles/site.scss index f3f1a699b7..0e9c66c901 100644 --- a/src/styles/site.scss +++ b/src/styles/site.scss @@ -39,6 +39,7 @@ body { right: 0; bottom: 0; contain: strict; + z-index: -1; } .layout-mobile, diff --git a/src/themes/theme.ts b/src/themes/theme.ts index 70e060dd74..4a17f6ade4 100644 --- a/src/themes/theme.ts +++ b/src/themes/theme.ts @@ -62,6 +62,13 @@ const theme = createTheme({ variant: 'filled' } }, + MuiFormHelperText: { + styleOverrides: { + root: { + fontSize: '1rem' + } + } + }, MuiTextField: { defaultProps: { variant: 'filled' From 3dd26c7785329c38f1a468c8561a49ce7d36fe3f Mon Sep 17 00:00:00 2001 From: Grady Hallenbeck Date: Thu, 19 Oct 2023 12:02:54 -0700 Subject: [PATCH 2/3] feat: (preferences) hook react display settings into user settings --- .../user/display/DisplayPreferences.tsx | 72 +++++++- .../user/display/ItemDetailPreferences.tsx | 18 +- .../user/display/LibraryPreferences.tsx | 45 ++++- .../user/display/LocalizationPreferences.tsx | 26 ++- .../routes/user/display/NextUpPreferences.tsx | 29 +++- .../display/hooks/useDisplaySettingForm.ts | 46 +++++ .../user/display/hooks/useDisplaySettings.ts | 159 ++++++++++++++++++ .../user/display/hooks/useScreensavers.ts | 29 ++++ .../user/display/hooks/useServerThemes.ts | 32 ++++ .../routes/user/display/index.tsx | 65 ++++++- .../experimental/routes/user/display/types.ts | 22 +++ src/scripts/settings/userSettings.js | 30 ++-- src/types/webConfig.ts | 3 +- 13 files changed, 530 insertions(+), 46 deletions(-) create mode 100644 src/apps/experimental/routes/user/display/hooks/useDisplaySettingForm.ts create mode 100644 src/apps/experimental/routes/user/display/hooks/useDisplaySettings.ts create mode 100644 src/apps/experimental/routes/user/display/hooks/useScreensavers.ts create mode 100644 src/apps/experimental/routes/user/display/hooks/useServerThemes.ts create mode 100644 src/apps/experimental/routes/user/display/types.ts diff --git a/src/apps/experimental/routes/user/display/DisplayPreferences.tsx b/src/apps/experimental/routes/user/display/DisplayPreferences.tsx index a898f0bf36..a862727cf1 100644 --- a/src/apps/experimental/routes/user/display/DisplayPreferences.tsx +++ b/src/apps/experimental/routes/user/display/DisplayPreferences.tsx @@ -3,15 +3,26 @@ import FormControl from '@mui/material/FormControl'; import FormControlLabel from '@mui/material/FormControlLabel'; import FormHelperText from '@mui/material/FormHelperText'; import MenuItem from '@mui/material/MenuItem'; -import Select from '@mui/material/Select'; +import Select, { SelectChangeEvent } from '@mui/material/Select'; import Stack from '@mui/material/Stack'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; import React from 'react'; import globalize from 'scripts/globalize'; +import { DisplaySettingsValues } from './types'; +import { useScreensavers } from './hooks/useScreensavers'; +import { useServerThemes } from './hooks/useServerThemes'; + +interface DisplayPreferencesProps { + onChange: (event: SelectChangeEvent | React.SyntheticEvent) => void; + values: DisplaySettingsValues; +} + +export function DisplayPreferences({ onChange, values }: Readonly) { + const { screensavers } = useScreensavers(); + const { themes } = useServerThemes(); -export function DisplayPreferences() { return ( {globalize.translate('Display')} @@ -19,7 +30,12 @@ export function DisplayPreferences() { + } + control={ + + } label={globalize.translate('DisableCustomCss')} + name='disableCustomCss' /> {globalize.translate('LabelDisableCustomCss')} @@ -52,8 +84,11 @@ export function DisplayPreferences() { {globalize.translate('LabelLocalCustomCss')} @@ -64,7 +99,18 @@ export function DisplayPreferences() { {/* Server Dashboard Theme */} - + {/* TODO: There are some extra options here related to screensavers */} @@ -72,8 +118,14 @@ export function DisplayPreferences() { } + control={ + + } label={globalize.translate('EnableFasterAnimations')} + name='enableFasterAnimation' /> {globalize.translate('EnableFasterAnimationsHelp')} @@ -83,8 +135,14 @@ export function DisplayPreferences() { } + control={ + + } label={globalize.translate('EnableBlurHash')} + name='enableBlurHash' /> {globalize.translate('EnableBlurHashHelp')} diff --git a/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx b/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx index 409167a657..00da9439de 100644 --- a/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx +++ b/src/apps/experimental/routes/user/display/ItemDetailPreferences.tsx @@ -7,17 +7,29 @@ import Typography from '@mui/material/Typography'; import React from 'react'; import globalize from 'scripts/globalize'; +import { DisplaySettingsValues } from './types'; -export function ItemDetailPreferences() { +interface ItemDetailPreferencesProps { + onChange: (event: React.SyntheticEvent) => void; + values: DisplaySettingsValues; +} + +export function ItemDetailPreferences({ onChange, values }: Readonly) { return ( - + {globalize.translate('ItemDetails')} } + control={ + + } label={globalize.translate('EnableDetailsBanner')} + name='enableItemDetailsBanner' /> {globalize.translate('EnableDetailsBannerHelp')} diff --git a/src/apps/experimental/routes/user/display/LibraryPreferences.tsx b/src/apps/experimental/routes/user/display/LibraryPreferences.tsx index ec13aa4112..04ae913999 100644 --- a/src/apps/experimental/routes/user/display/LibraryPreferences.tsx +++ b/src/apps/experimental/routes/user/display/LibraryPreferences.tsx @@ -8,10 +8,16 @@ import Typography from '@mui/material/Typography'; import React from 'react'; import globalize from 'scripts/globalize'; +import { DisplaySettingsValues } from './types'; -export function LibraryPreferences() { +interface LibraryPreferencesProps { + onChange: (event: React.SyntheticEvent) => void; + values: DisplaySettingsValues; +} + +export function LibraryPreferences({ onChange, values }: Readonly) { return ( - + {globalize.translate('HeaderLibraries')} @@ -26,7 +32,10 @@ export function LibraryPreferences() { required: true, step: '1' }} + defaultValue={values.libraryPageSize} label={globalize.translate('LabelLibraryPageSize')} + name='libraryPageSize' + onChange={onChange} /> {globalize.translate('LabelLibraryPageSizeHelp')} @@ -36,8 +45,14 @@ export function LibraryPreferences() { } + control={ + + } label={globalize.translate('Backdrops')} + name='enableLibraryBackdrops' /> {globalize.translate('EnableBackdropsHelp')} @@ -47,8 +62,14 @@ export function LibraryPreferences() { } + control={ + + } label={globalize.translate('ThemeSongs')} + name='enableLibraryThemeSongs' /> {globalize.translate('EnableThemeSongsHelp')} @@ -58,8 +79,14 @@ export function LibraryPreferences() { } + control={ + + } label={globalize.translate('ThemeVideos')} + name='enableLibraryThemeVideos' /> {globalize.translate('EnableThemeVideosHelp')} @@ -69,8 +96,14 @@ export function LibraryPreferences() { } + control={ + + } label={globalize.translate('DisplayMissingEpisodesWithinSeasons')} + name='displayMissingEpisodes' /> {globalize.translate('DisplayMissingEpisodesWithinSeasonsHelp')} diff --git a/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx b/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx index 50a0b2252d..d0e625174e 100644 --- a/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx +++ b/src/apps/experimental/routes/user/display/LocalizationPreferences.tsx @@ -2,23 +2,34 @@ import FormControl from '@mui/material/FormControl'; import FormHelperText from '@mui/material/FormHelperText'; import Link from '@mui/material/Link'; import MenuItem from '@mui/material/MenuItem'; -import Select from '@mui/material/Select'; +import Select, { SelectChangeEvent } from '@mui/material/Select'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import React from 'react'; import globalize from 'scripts/globalize'; import { DATE_LOCALE_OPTIONS, LANGUAGE_OPTIONS } from './constants'; +import { DisplaySettingsValues } from './types'; -export function LocalizationPreferences() { +interface LocalizationPreferencesProps { + onChange: (event: SelectChangeEvent) => void; + values: DisplaySettingsValues; +} + +export function LocalizationPreferences({ onChange, values }: Readonly) { return ( - + {globalize.translate('Localization')} + - {globalize.translate('Auto')} - {globalize.translate('Desktop')} - {globalize.translate('Mobile')} - {globalize.translate('TV')} - {globalize.translate('Experimental')} - - - {globalize.translate('DisplayModeHelp')} - {globalize.translate('LabelPleaseRestart')} - - + { appHost.supports('displaymode') && ( + + {globalize.translate('LabelDisplayMode')} + + + {globalize.translate('DisplayModeHelp')} + {globalize.translate('LabelPleaseRestart')} + + + ) } - - - + { themes.length > 0 && ( + + {globalize.translate('LabelTheme')} + + + ) } - {/* TODO: There are some admin-only options here */} - {/* Server Dashboard Theme */} + { themes.length > 0 && user?.Policy?.IsAdministrator && ( + + {globalize.translate('LabelDashboardTheme')} + + + ) } - - - + { screensavers.length > 0 && appHost.supports('screensaver') && ( + + + {globalize.translate('LabelScreensaver')} + + - {/* TODO: There are some extra options here related to screensavers */} + + + + {globalize.translate('LabelBackdropScreensaverIntervalHelp')} + + + + ) } ) { return ( - + {globalize.translate('HeaderLibraries')} @@ -32,7 +32,7 @@ export function LibraryPreferences({ onChange, values }: Readonly) { + if (!appHost.supports('displaylanguage') && !datetime.supportsLocalization()) { + return null; + } return ( - + {globalize.translate('Localization')} - - - - {globalize.translate('LabelDisplayLanguageHelp')} - + {globalize.translate('LabelDisplayLanguage')} + + + {globalize.translate('LabelDisplayLanguageHelp')} + { appHost.supports('externallinks') && ( + + {globalize.translate('LearnHowYouCanContribute')} + + ) } + + + ) } - - - + { datetime.supportsLocalization() && ( + + {globalize.translate('LabelDateTimeLocale')} + + + ) } ); } diff --git a/src/apps/experimental/routes/user/display/NextUpPreferences.tsx b/src/apps/experimental/routes/user/display/NextUpPreferences.tsx index fba6b406ef..1c21012a1f 100644 --- a/src/apps/experimental/routes/user/display/NextUpPreferences.tsx +++ b/src/apps/experimental/routes/user/display/NextUpPreferences.tsx @@ -17,13 +17,13 @@ interface NextUpPreferencesProps { export function NextUpPreferences({ onChange, values }: Readonly) { return ( - + {globalize.translate('NextUp')} { const target = e.target as HTMLInputElement; const fieldName = target.name as keyof DisplaySettingsValues; - const fieldValue = target.checked ?? target.value; + const fieldValue = target.type === 'checkbox' ? target.checked : target.value; if (values?.[fieldName] !== fieldValue) { updateField({