From e466842c778bbcfe08df1567e64987dbbb1bc16e Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sat, 5 Oct 2024 22:12:32 +0200 Subject: [PATCH] Move theme files into new folder --- src/App.tsx | 2 +- src/lib/metadata/metadataServerSettings.ts | 2 +- src/lib/ui/MediaQuery.tsx | 2 +- src/modules/core/contexts/AppContext.tsx | 4 +- src/modules/theme/AppTheme.types.ts | 14 +++ .../AppThemes.ts => modules/theme/Themes.ts} | 98 +---------------- .../theme/components}/CreateThemeButton.tsx | 2 +- .../theme/components}/CreateThemeDialog.tsx | 4 +- .../theme/components}/ThemeList.tsx | 8 +- .../theme/components}/ThemePreview.tsx | 6 +- .../theme/contexts}/ThemeModeContext.tsx | 2 +- src/modules/theme/services/AppThemes.ts | 102 ++++++++++++++++++ .../settings/{appearance => }/Appearance.tsx | 8 +- src/theme.tsx | 4 +- src/typings.ts | 7 +- 15 files changed, 142 insertions(+), 123 deletions(-) create mode 100644 src/modules/theme/AppTheme.types.ts rename src/{lib/ui/AppThemes.ts => modules/theme/Themes.ts} (59%) rename src/{screens/settings/appearance/theme => modules/theme/components}/CreateThemeButton.tsx (94%) rename src/{screens/settings/appearance/theme => modules/theme/components}/CreateThemeDialog.tsx (98%) rename src/{screens/settings/appearance/theme => modules/theme/components}/ThemeList.tsx (91%) rename src/{screens/settings/appearance/theme => modules/theme/components}/ThemePreview.tsx (97%) rename src/{components/context => modules/theme/contexts}/ThemeModeContext.tsx (93%) create mode 100644 src/modules/theme/services/AppThemes.ts rename src/screens/settings/{appearance => }/Appearance.tsx (95%) diff --git a/src/App.tsx b/src/App.tsx index e222f91e..57ed4aa5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -58,7 +58,7 @@ const { LibraryDuplicates } = loadable( () => import('@/modules/library/screens/LibraryDuplicates.tsx'), lazyLoadFallback, ); -const { Appearance } = loadable(() => import('@/screens/settings/appearance/Appearance.tsx'), lazyLoadFallback); +const { Appearance } = loadable(() => import('@/screens/settings/Appearance.tsx'), lazyLoadFallback); if (process.env.NODE_ENV !== 'production') { // Adds messages only in a dev environment diff --git a/src/lib/metadata/metadataServerSettings.ts b/src/lib/metadata/metadataServerSettings.ts index daddaf1d..9d821b65 100644 --- a/src/lib/metadata/metadataServerSettings.ts +++ b/src/lib/metadata/metadataServerSettings.ts @@ -12,7 +12,6 @@ import { Metadata, MetadataServerSettingKeys, MetadataServerSettings, - MetadataThemeSettings, } from '@/typings.ts'; import { requestManager } from '@/lib/requests/requests/RequestManager.ts'; import { convertFromGqlMeta, getMetadataFrom, requestUpdateServerMetadata } from '@/lib/metadata/metadata.ts'; @@ -21,6 +20,7 @@ import { DEFAULT_DEVICE } from '@/util/device.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { DEFAULT_SORT_SETTINGS } from '@/modules/migration/Migration.constants.ts'; import { MetadataMigrationSettings } from '@/modules/migration/Migration.types.ts'; +import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; export const getDefaultSettings = (): MetadataServerSettings => ({ // downloads diff --git a/src/lib/ui/MediaQuery.tsx b/src/lib/ui/MediaQuery.tsx index 0a6650ba..554d4bb6 100644 --- a/src/lib/ui/MediaQuery.tsx +++ b/src/lib/ui/MediaQuery.tsx @@ -10,7 +10,7 @@ import useMediaQuery from '@mui/material/useMediaQuery'; import { Breakpoint } from '@mui/material/styles'; import { useCallback, useState } from 'react'; import { getCurrentTheme } from '@/theme.tsx'; -import { ThemeMode } from '@/components/context/ThemeModeContext.tsx'; +import { ThemeMode } from '@/modules/theme/contexts/ThemeModeContext.tsx'; import { AppStorage } from '@/lib/AppStorage.ts'; import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx'; diff --git a/src/modules/core/contexts/AppContext.tsx b/src/modules/core/contexts/AppContext.tsx index bd71e153..f353d586 100644 --- a/src/modules/core/contexts/AppContext.tsx +++ b/src/modules/core/contexts/AppContext.tsx @@ -19,12 +19,12 @@ import rtlPlugin from 'stylis-plugin-rtl'; import { SnackbarProvider } from 'notistack'; import { createAndSetTheme } from '@/theme.tsx'; import { useLocalStorage } from '@/modules/core/hooks/useStorage.tsx'; -import { ThemeMode, ThemeModeContext } from '@/components/context/ThemeModeContext.tsx'; +import { ThemeMode, ThemeModeContext } from '@/modules/theme/contexts/ThemeModeContext.tsx'; import { NavBarContextProvider } from '@/components/navbar/NavBarContextProvider.tsx'; import { LibraryOptionsContextProvider } from '@/modules/library/contexts/LibraryOptionsProvider.tsx'; import { ActiveDevice, DEFAULT_DEVICE, setActiveDevice } from '@/util/device.ts'; import { MediaQuery } from '@/lib/ui/MediaQuery.tsx'; -import { AppThemes, getTheme } from '@/lib/ui/AppThemes.ts'; +import { AppThemes, getTheme } from '@/modules/theme/services/AppThemes.ts'; import { useMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts'; interface Props { diff --git a/src/modules/theme/AppTheme.types.ts b/src/modules/theme/AppTheme.types.ts new file mode 100644 index 00000000..d0409d42 --- /dev/null +++ b/src/modules/theme/AppTheme.types.ts @@ -0,0 +1,14 @@ +/* + * 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 { AppTheme } from '@/modules/theme/services/AppThemes.ts'; + +export type MetadataThemeSettings = { + customThemes: Record; + mangaThumbnailBackdrop: boolean; +}; diff --git a/src/lib/ui/AppThemes.ts b/src/modules/theme/Themes.ts similarity index 59% rename from src/lib/ui/AppThemes.ts rename to src/modules/theme/Themes.ts index 18287f21..87655930 100644 --- a/src/lib/ui/AppThemes.ts +++ b/src/modules/theme/Themes.ts @@ -8,13 +8,10 @@ import { ThemeOptions } from '@mui/material/styles'; import { t as translate } from 'i18next'; -import WebFont from 'webfontloader'; -import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { ControlledPromise } from '@/lib/ControlledPromise.ts'; -type Theme = { isCustom: boolean; getName: () => string; muiTheme: ThemeOptions }; +export type TBaseTheme = { isCustom: boolean; getName: () => string; muiTheme: ThemeOptions }; -const themes = { +export const themes = { default: { isCustom: false, getName: () => translate('global.label.default'), @@ -183,93 +180,4 @@ const themes = { }, }, }, -} as const satisfies Record; - -export type AppThemes = keyof typeof themes | string; - -export type AppTheme = Theme & { id: AppThemes; isCustom: boolean }; - -export const appThemes = (Object.entries(themes) as [AppThemes, Theme][]).map(([id, theme]) => ({ - id, - ...theme, -})) satisfies AppTheme[]; - -export const getTheme = (id: AppThemes, customThemes: Record = {}): AppTheme => { - try { - const allThemes = { ...themes, ...customThemes }; - const theme = (allThemes[id as keyof typeof themes] as AppTheme) ?? themes.default; - - return { - // @ts-ignore - custom themes do not have a "getName" function - getName: () => id, - ...theme, - }; - } catch (e) { - defaultPromiseErrorHandler('getTheme')(e); - } - return { id, ...themes[id as keyof typeof themes] }; -}; - -export const isThemeNameUnique = (id: string, customThemes: Record): boolean => - Object.keys({ ...themes, ...customThemes }).every((themeId) => themeId.toLowerCase() !== id.toLowerCase()); - -const getFontsFromTheme = (obj: Record, fonts: string[] = []): string[] => { - const tmpFonts = [...fonts]; - - const propertyNames = Object.keys(obj); - for (const propertyName of propertyNames) { - const propertyValue = obj[propertyName]; - const propertyType = typeof obj[propertyName]; - - const isValidFontProperty = propertyName === 'fontFamily' && propertyType === 'string'; - if (isValidFontProperty) { - tmpFonts.push(propertyValue as string); - // eslint-disable-next-line no-continue - continue; - } - - const isObject = propertyType === 'object'; - if (isObject) { - tmpFonts.push(...getFontsFromTheme(propertyValue as Record, tmpFonts)); - } - } - - return [...new Set(tmpFonts)]; -}; - -const loadedFonts: string[] = []; - -export const hasMissingFonts = (theme: ThemeOptions): boolean => { - const themeFonts = getFontsFromTheme(theme.typography ?? {}); - return !!themeFonts.length && themeFonts.some((font) => !loadedFonts.includes(font)); -}; - -export const loadThemeFonts = async (theme: ThemeOptions): Promise => { - const themeFonts = getFontsFromTheme(theme.typography ?? {}); - const missingThemeFonts = themeFonts.filter((font) => !loadedFonts.includes(font)); - - if (!missingThemeFonts.length) { - return; - } - - const loadFontsPromise = new ControlledPromise(); - try { - WebFont.load({ - google: { - families: missingThemeFonts, - }, - active: () => { - loadedFonts.push(...missingThemeFonts); - loadFontsPromise.resolve(); - }, - inactive: () => { - loadFontsPromise.reject(); - }, - }); - } catch (e) { - defaultPromiseErrorHandler('AppThemes::loadFonts')(e); - loadFontsPromise.reject(e); - } - - await loadFontsPromise.promise; -}; +} as const satisfies Record; diff --git a/src/screens/settings/appearance/theme/CreateThemeButton.tsx b/src/modules/theme/components/CreateThemeButton.tsx similarity index 94% rename from src/screens/settings/appearance/theme/CreateThemeButton.tsx rename to src/modules/theme/components/CreateThemeButton.tsx index ad0d627f..ea90b7c0 100644 --- a/src/screens/settings/appearance/theme/CreateThemeButton.tsx +++ b/src/modules/theme/components/CreateThemeButton.tsx @@ -12,7 +12,7 @@ import Button from '@mui/material/Button'; import AddCircleIcon from '@mui/icons-material/AddCircle'; import { bindDialog, bindTrigger, usePopupState } from 'material-ui-popup-state/hooks'; import Tooltip from '@mui/material/Tooltip'; -import { ThemeCreationDialog } from '@/screens/settings/appearance/theme/CreateThemeDialog.tsx'; +import { ThemeCreationDialog } from '@/modules/theme/components/CreateThemeDialog.tsx'; import { TypographyMaxLines } from '@/modules/core/components/TypographyMaxLines.tsx'; export const CreateThemeButton = () => { diff --git a/src/screens/settings/appearance/theme/CreateThemeDialog.tsx b/src/modules/theme/components/CreateThemeDialog.tsx similarity index 98% rename from src/screens/settings/appearance/theme/CreateThemeDialog.tsx rename to src/modules/theme/components/CreateThemeDialog.tsx index b1c0f918..b87287de 100644 --- a/src/screens/settings/appearance/theme/CreateThemeDialog.tsx +++ b/src/modules/theme/components/CreateThemeDialog.tsx @@ -20,17 +20,17 @@ import TextField from '@mui/material/TextField'; import Link from '@mui/material/Link'; import { jsonrepair } from 'jsonrepair'; import { jsonSaveParse } from '@/lib/HelperFunctions.ts'; -import { AppTheme, isThemeNameUnique } from '@/lib/ui/AppThemes.ts'; +import { AppTheme, isThemeNameUnique } from '@/modules/theme/services/AppThemes.ts'; import { createUpdateMetadataServerSettings, useMetadataServerSettings, } from '@/lib/metadata/metadataServerSettings.ts'; -import { MetadataThemeSettings } from '@/typings.ts'; import { makeToast } from '@/lib/ui/Toast.ts'; import { EmptyView } from '@/modules/core/components/placeholder/EmptyView.tsx'; import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { TranslationKey } from '@/Base.types.ts'; +import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; const baseCustomTheme: AppTheme = { id: '', diff --git a/src/screens/settings/appearance/theme/ThemeList.tsx b/src/modules/theme/components/ThemeList.tsx similarity index 91% rename from src/screens/settings/appearance/theme/ThemeList.tsx rename to src/modules/theme/components/ThemeList.tsx index 056fb574..695a1dc2 100644 --- a/src/screens/settings/appearance/theme/ThemeList.tsx +++ b/src/modules/theme/components/ThemeList.tsx @@ -9,18 +9,18 @@ import { useTranslation } from 'react-i18next'; import Stack from '@mui/material/Stack'; import { useMemo } from 'react'; -import { appThemes } from '@/lib/ui/AppThemes.ts'; +import { appThemes } from '@/modules/theme/services/AppThemes.ts'; import { createUpdateMetadataServerSettings, useMetadataServerSettings, } from '@/lib/metadata/metadataServerSettings.ts'; -import { MetadataThemeSettings } from '@/typings.ts'; import { makeToast } from '@/lib/ui/Toast.ts'; import { EmptyView } from '@/modules/core/components/placeholder/EmptyView.tsx'; import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { CreateThemeButton } from '@/screens/settings/appearance/theme/CreateThemeButton.tsx'; -import { ThemePreview } from '@/screens/settings/appearance/theme/ThemePreview.tsx'; +import { CreateThemeButton } from '@/modules/theme/components/CreateThemeButton.tsx'; +import { ThemePreview } from '@/modules/theme/components/ThemePreview.tsx'; +import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; export const ThemeList = () => { const { t } = useTranslation(); diff --git a/src/screens/settings/appearance/theme/ThemePreview.tsx b/src/modules/theme/components/ThemePreview.tsx similarity index 97% rename from src/screens/settings/appearance/theme/ThemePreview.tsx rename to src/modules/theme/components/ThemePreview.tsx index e2ababce..09f93c0d 100644 --- a/src/screens/settings/appearance/theme/ThemePreview.tsx +++ b/src/modules/theme/components/ThemePreview.tsx @@ -19,10 +19,10 @@ import IconButton from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; import EditIcon from '@mui/icons-material/Edit'; import { bindDialog, usePopupState } from 'material-ui-popup-state/hooks'; -import { ThemeModeContext } from '@/components/context/ThemeModeContext.tsx'; -import { AppTheme, hasMissingFonts, loadThemeFonts } from '@/lib/ui/AppThemes.ts'; +import { ThemeModeContext } from '@/modules/theme/contexts/ThemeModeContext.tsx'; +import { AppTheme, hasMissingFonts, loadThemeFonts } from '@/modules/theme/services/AppThemes.ts'; import { createTheme } from '@/theme.tsx'; -import { ThemeCreationDialog } from '@/screens/settings/appearance/theme/CreateThemeDialog.tsx'; +import { ThemeCreationDialog } from '@/modules/theme/components/CreateThemeDialog.tsx'; import { makeToast } from '@/lib/ui/Toast.ts'; import { TypographyMaxLines } from '@/modules/core/components/TypographyMaxLines.tsx'; diff --git a/src/components/context/ThemeModeContext.tsx b/src/modules/theme/contexts/ThemeModeContext.tsx similarity index 93% rename from src/components/context/ThemeModeContext.tsx rename to src/modules/theme/contexts/ThemeModeContext.tsx index 4b6fe96f..b31c403c 100644 --- a/src/components/context/ThemeModeContext.tsx +++ b/src/modules/theme/contexts/ThemeModeContext.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { AppThemes } from '@/lib/ui/AppThemes.ts'; +import { AppThemes } from '@/modules/theme/services/AppThemes.ts'; export enum ThemeMode { SYSTEM = 'system', diff --git a/src/modules/theme/services/AppThemes.ts b/src/modules/theme/services/AppThemes.ts new file mode 100644 index 00000000..2742c656 --- /dev/null +++ b/src/modules/theme/services/AppThemes.ts @@ -0,0 +1,102 @@ +/* + * 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 { ThemeOptions } from '@mui/material/styles'; +import WebFont from 'webfontloader'; +import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; +import { ControlledPromise } from '@/lib/ControlledPromise.ts'; +import { TBaseTheme, themes } from '@/modules/theme/Themes.ts'; + +export type AppThemes = keyof typeof themes | string; + +export type AppTheme = TBaseTheme & { id: AppThemes; isCustom: boolean }; + +export const appThemes = (Object.entries(themes) as [AppThemes, TBaseTheme][]).map(([id, theme]) => ({ + id, + ...theme, +})) satisfies AppTheme[]; + +export const getTheme = (id: AppThemes, customThemes: Record = {}): AppTheme => { + try { + const allThemes = { ...themes, ...customThemes }; + const theme = (allThemes[id as keyof typeof themes] as AppTheme) ?? themes.default; + + return { + // @ts-ignore - custom themes do not have a "getName" function + getName: () => id, + ...theme, + }; + } catch (e) { + defaultPromiseErrorHandler('getTheme')(e); + } + return { id, ...themes[id as keyof typeof themes] }; +}; + +export const isThemeNameUnique = (id: string, customThemes: Record): boolean => + Object.keys({ ...themes, ...customThemes }).every((themeId) => themeId.toLowerCase() !== id.toLowerCase()); + +const getFontsFromTheme = (obj: Record, fonts: string[] = []): string[] => { + const tmpFonts = [...fonts]; + + const propertyNames = Object.keys(obj); + for (const propertyName of propertyNames) { + const propertyValue = obj[propertyName]; + const propertyType = typeof obj[propertyName]; + + const isValidFontProperty = propertyName === 'fontFamily' && propertyType === 'string'; + if (isValidFontProperty) { + tmpFonts.push(propertyValue as string); + // eslint-disable-next-line no-continue + continue; + } + + const isObject = propertyType === 'object'; + if (isObject) { + tmpFonts.push(...getFontsFromTheme(propertyValue as Record, tmpFonts)); + } + } + + return [...new Set(tmpFonts)]; +}; + +const loadedFonts: string[] = []; + +export const hasMissingFonts = (theme: ThemeOptions): boolean => { + const themeFonts = getFontsFromTheme(theme.typography ?? {}); + return !!themeFonts.length && themeFonts.some((font) => !loadedFonts.includes(font)); +}; + +export const loadThemeFonts = async (theme: ThemeOptions): Promise => { + const themeFonts = getFontsFromTheme(theme.typography ?? {}); + const missingThemeFonts = themeFonts.filter((font) => !loadedFonts.includes(font)); + + if (!missingThemeFonts.length) { + return; + } + + const loadFontsPromise = new ControlledPromise(); + try { + WebFont.load({ + google: { + families: missingThemeFonts, + }, + active: () => { + loadedFonts.push(...missingThemeFonts); + loadFontsPromise.resolve(); + }, + inactive: () => { + loadFontsPromise.reject(); + }, + }); + } catch (e) { + defaultPromiseErrorHandler('AppThemes::loadFonts')(e); + loadFontsPromise.reject(e); + } + + await loadFontsPromise.promise; +}; diff --git a/src/screens/settings/appearance/Appearance.tsx b/src/screens/settings/Appearance.tsx similarity index 95% rename from src/screens/settings/appearance/Appearance.tsx rename to src/screens/settings/Appearance.tsx index 18142fcd..4f4ec6aa 100644 --- a/src/screens/settings/appearance/Appearance.tsx +++ b/src/screens/settings/Appearance.tsx @@ -16,15 +16,15 @@ import ListSubheader from '@mui/material/ListSubheader'; import Switch from '@mui/material/Switch'; import Link from '@mui/material/Link'; import { NavBarContext } from '@/components/context/NavbarContext.tsx'; -import { ThemeMode, ThemeModeContext } from '@/components/context/ThemeModeContext.tsx'; +import { ThemeMode, ThemeModeContext } from '@/modules/theme/contexts/ThemeModeContext.tsx'; import { Select } from '@/modules/core/components/inputs/Select.tsx'; import { MediaQuery } from '@/lib/ui/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 '@/lib/Languages.tsx'; -import { getTheme } from '@/lib/ui/AppThemes.ts'; -import { ThemeList } from '@/screens/settings/appearance/theme/ThemeList.tsx'; +import { getTheme } from '@/modules/theme/services/AppThemes.ts'; +import { ThemeList } from '@/modules/theme/components/ThemeList.tsx'; import { createUpdateMetadataServerSettings, useMetadataServerSettings, @@ -32,8 +32,8 @@ import { import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx'; import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { MetadataThemeSettings } from '@/typings.ts'; import { makeToast } from '@/lib/ui/Toast.ts'; +import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; export const Appearance = () => { const { t, i18n } = useTranslation(); diff --git a/src/theme.tsx b/src/theme.tsx index 1d83e6f5..932b60dc 100644 --- a/src/theme.tsx +++ b/src/theme.tsx @@ -17,9 +17,9 @@ import { useTheme, } from '@mui/material/styles'; import { useCallback } from 'react'; -import { ThemeMode } from '@/components/context/ThemeModeContext.tsx'; +import { ThemeMode } from '@/modules/theme/contexts/ThemeModeContext.tsx'; import { MediaQuery } from '@/lib/ui/MediaQuery.tsx'; -import { AppTheme, loadThemeFonts } from '@/lib/ui/AppThemes.ts'; +import { AppTheme, loadThemeFonts } from '@/modules/theme/services/AppThemes.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; const SCROLLBAR_SIZE = 14; diff --git a/src/typings.ts b/src/typings.ts index 1db5e6cb..d6d2ffe9 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -9,7 +9,6 @@ import { OverridableComponent } from '@mui/material/OverridableComponent'; import { SvgIconTypeMap } from '@mui/material/SvgIcon'; import { GetServerSettingsQuery, MetaType } from '@/lib/graphql/generated/graphql.ts'; -import { AppTheme } from '@/lib/ui/AppThemes.ts'; import { MetadataMigrationSettings } from '@/modules/migration/Migration.types.ts'; import { TranslationKey } from '@/Base.types.ts'; import { MangaMetadataKeys } from '@/modules/manga/MangaCard.types.tsx'; @@ -18,6 +17,7 @@ import { SourceMetadataKeys } from '@/modules/source/Source.types.ts'; import { MetadataTrackingSettings } from '@/modules/tracker/Tracker.types.ts'; import { CategoryMetadataKeys } from '@/modules/category/Category.types.ts'; import { MetadataUpdateSettings } from '@/modules/app-updates/AppUpdateChecker.types.ts'; +import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; export interface IMetadataMigration { appKeyPrefix?: { oldPrefix: string; newPrefix: string }; @@ -78,11 +78,6 @@ export type MetadataBrowseSettings = { hideLibraryEntries: boolean; }; -export type MetadataThemeSettings = { - customThemes: Record; - mangaThumbnailBackdrop: boolean; -}; - export type MetadataServerSettings = MetadataDownloadSettings & MetadataLibrarySettings & MetadataClientSettings &