Merge "selected source/extension" languages

This commit is contained in:
schroda
2026-01-25 17:31:02 +01:00
parent dd1f5bd218
commit 4d7eb74a56
10 changed files with 46 additions and 24 deletions

View File

@@ -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**) Increase max length of custom theme names to 32 (previously 16)
- (**Theme**) Change "pure black mode" paper background color to true black - (**Theme**) Change "pure black mode" paper background color to true black
- (**Library**) Improve library manga sorting - (**Library**) Improve library manga sorting
- (**Browse**) Merge languages filter of the sources and extensions into one
### Fixed ### Fixed
- (**Library**) Fix total library size chip color in light mode - (**Library**) Fix total library size chip color in light mode

View File

@@ -38,7 +38,9 @@ export function LanguageSelect({ selectedLanguages, setSelectedLanguages, langua
const languagesSortedBySelectState = useMemo( const languagesSortedBySelectState = useMemo(
() => () =>
toUniqueLanguageCodes([ toUniqueLanguageCodes([
...tmpSelectedLanguages.toSorted(languageSortComparator), ...tmpSelectedLanguages
.filter((language) => languages.includes(language))
.toSorted(languageSortComparator),
...languages.toSorted(languageSortComparator), ...languages.toSorted(languageSortComparator),
]), ]),
[languages, tmpSelectedLanguages], [languages, tmpSelectedLanguages],

View File

@@ -10,8 +10,7 @@ import { SourceIdInfo } from '@/features/source/Source.types.ts';
export type MetadataBrowseSettings = { export type MetadataBrowseSettings = {
hideLibraryEntries: boolean; hideLibraryEntries: boolean;
extensionLanguages: string[]; browseLanguages: string[];
sourceLanguages: string[];
showNsfw: boolean; showNsfw: boolean;
lastUsedSourceId: SourceIdInfo['id'] | null; lastUsedSourceId: SourceIdInfo['id'] | null;
shouldShowOnlySourcesWithResults: boolean; shouldShowOnlySourcesWithResults: boolean;

View File

@@ -129,10 +129,10 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
requestManager.useExtensionListFetch(); requestManager.useExtensionListFetch();
const { const {
settings: { extensionLanguages: shownLangs, showNsfw }, settings: { browseLanguages: shownLangs, showNsfw },
} = useMetadataServerSettings(); } = useMetadataServerSettings();
const updateMetadataServerSettings = createUpdateMetadataServerSettings< const updateMetadataServerSettings = createUpdateMetadataServerSettings<
keyof Pick<MetadataBrowseSettings, 'extensionLanguages'> keyof Pick<MetadataBrowseSettings, 'browseLanguages'>
>((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e))); >((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)));
const [query] = useQueryParam(SearchParam.QUERY, StringParam); const [query] = useQueryParam(SearchParam.QUERY, StringParam);
@@ -220,7 +220,7 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
<LanguageSelect <LanguageSelect
selectedLanguages={shownLangs} selectedLanguages={shownLangs}
setSelectedLanguages={(languages: string[]) => setSelectedLanguages={(languages: string[]) =>
updateMetadataServerSettings('extensionLanguages', languages) updateMetadataServerSettings('browseLanguages', languages)
} }
languages={allLangs} languages={allLangs}
/> />

View File

@@ -35,6 +35,7 @@ import { MetadataThemeSettings } from '@/features/theme/AppTheme.types.ts';
import { TapZoneInvertMode } from '@/features/reader/tap-zones/TapZoneLayout.types.ts'; import { TapZoneInvertMode } from '@/features/reader/tap-zones/TapZoneLayout.types.ts';
import { detectLocale, getISOLanguage } from '@/lib/ISOLanguageUtil.ts'; import { detectLocale, getISOLanguage } from '@/lib/ISOLanguageUtil.ts';
import { i18nResources } from '@/i18n'; import { i18nResources } from '@/i18n';
import { toUniqueLanguageCodes } from '@/base/utils/Languages.ts';
export const APP_METADATA_KEY_PREFIX = 'webUI'; export const APP_METADATA_KEY_PREFIX = 'webUI';
@@ -333,10 +334,7 @@ export const APP_METADATA: Record<
showChapterNumber: { showChapterNumber: {
convert: convertToBoolean, convert: convertToBoolean,
}, },
extensionLanguages: { browseLanguages: {
convert: convertToObject<string[]>,
},
sourceLanguages: {
convert: convertToObject<string[]>, convert: convertToObject<string[]>,
}, },
showNsfw: { showNsfw: {
@@ -437,8 +435,7 @@ export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [
// browse // browse
'hideLibraryEntries', 'hideLibraryEntries',
'extensionLanguages', 'browseLanguages',
'sourceLanguages',
'showNsfw', 'showNsfw',
'lastUsedSourceId', 'lastUsedSourceId',
'shouldShowOnlySourcesWithResults', '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 * getting migrated, the key in the value migration is the "old" key (before the migration to the
* new key). * 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"): * Migration order (function "applyMetadataMigrations"):
* 1. app metadata key prefix * 1. app metadata key prefix
* 2. app metadata values * 2. app metadata values
* 3. app metadata keys * 3. create new app metadata with values from existing metadata
* 4. app metadata keys deletion * 4. app metadata keys
* 5. app metadata keys deletion
* *
* @example * @example
* // changes: * // 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<string[]>(sourceLanguagesValue, []);
const convertedExtensionLanguages = convertToObject<string[]>(extensionLanguagesValue, []);
return JSON.stringify(
toUniqueLanguageCodes([...convertedSourceLanguages, ...convertedExtensionLanguages]),
);
},
},
],
keys: [{ oldKey: 'sourceLanguages', newKey: 'browseLanguages' }],
deleteKeys: ['sourceLanguages', 'extensionLanguages'],
},
]; ];

View File

@@ -22,7 +22,7 @@ export interface IMetadataMigration {
*/ */
key?: string; key?: string;
oldValue: string | RegExp | undefined; oldValue: string | RegExp | undefined;
newValue: string | ((oldValue: string) => string); newValue: string | ((oldValue: string, key: string, oldMetadata: Metadata) => string);
}[]; }[];
keys?: { oldKey: string; newKey: string }[]; keys?: { oldKey: string; newKey: string }[];
deleteKeys?: string[]; deleteKeys?: string[];

View File

@@ -87,7 +87,8 @@ const applyMetadataValueMigration = (meta: Metadata, migration: IMetadataMigrati
(oldValue === undefined && meta[metaKey] === oldValue) || (oldValue === undefined && meta[metaKey] === oldValue) ||
(oldValue !== undefined && meta[metaKey].match(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;
} }
}; };

View File

@@ -68,8 +68,7 @@ export const SERVER_SETTINGS_METADATA_DEFAULT: MetadataServerSettings = {
// browse // browse
hideLibraryEntries: false, hideLibraryEntries: false,
extensionLanguages: getDefaultLanguages(), browseLanguages: getDefaultLanguages(),
sourceLanguages: getDefaultLanguages(),
showNsfw: true, showNsfw: true,
lastUsedSourceId: null, lastUsedSourceId: null,
shouldShowOnlySourcesWithResults: true, shouldShowOnlySourcesWithResults: true,

View File

@@ -23,8 +23,7 @@ export const convertSettingsToMetadata = (
devices: JSON.stringify(settings.devices), devices: JSON.stringify(settings.devices),
customThemes: JSON.stringify(settings.customThemes), customThemes: JSON.stringify(settings.customThemes),
migrateSortSettings: JSON.stringify(settings.migrateSortSettings), migrateSortSettings: JSON.stringify(settings.migrateSortSettings),
extensionLanguages: JSON.stringify(settings.extensionLanguages), browseLanguages: JSON.stringify(settings.browseLanguages),
sourceLanguages: JSON.stringify(settings.sourceLanguages),
}); });
const getMetadataServerSettingsWithDefaultFallback = ( const getMetadataServerSettingsWithDefaultFallback = (

View File

@@ -157,16 +157,16 @@ export class Sources {
} { } {
const { t } = useLingui(); const { t } = useLingui();
const { const {
settings: { sourceLanguages }, settings: { browseLanguages },
} = useMetadataServerSettings(); } = useMetadataServerSettings();
const updateSetting = createUpdateMetadataServerSettings<'sourceLanguages'>((e) => const updateSetting = createUpdateMetadataServerSettings<'browseLanguages'>((e) =>
makeToast(t`Failed to save changes`, 'error', getErrorMessage(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 { return {
languages: sourceLanguages, languages: browseLanguages,
setLanguages, setLanguages,
}; };
} }