/* * 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 List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import MenuItem from '@mui/material/MenuItem'; import ListSubheader from '@mui/material/ListSubheader'; import Switch from '@mui/material/Switch'; import Link from '@mui/material/Link'; import { useColorScheme } from '@mui/material/styles'; import { useLingui } from '@lingui/react/macro'; import { useAppThemeContext } from '@/features/theme/AppThemeContext.tsx'; import { Select } from '@/base/components/inputs/Select.tsx'; import { MediaQuery } from '@/base/utils/MediaQuery.tsx'; import { NumberSetting } from '@/base/components/settings/NumberSetting.tsx'; import { i18nResources, loadCatalog } from '@/i18n'; import { languageCodeToName } from '@/base/utils/Languages.ts'; import { ThemeList } from '@/features/theme/components/ThemeList.tsx'; import { createUpdateMetadataServerSettings, useMetadataServerSettings, } from '@/features/settings/services/ServerSettingsMetadata.ts'; import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx'; import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { makeToast } from '@/base/utils/Toast.ts'; import { MetadataThemeSettings, ThemeMode } from '@/features/theme/AppTheme.types.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { AppStorage } from '@/lib/storage/AppStorage.ts'; import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts'; import { MANGA_GRID_WIDTH, SERVER_SETTINGS_METADATA_DEFAULT } from '@/features/settings/Settings.constants.ts'; import { MUI_THEME_MODE_KEY } from '@/lib/mui/MUI.constants.ts'; export const Appearance = () => { const { t } = useLingui(); const { themeMode, setThemeMode, shouldUsePureBlackMode, setShouldUsePureBlackMode } = useAppThemeContext(); const { mode, setMode } = useColorScheme(); const actualThemeMode = (mode ?? themeMode) as ThemeMode; useAppTitle(t`Appearance`); const { settings: { mangaThumbnailBackdrop, mangaDynamicColorSchemes, mangaGridItemWidth, locale }, request: { loading, error, refetch }, } = useMetadataServerSettings(); const updateMetadataSetting = createUpdateMetadataServerSettings((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)), ); const isDarkMode = MediaQuery.getThemeMode(actualThemeMode) === ThemeMode.DARK; if (loading) { return ; } if (error) { return ( refetch().catch(defaultPromiseErrorHandler('Appearance::refetch'))} /> ); } return ( {t`Theme`} } > value={actualThemeMode} onChange={(e) => { const newMode = e.target.value as 'system' | 'light' | 'dark'; setThemeMode(newMode as ThemeMode); setMode(newMode); // in case a non "colorSchemes" mui theme is active, "setMode" does not update the mode ("mui-mode") value AppStorage.local.setItem(MUI_THEME_MODE_KEY, newMode, true); }} > {t`System`} {t`Dark`} {t`Light`} {isDarkMode && ( setShouldUsePureBlackMode(enabled)} /> )} {t`Display`} } > {t`Feel free to translate the project on`} {t`Weblate`} } /> updateMetadataSetting('mangaGridItemWidth', width)} /> updateMetadataSetting('mangaThumbnailBackdrop', e.target.checked)} /> updateMetadataSetting('mangaDynamicColorSchemes', e.target.checked)} /> ); };