/* * 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 { useContext, useLayoutEffect } from 'react'; 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 { ThemeMode, AppThemeContext } from '@/modules/theme/contexts/AppThemeContext.tsx'; import { Select } from '@/modules/core/components/inputs/Select.tsx'; import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx'; import { NumberSetting } from '@/modules/core/components/settings/NumberSetting.tsx'; import { useLocalStorage } from '@/modules/core/hooks/useStorage.tsx'; import { I18nResourceCode, i18nResources } from '@/i18n'; import { langCodeToName } from '@/modules/core/utils/Languages.ts'; import { ThemeList } from '@/modules/theme/components/ThemeList.tsx'; import { createUpdateMetadataServerSettings, useMetadataServerSettings, } from '@/modules/settings/services/ServerSettingsMetadata.ts'; import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPlaceholder.tsx'; import { EmptyViewAbsoluteCentered } from '@/modules/core/components/feedback/EmptyViewAbsoluteCentered.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { makeToast } from '@/modules/core/utils/Toast.ts'; import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts'; import { AppStorage } from '@/lib/storage/AppStorage.ts'; import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx'; export const Appearance = () => { const { t, i18n } = useTranslation(); const { themeMode, setThemeMode, pureBlackMode, setPureBlackMode } = useContext(AppThemeContext); const { mode, setMode } = useColorScheme(); const actualThemeMode = (mode ?? themeMode) as ThemeMode; const { setTitle, setAction } = useNavBarContext(); useLayoutEffect(() => { setTitle(t('settings.appearance.title')); setAction(null); return () => { setTitle(''); setAction(null); }; }, [t]); const { settings, request: { loading, error, refetch }, } = useMetadataServerSettings(); const updateMetadataSetting = createUpdateMetadataServerSettings((e) => makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)), ); const isDarkMode = MediaQuery.getThemeMode() === ThemeMode.DARK; const DEFAULT_ITEM_WIDTH = 300; const [itemWidth, setItemWidth] = useLocalStorage('ItemWidth', DEFAULT_ITEM_WIDTH); if (loading) { return ; } if (error) { return ( refetch().catch(defaultPromiseErrorHandler('Appearance::refetch'))} /> ); } return ( {t('settings.appearance.theme.title')} } > 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-mode', newMode, true, false); }} > {t('global.label.system')} {t('global.label.dark')} {t('global.label.light')} {isDarkMode && ( setPureBlackMode(enabled)} /> )} {t('global.label.display')} } > {t('settings.label.language_description')} {t('global.language.title.weblate')} } /> updateMetadataSetting('mangaThumbnailBackdrop', e.target.checked)} /> updateMetadataSetting('mangaDynamicColorSchemes', e.target.checked)} /> ); };