Migrate to lingui
Switch to "lingui" for better DX. Tried to persist existing languages as much as possible. Removed "vite-plugin-node-polyfills" because it's incompatible with "lingui"
This commit is contained in:
@@ -7,9 +7,9 @@
|
||||
*/
|
||||
|
||||
import React, { ReactNode, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Direction, ThemeProvider } from '@mui/material/styles';
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { AppTheme, getTheme } from '@/features/theme/services/AppThemes.ts';
|
||||
import {
|
||||
createUpdateMetadataServerSettings,
|
||||
@@ -24,6 +24,7 @@ import { createAndSetTheme } from '@/features/theme/services/ThemeCreator.ts';
|
||||
import { AppStorage } from '@/lib/storage/AppStorage.ts';
|
||||
import { DIRECTION_TO_CACHE } from '@/features/theme/ThemeDirectionCache.ts';
|
||||
import { TAppThemeContext, ThemeMode } from '@/features/theme/AppTheme.types.ts';
|
||||
import { getLanguageReadingDirection } from '@/lib/ISOLanguageUtil.ts';
|
||||
|
||||
export const AppThemeContext = React.createContext<TAppThemeContext>({
|
||||
appTheme: 'default',
|
||||
@@ -39,7 +40,7 @@ export const AppThemeContext = React.createContext<TAppThemeContext>({
|
||||
export const useAppThemeContext = () => useContext(AppThemeContext);
|
||||
|
||||
export const AppThemeContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t, i18n } = useLingui();
|
||||
const {
|
||||
request: metadataServerSettingsRequest,
|
||||
settings: { appTheme: serverAppTheme, themeMode, shouldUsePureBlackMode, customThemes },
|
||||
@@ -60,10 +61,10 @@ export const AppThemeContextProvider = ({ children }: { children: ReactNode }) =
|
||||
|
||||
const appTheme = areMetadataServerSettingsReady ? serverAppTheme : localAppTheme.id;
|
||||
const actualThemeMode = areMetadataServerSettingsReady ? themeMode : localThemeMode;
|
||||
const currentDirection = i18n.dir();
|
||||
const currentDirection = getLanguageReadingDirection(i18n.locale);
|
||||
|
||||
const updateSetting = createUpdateMetadataServerSettings<'appTheme' | 'themeMode' | 'shouldUsePureBlackMode'>((e) =>
|
||||
makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)),
|
||||
makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)),
|
||||
);
|
||||
|
||||
const appThemeContext = useMemo(
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { CssVarsThemeOptions } from '@mui/material/styles';
|
||||
import { t as translate } from 'i18next';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export type TBaseTheme = {
|
||||
isCustom: boolean;
|
||||
@@ -18,7 +18,7 @@ export type TBaseTheme = {
|
||||
export const themes = {
|
||||
default: {
|
||||
isCustom: false,
|
||||
getName: () => translate('global.label.default'),
|
||||
getName: () => t`Default`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -46,7 +46,7 @@ export const themes = {
|
||||
},
|
||||
lavender: {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.lavender'),
|
||||
getName: () => t`Lavender`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -82,7 +82,7 @@ export const themes = {
|
||||
},
|
||||
dune: {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.dune'),
|
||||
getName: () => t`Dune`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -110,7 +110,7 @@ export const themes = {
|
||||
},
|
||||
rosegold: {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.rosegold'),
|
||||
getName: () => t`Rosegold`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -142,7 +142,7 @@ export const themes = {
|
||||
},
|
||||
'forest dew': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.forest_dew'),
|
||||
getName: () => t`Forest Dew`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -170,7 +170,7 @@ export const themes = {
|
||||
},
|
||||
'montain sunset': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.mountain_sunset'),
|
||||
getName: () => t`Mountain Sunset`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -202,7 +202,7 @@ export const themes = {
|
||||
},
|
||||
crimson: {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.crimson'),
|
||||
getName: () => t`Crimson`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -230,7 +230,7 @@ export const themes = {
|
||||
},
|
||||
'minty miracles': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.minty_miracles'),
|
||||
getName: () => t`Minty Miracles`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -262,7 +262,7 @@ export const themes = {
|
||||
},
|
||||
'orange juice': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.orange_juice'),
|
||||
getName: () => t`Orange Juice`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -294,7 +294,7 @@ export const themes = {
|
||||
},
|
||||
'bright pink': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.bright_pink'),
|
||||
getName: () => t`Bright Pink`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -322,7 +322,7 @@ export const themes = {
|
||||
},
|
||||
veronica: {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.veronica'),
|
||||
getName: () => t`Veronica`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -350,7 +350,7 @@ export const themes = {
|
||||
},
|
||||
'tree frog green': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.tree_frog_green'),
|
||||
getName: () => t`Tree Frog Green`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
@@ -382,7 +382,7 @@ export const themes = {
|
||||
},
|
||||
'ying and yang': {
|
||||
isCustom: false,
|
||||
getName: () => translate('settings.appearance.theme.themes.ying_and_yang'),
|
||||
getName: () => t`Ying & Yang`,
|
||||
muiTheme: {
|
||||
colorSchemes: {
|
||||
light: {
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Button from '@mui/material/Button';
|
||||
import AddCircleIcon from '@mui/icons-material/AddCircle';
|
||||
import { AwaitableComponent } from 'awaitable-component';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||
import { ThemeCreationDialog } from '@/features/theme/components/CreateThemeDialog.tsx';
|
||||
import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx';
|
||||
|
||||
export const CreateThemeButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
<Stack sx={{ alignItems: 'center', gap: 1, minWidth: '150px', maxWidth: '150px' }}>
|
||||
@@ -33,10 +33,8 @@ export const CreateThemeButton = () => {
|
||||
>
|
||||
<AddCircleIcon fontSize="large" />
|
||||
</Button>
|
||||
<CustomTooltip title={t('settings.appearance.theme.create.title')} placement="top">
|
||||
<TypographyMaxLines sx={{ maxWidth: '100%' }}>
|
||||
{t('settings.appearance.theme.create.title')}
|
||||
</TypographyMaxLines>
|
||||
<CustomTooltip title={t`Create theme`} placement="top">
|
||||
<TypographyMaxLines sx={{ maxWidth: '100%' }}>{t`Create theme`}</TypographyMaxLines>
|
||||
</CustomTooltip>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { MessageDescriptor } from '@lingui/core';
|
||||
import { useState } from 'react';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Stack from '@mui/material/Stack';
|
||||
@@ -19,6 +19,8 @@ import TextField from '@mui/material/TextField';
|
||||
import Link from '@mui/material/Link';
|
||||
import { jsonrepair } from 'jsonrepair';
|
||||
import { AwaitableComponentProps } from 'awaitable-component';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { getErrorMessage, jsonSaveParse } from '@/lib/HelperFunctions.ts';
|
||||
import { AppTheme, isThemeNameUnique } from '@/features/theme/services/AppThemes.ts';
|
||||
import {
|
||||
@@ -30,7 +32,6 @@ import { EmptyView } from '@/base/components/feedback/EmptyView.tsx';
|
||||
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
|
||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||
import { MetadataThemeSettings } from '@/features/theme/AppTheme.types.ts';
|
||||
import { TranslationKey } from '@/base/Base.types.ts';
|
||||
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
|
||||
import { useAppThemeContext } from '@/features/theme/AppThemeContext.tsx';
|
||||
|
||||
@@ -66,36 +67,36 @@ const baseCustomTheme: AppTheme = {
|
||||
|
||||
type DialogMode = 'create' | 'edit' | 'save_dynamic';
|
||||
|
||||
const dialogModeToTranslationKey: Record<
|
||||
const dialogModeToTranslation: Record<
|
||||
DialogMode,
|
||||
{
|
||||
title: TranslationKey;
|
||||
button: TranslationKey;
|
||||
action: TranslationKey;
|
||||
success: TranslationKey;
|
||||
failure: TranslationKey;
|
||||
title: MessageDescriptor;
|
||||
button: MessageDescriptor;
|
||||
action: MessageDescriptor;
|
||||
success: MessageDescriptor;
|
||||
failure: MessageDescriptor;
|
||||
}
|
||||
> = {
|
||||
create: {
|
||||
title: 'settings.appearance.theme.create.title',
|
||||
button: 'global.button.ok',
|
||||
action: 'settings.appearance.theme.create.action',
|
||||
success: 'settings.appearance.theme.create.success',
|
||||
failure: 'settings.appearance.theme.create.failure',
|
||||
title: msg`Create theme`,
|
||||
button: msg`Ok`,
|
||||
action: msg`Creating theme…`,
|
||||
success: msg`Created theme`,
|
||||
failure: msg`Could not create theme`,
|
||||
},
|
||||
edit: {
|
||||
title: 'settings.appearance.theme.edit.title',
|
||||
button: 'global.button.save',
|
||||
action: 'settings.appearance.theme.edit.action',
|
||||
success: 'settings.appearance.theme.edit.success',
|
||||
failure: 'settings.appearance.theme.edit.failure',
|
||||
title: msg`Edit theme`,
|
||||
button: msg`Save`,
|
||||
action: msg`Saving theme changes…`,
|
||||
success: msg`Saved theme changes`,
|
||||
failure: msg`Could not save theme changes`,
|
||||
},
|
||||
save_dynamic: {
|
||||
title: 'settings.appearance.manga_dynamic_color_schemes.save',
|
||||
button: 'global.button.save',
|
||||
action: 'settings.appearance.theme.create.action',
|
||||
success: 'settings.appearance.theme.create.success',
|
||||
failure: 'settings.appearance.theme.create.failure',
|
||||
title: msg`Save dynamic color theme`,
|
||||
button: msg`Save`,
|
||||
action: msg`Creating theme…`,
|
||||
success: msg`Created theme`,
|
||||
failure: msg`Could not create theme`,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -110,7 +111,7 @@ export const ThemeCreationDialog = ({
|
||||
mode: DialogMode;
|
||||
appTheme?: AppTheme;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
const {
|
||||
settings: { customThemes },
|
||||
@@ -131,12 +132,12 @@ export const ThemeCreationDialog = ({
|
||||
|
||||
return (
|
||||
<Dialog open={isVisible} onTransitionExited={onExitComplete} fullWidth maxWidth="md">
|
||||
<DialogTitle>{t(dialogModeToTranslationKey[mode].title)}</DialogTitle>
|
||||
<DialogTitle>{t(dialogModeToTranslation[mode].title)}</DialogTitle>
|
||||
<DialogContent>
|
||||
{loading && <LoadingPlaceholder />}
|
||||
{error && (
|
||||
<EmptyView
|
||||
message={t('global.error.label.failed_to_load_data')}
|
||||
message={t`Unable to load data`}
|
||||
messageExtra={getErrorMessage(error)}
|
||||
retry={() => refetch().catch(defaultPromiseErrorHandler('ThemeCreationDialog::refetch'))}
|
||||
/>
|
||||
@@ -144,21 +145,29 @@ export const ThemeCreationDialog = ({
|
||||
{!error && (
|
||||
<Stack sx={{ gap: 2, whiteSpace: 'pre-line' }}>
|
||||
<Typography>
|
||||
<Trans i18nKey="settings.appearance.theme.create.dialog.description">
|
||||
<Trans>
|
||||
See the official{' '}
|
||||
<Link
|
||||
href="https://mui.com/material-ui/customization/how-to-customize/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
MUI documentation
|
||||
</Link>
|
||||
</Link>{' '}
|
||||
for how to customize the theme.
|
||||
<br />
|
||||
The palette API is not supported, you have to use the new
|
||||
<Link
|
||||
href="https://mui.com/material-ui/customization/palette/#color-schemes"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
MUI documentation
|
||||
color schemes API
|
||||
</Link>
|
||||
.
|
||||
<br />
|
||||
<br />
|
||||
You can use theme creators like{' '}
|
||||
<Link
|
||||
href="https://zenoo.github.io/mui-theme-creator/"
|
||||
target="_blank"
|
||||
@@ -166,16 +175,21 @@ export const ThemeCreationDialog = ({
|
||||
>
|
||||
MUI Theme Creator
|
||||
</Link>{' '}
|
||||
, copy everything after "themeOptions" from "{'{'}" to "{'}'}
|
||||
" and paste it into the "theme" text field.
|
||||
, however, you have to adjust the created object according to the new color schemes API.
|
||||
<br />
|
||||
<br />
|
||||
In case no background is defined, a background will be calculated based on the primary
|
||||
color.
|
||||
</Trans>
|
||||
</Typography>
|
||||
<TextField
|
||||
disabled={mode === 'edit'}
|
||||
label={t('settings.appearance.theme.create.dialog.theme_name')}
|
||||
label={t`Name`}
|
||||
value={theme.getName()}
|
||||
error={invalidName}
|
||||
helperText={invalidName && t('settings.appearance.theme.create.dialog.error.invalid_name')}
|
||||
helperText={
|
||||
invalidName && t`The theme name must be unique and has a limit of 16 characters`
|
||||
}
|
||||
onChange={(e) => {
|
||||
const name = e.target.value.trim();
|
||||
|
||||
@@ -191,10 +205,10 @@ export const ThemeCreationDialog = ({
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
label={t('settings.appearance.theme.title')}
|
||||
label={t`Theme`}
|
||||
multiline
|
||||
error={invalidTheme}
|
||||
helperText={invalidTheme && t('settings.appearance.theme.create.dialog.error.invalid_json')}
|
||||
helperText={invalidTheme && t`Invalid json`}
|
||||
defaultValue={JSON.stringify(theme.muiTheme, null, 2)}
|
||||
onChange={(e) => {
|
||||
const invalidThemeStr = 'invalid';
|
||||
@@ -229,29 +243,23 @@ export const ThemeCreationDialog = ({
|
||||
<CheckboxInput
|
||||
sx={{ margin: 0 }}
|
||||
size="small"
|
||||
label={t('settings.appearance.manga_dynamic_color_schemes.set_active')}
|
||||
label={t`Set as active theme`}
|
||||
checked={setAsActiveTheme}
|
||||
onChange={(_, checked) => setSetAsActiveTheme(checked)}
|
||||
/>
|
||||
<Stack sx={{ flexDirection: 'row', justifyContent: 'end' }}>
|
||||
<Button autoFocus onClick={() => onDismiss()} color="primary">
|
||||
{t('global.button.cancel')}
|
||||
{t`Cancel`}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={invalidTheme || invalidName || isCreating || !didThemeChange || !theme.id.length}
|
||||
onClick={() => {
|
||||
makeToast(
|
||||
t(dialogModeToTranslationKey[mode].action, { theme: theme.getName() }),
|
||||
'info',
|
||||
);
|
||||
makeToast(t(dialogModeToTranslation[mode].action), 'info');
|
||||
|
||||
setIsCreating(true);
|
||||
updateCustomThemes('customThemes', { ...customThemes, [theme.id]: theme })
|
||||
.then(() => {
|
||||
makeToast(
|
||||
t(dialogModeToTranslationKey[mode].success, { theme: theme.getName() }),
|
||||
'success',
|
||||
);
|
||||
makeToast(t(dialogModeToTranslation[mode].success), 'success');
|
||||
|
||||
if (setAsActiveTheme) {
|
||||
setAppTheme(theme.getName());
|
||||
@@ -261,7 +269,7 @@ export const ThemeCreationDialog = ({
|
||||
})
|
||||
.catch((updateError) =>
|
||||
makeToast(
|
||||
t(dialogModeToTranslationKey[mode].failure, { theme: theme.getName() }),
|
||||
t(dialogModeToTranslation[mode].failure),
|
||||
'error',
|
||||
getErrorMessage(updateError),
|
||||
),
|
||||
@@ -270,7 +278,7 @@ export const ThemeCreationDialog = ({
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
{t(dialogModeToTranslationKey[mode].button)}
|
||||
{t(dialogModeToTranslation[mode].button)}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { useMemo } from 'react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { appThemes } from '@/features/theme/services/AppThemes.ts';
|
||||
import {
|
||||
createUpdateMetadataServerSettings,
|
||||
@@ -24,7 +24,7 @@ import { MetadataThemeSettings } from '@/features/theme/AppTheme.types.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
|
||||
export const ThemeList = () => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
const {
|
||||
settings: { customThemes },
|
||||
@@ -53,7 +53,7 @@ export const ThemeList = () => {
|
||||
if (error) {
|
||||
return (
|
||||
<EmptyView
|
||||
message={t('global.error.label.failed_to_load_data')}
|
||||
message={t`Unable to load data`}
|
||||
messageExtra={getErrorMessage(error)}
|
||||
retry={() => refetch().catch(defaultPromiseErrorHandler('ThemeList::refetch'))}
|
||||
/>
|
||||
@@ -70,23 +70,14 @@ export const ThemeList = () => {
|
||||
key={theme.id}
|
||||
appTheme={theme}
|
||||
onDelete={() => {
|
||||
makeToast(t('settings.appearance.theme.delete.action', { theme: theme.getName() }), 'info');
|
||||
makeToast(t`Deleting theme "${theme.getName()}"…`, 'info');
|
||||
updateCustomThemes(
|
||||
'customThemes',
|
||||
Object.fromEntries(Object.entries(customThemes).filter(([id]) => id !== theme.id)),
|
||||
)
|
||||
.then(() =>
|
||||
makeToast(
|
||||
t('settings.appearance.theme.delete.success', { theme: theme.getName() }),
|
||||
'success',
|
||||
),
|
||||
)
|
||||
.then(() => makeToast(t`Deleted theme "${theme.getName()}"`, 'success'))
|
||||
.catch((e) =>
|
||||
makeToast(
|
||||
t('settings.appearance.theme.delete.failure', { theme: theme.getName() }),
|
||||
'error',
|
||||
getErrorMessage(e),
|
||||
),
|
||||
makeToast(t`Could not delete theme "${theme.getName()}"`, 'error', getErrorMessage(e)),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useMemo } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Stack from '@mui/material/Stack';
|
||||
@@ -19,6 +18,7 @@ import IconButton from '@mui/material/IconButton';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import { AwaitableComponent } from 'awaitable-component';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||
import { useAppThemeContext } from '@/features/theme/AppThemeContext.tsx';
|
||||
import { AppTheme } from '@/features/theme/services/AppThemes.ts';
|
||||
@@ -37,7 +37,7 @@ const ThemePreviewBadge = styled(Box)(() => ({
|
||||
export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDelete: () => void }) => {
|
||||
const { getName } = appTheme;
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
const theme = useTheme();
|
||||
const { themeMode, setAppTheme, appTheme: activeAppTheme, shouldUsePureBlackMode } = useAppThemeContext();
|
||||
|
||||
@@ -95,16 +95,10 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
|
||||
return;
|
||||
}
|
||||
|
||||
makeToast(t('settings.appearance.theme.select.fonts.loading'), 'info');
|
||||
makeToast(t`Loading theme fonts…`, 'info');
|
||||
ThemeFontLoader.load(appTheme.muiTheme)
|
||||
.then(() => setAppTheme(appTheme.id))
|
||||
.catch((e) =>
|
||||
makeToast(
|
||||
t('settings.appearance.theme.select.fonts.error'),
|
||||
'error',
|
||||
getErrorMessage(e),
|
||||
),
|
||||
);
|
||||
.catch((e) => makeToast(t`Could not load theme fonts`, 'error', getErrorMessage(e)));
|
||||
}}
|
||||
>
|
||||
<Stack sx={{ height: '100%', m: 0 }}>
|
||||
@@ -151,7 +145,7 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
|
||||
size="small"
|
||||
sx={{ mt: -0.5 }}
|
||||
>
|
||||
<CustomTooltip title={t('global.button.delete')} placement="auto">
|
||||
<CustomTooltip title={t`Delete`} placement="auto">
|
||||
<DeleteIcon />
|
||||
</CustomTooltip>
|
||||
</IconButton>
|
||||
@@ -170,7 +164,7 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
|
||||
component="div"
|
||||
size="small"
|
||||
>
|
||||
<CustomTooltip title={t('global.button.edit')} placement="auto">
|
||||
<CustomTooltip title={t`Edit`} placement="auto">
|
||||
<EditIcon />
|
||||
</CustomTooltip>
|
||||
</IconButton>
|
||||
|
||||
Reference in New Issue
Block a user