From 4d7eb74a561eea993d1c9483b232df75fc822558 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sun, 25 Jan 2026 17:31:02 +0100 Subject: [PATCH] Merge "selected source/extension" languages --- CHANGELOG.md | 1 + src/base/components/inputs/LanguageSelect.tsx | 4 +- src/features/browse/Browse.types.ts | 3 +- src/features/browse/extensions/Extensions.tsx | 6 +-- src/features/metadata/Metadata.constants.ts | 37 +++++++++++++++---- src/features/metadata/Metadata.types.ts | 2 +- .../metadata/services/MetadataMigrations.ts | 3 +- src/features/settings/Settings.constants.ts | 3 +- .../services/ServerSettingsMetadata.ts | 3 +- src/features/source/services/Sources.ts | 8 ++-- 10 files changed, 46 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0242c96..d88fe086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Theme**) Increase max length of custom theme names to 32 (previously 16) - (**Theme**) Change "pure black mode" paper background color to true black - (**Library**) Improve library manga sorting +- (**Browse**) Merge languages filter of the sources and extensions into one ### Fixed - (**Library**) Fix total library size chip color in light mode diff --git a/src/base/components/inputs/LanguageSelect.tsx b/src/base/components/inputs/LanguageSelect.tsx index 09298910..c0fc0ca4 100644 --- a/src/base/components/inputs/LanguageSelect.tsx +++ b/src/base/components/inputs/LanguageSelect.tsx @@ -38,7 +38,9 @@ export function LanguageSelect({ selectedLanguages, setSelectedLanguages, langua const languagesSortedBySelectState = useMemo( () => toUniqueLanguageCodes([ - ...tmpSelectedLanguages.toSorted(languageSortComparator), + ...tmpSelectedLanguages + .filter((language) => languages.includes(language)) + .toSorted(languageSortComparator), ...languages.toSorted(languageSortComparator), ]), [languages, tmpSelectedLanguages], diff --git a/src/features/browse/Browse.types.ts b/src/features/browse/Browse.types.ts index 87b90eb2..23ded639 100644 --- a/src/features/browse/Browse.types.ts +++ b/src/features/browse/Browse.types.ts @@ -10,8 +10,7 @@ import { SourceIdInfo } from '@/features/source/Source.types.ts'; export type MetadataBrowseSettings = { hideLibraryEntries: boolean; - extensionLanguages: string[]; - sourceLanguages: string[]; + browseLanguages: string[]; showNsfw: boolean; lastUsedSourceId: SourceIdInfo['id'] | null; shouldShowOnlySourcesWithResults: boolean; diff --git a/src/features/browse/extensions/Extensions.tsx b/src/features/browse/extensions/Extensions.tsx index 42dcc94f..01d93d0c 100644 --- a/src/features/browse/extensions/Extensions.tsx +++ b/src/features/browse/extensions/Extensions.tsx @@ -129,10 +129,10 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) { requestManager.useExtensionListFetch(); const { - settings: { extensionLanguages: shownLangs, showNsfw }, + settings: { browseLanguages: shownLangs, showNsfw }, } = useMetadataServerSettings(); const updateMetadataServerSettings = createUpdateMetadataServerSettings< - keyof Pick + keyof Pick >((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e))); const [query] = useQueryParam(SearchParam.QUERY, StringParam); @@ -220,7 +220,7 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) { - updateMetadataServerSettings('extensionLanguages', languages) + updateMetadataServerSettings('browseLanguages', languages) } languages={allLangs} /> diff --git a/src/features/metadata/Metadata.constants.ts b/src/features/metadata/Metadata.constants.ts index e3d93ad9..61dfc0fc 100644 --- a/src/features/metadata/Metadata.constants.ts +++ b/src/features/metadata/Metadata.constants.ts @@ -35,6 +35,7 @@ import { MetadataThemeSettings } from '@/features/theme/AppTheme.types.ts'; import { TapZoneInvertMode } from '@/features/reader/tap-zones/TapZoneLayout.types.ts'; import { detectLocale, getISOLanguage } from '@/lib/ISOLanguageUtil.ts'; import { i18nResources } from '@/i18n'; +import { toUniqueLanguageCodes } from '@/base/utils/Languages.ts'; export const APP_METADATA_KEY_PREFIX = 'webUI'; @@ -333,10 +334,7 @@ export const APP_METADATA: Record< showChapterNumber: { convert: convertToBoolean, }, - extensionLanguages: { - convert: convertToObject, - }, - sourceLanguages: { + browseLanguages: { convert: convertToObject, }, showNsfw: { @@ -437,8 +435,7 @@ export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [ // browse 'hideLibraryEntries', - 'extensionLanguages', - 'sourceLanguages', + 'browseLanguages', 'showNsfw', 'lastUsedSourceId', 'shouldShowOnlySourcesWithResults', @@ -490,11 +487,14 @@ export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [ * getting migrated, the key in the value migration is the "old" key (before the migration to the * new key). * + * For new metadata migrations, the value migrations have already been applied while the key migrations are still outstanding (same as for the value migrations) + * * Migration order (function "applyMetadataMigrations"): * 1. app metadata key prefix * 2. app metadata values - * 3. app metadata keys - * 4. app metadata keys deletion + * 3. create new app metadata with values from existing metadata + * 4. app metadata keys + * 5. app metadata keys deletion * * @example * // changes: @@ -666,4 +666,25 @@ export const METADATA_MIGRATIONS: IMetadataMigration[] = [ }, ], }, + { + values: [ + { + key: 'sourceLanguages', + oldValue: /^\[.*]$/g, + newValue: (sourceLanguagesValue, key, oldMetadata) => { + const extensionLanguagesKey = key.replace('sourceLanguages', 'extensionLanguages'); + const extensionLanguagesValue = oldMetadata[extensionLanguagesKey]; + + const convertedSourceLanguages = convertToObject(sourceLanguagesValue, []); + const convertedExtensionLanguages = convertToObject(extensionLanguagesValue, []); + + return JSON.stringify( + toUniqueLanguageCodes([...convertedSourceLanguages, ...convertedExtensionLanguages]), + ); + }, + }, + ], + keys: [{ oldKey: 'sourceLanguages', newKey: 'browseLanguages' }], + deleteKeys: ['sourceLanguages', 'extensionLanguages'], + }, ]; diff --git a/src/features/metadata/Metadata.types.ts b/src/features/metadata/Metadata.types.ts index c0ba75f4..fcba1a9a 100644 --- a/src/features/metadata/Metadata.types.ts +++ b/src/features/metadata/Metadata.types.ts @@ -22,7 +22,7 @@ export interface IMetadataMigration { */ key?: string; oldValue: string | RegExp | undefined; - newValue: string | ((oldValue: string) => string); + newValue: string | ((oldValue: string, key: string, oldMetadata: Metadata) => string); }[]; keys?: { oldKey: string; newKey: string }[]; deleteKeys?: string[]; diff --git a/src/features/metadata/services/MetadataMigrations.ts b/src/features/metadata/services/MetadataMigrations.ts index 90059d31..cf452698 100644 --- a/src/features/metadata/services/MetadataMigrations.ts +++ b/src/features/metadata/services/MetadataMigrations.ts @@ -87,7 +87,8 @@ const applyMetadataValueMigration = (meta: Metadata, migration: IMetadataMigrati (oldValue === undefined && meta[metaKey] === oldValue) || (oldValue !== undefined && meta[metaKey].match(oldValue)) ) { - migratedMetadata[metaKey] = typeof newValue === 'function' ? newValue(meta[metaKey]) : newValue; + migratedMetadata[metaKey] = + typeof newValue === 'function' ? newValue(meta[metaKey], metaKey, appMetadata) : newValue; } }; diff --git a/src/features/settings/Settings.constants.ts b/src/features/settings/Settings.constants.ts index cacde961..19e363cb 100644 --- a/src/features/settings/Settings.constants.ts +++ b/src/features/settings/Settings.constants.ts @@ -68,8 +68,7 @@ export const SERVER_SETTINGS_METADATA_DEFAULT: MetadataServerSettings = { // browse hideLibraryEntries: false, - extensionLanguages: getDefaultLanguages(), - sourceLanguages: getDefaultLanguages(), + browseLanguages: getDefaultLanguages(), showNsfw: true, lastUsedSourceId: null, shouldShowOnlySourcesWithResults: true, diff --git a/src/features/settings/services/ServerSettingsMetadata.ts b/src/features/settings/services/ServerSettingsMetadata.ts index 19834d36..f289d9ab 100644 --- a/src/features/settings/services/ServerSettingsMetadata.ts +++ b/src/features/settings/services/ServerSettingsMetadata.ts @@ -23,8 +23,7 @@ export const convertSettingsToMetadata = ( devices: JSON.stringify(settings.devices), customThemes: JSON.stringify(settings.customThemes), migrateSortSettings: JSON.stringify(settings.migrateSortSettings), - extensionLanguages: JSON.stringify(settings.extensionLanguages), - sourceLanguages: JSON.stringify(settings.sourceLanguages), + browseLanguages: JSON.stringify(settings.browseLanguages), }); const getMetadataServerSettingsWithDefaultFallback = ( diff --git a/src/features/source/services/Sources.ts b/src/features/source/services/Sources.ts index 1ba713ae..19c353da 100644 --- a/src/features/source/services/Sources.ts +++ b/src/features/source/services/Sources.ts @@ -157,16 +157,16 @@ export class Sources { } { const { t } = useLingui(); const { - settings: { sourceLanguages }, + settings: { browseLanguages }, } = useMetadataServerSettings(); - const updateSetting = createUpdateMetadataServerSettings<'sourceLanguages'>((e) => + const updateSetting = createUpdateMetadataServerSettings<'browseLanguages'>((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)), ); - const setLanguages = useCallback((languages: string[]) => updateSetting('sourceLanguages', languages), []); + const setLanguages = useCallback((languages: string[]) => updateSetting('browseLanguages', languages), []); return { - languages: sourceLanguages, + languages: browseLanguages, setLanguages, }; }