From cb7498465931e1e424543937e2148a59baf1bd2b Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Wed, 25 Jun 2025 00:38:01 +0200 Subject: [PATCH] Fix constraining logic of stored client metadata By the time the constraining function was called, the stored values were still of type string and were not converted to the correct type yet. --- .../category/services/CategoryMetadata.ts | 17 +- src/modules/manga/services/MangaMetadata.ts | 14 +- src/modules/metadata/Metadata.constants.ts | 217 ++++++++++-------- .../metadata/services/MetadataConverter.ts | 24 +- .../metadata/services/MetadataReader.ts | 16 +- .../reader/services/ReaderSettingsMetadata.ts | 45 +--- .../services/ServerSettingsMetadata.ts | 33 +-- src/modules/source/services/SourceMetadata.ts | 29 +-- 8 files changed, 146 insertions(+), 249 deletions(-) diff --git a/src/modules/category/services/CategoryMetadata.ts b/src/modules/category/services/CategoryMetadata.ts index 13b7eb2b..a330bfbf 100644 --- a/src/modules/category/services/CategoryMetadata.ts +++ b/src/modules/category/services/CategoryMetadata.ts @@ -7,7 +7,6 @@ */ import { useEffect, useMemo } from 'react'; -import { jsonSaveParse } from '@/lib/HelperFunctions.ts'; import { requestUpdateCategoryMetadata } from '@/modules/metadata/services/MetadataUpdater.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { LibraryOptions } from '@/modules/library/Library.types.ts'; @@ -16,7 +15,6 @@ import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverte import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts'; import { AllowedMetadataValueTypes, - AppMetadataKeys, GqlMetaHolder, Metadata, MetadataHolder, @@ -45,24 +43,11 @@ const convertAppMetadataToGqlMetadata = ( hasStatus: metadata.hasStatus ? JSON.stringify(metadata.hasStatus) : undefined, }); -const convertGqlMetadataToAppMetadata = ( - metadata: Partial>, -): ICategoryMetadata => ({ - ...(metadata as unknown as ICategoryMetadata), - hasTrackerBinding: - jsonSaveParse(metadata.hasTrackerBinding as string) ?? - (undefined as any), - hasStatus: jsonSaveParse(metadata.hasStatus as string) ?? (undefined as any), -}); - const getCategoryMetadataWithDefaultValueFallback = ( meta: CategoryIdInfo & MetadataHolder, defaultMetadata: ICategoryMetadata = DEFAULT_CATEGORY_METADATA, useEffectFn?: typeof useEffect, -): ICategoryMetadata => - convertGqlMetadataToAppMetadata( - getMetadataFrom('category', meta, convertAppMetadataToGqlMetadata(defaultMetadata), undefined, useEffectFn), - ); +): ICategoryMetadata => getMetadataFrom('category', meta, defaultMetadata, undefined, useEffectFn); const getMetadata = ( metaHolder: CategoryIdInfo & GqlMetaHolder, diff --git a/src/modules/manga/services/MangaMetadata.ts b/src/modules/manga/services/MangaMetadata.ts index 663ede5d..dc9c1247 100644 --- a/src/modules/manga/services/MangaMetadata.ts +++ b/src/modules/manga/services/MangaMetadata.ts @@ -12,7 +12,6 @@ import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts'; import { MangaIdInfo, MangaMetadata, MangaMetadataKeys } from '@/modules/manga/Manga.types.ts'; import { AllowedMetadataValueTypes, - AppMetadataKeys, GqlMetaHolder, Metadata, MetadataHolder, @@ -20,7 +19,6 @@ import { import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts'; import { requestUpdateMangaMetadata } from '@/modules/metadata/services/MetadataUpdater.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { jsonSaveParse } from '@/lib/HelperFunctions.ts'; const DEFAULT_MANGA_METADATA: MangaMetadata = { ...DEFAULT_CHAPTER_OPTIONS, @@ -33,21 +31,11 @@ const convertAppMetadataToGqlMetadata = ( excludedScanlators: JSON.stringify(metadata.excludedScanlators), }); -const convertGqlMetadataToAppMetadata = ( - metadata: Partial>, -): MangaMetadata => ({ - ...(metadata as unknown as MangaMetadata), - excludedScanlators: jsonSaveParse(metadata.excludedScanlators as string) ?? [], -}); - const getMangaMetadataWithDefaultValueFallback = ( meta: MangaIdInfo & MetadataHolder, defaultMetadata: MangaMetadata = DEFAULT_MANGA_METADATA, useEffectFn?: typeof useEffect, -): MangaMetadata => - convertGqlMetadataToAppMetadata( - getMetadataFrom('manga', meta, convertAppMetadataToGqlMetadata(defaultMetadata), undefined, useEffectFn), - ); +): MangaMetadata => getMetadataFrom('manga', meta, defaultMetadata, undefined, useEffectFn); const getMetadata = ( metaHolder: MangaIdInfo & GqlMetaHolder, diff --git a/src/modules/metadata/Metadata.constants.ts b/src/modules/metadata/Metadata.constants.ts index 2005603c..b13156b2 100644 --- a/src/modules/metadata/Metadata.constants.ts +++ b/src/modules/metadata/Metadata.constants.ts @@ -6,6 +6,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +// eslint-disable-next-line import/no-extraneous-dependencies,no-restricted-imports +import deepmerge from '@mui/utils/deepmerge'; import { AppMetadataKeys, IMetadataMigration } from '@/modules/metadata/Metadata.types.ts'; import { IReaderSettings, @@ -23,173 +25,190 @@ import { PROGRESS_BAR_SIZE, SCROLL_AMOUNT, } from '@/modules/reader/constants/ReaderSettings.constants.tsx'; -import { coerceIn } from '@/lib/HelperFunctions.ts'; +import { coerceIn, jsonSaveParse } from '@/lib/HelperFunctions.ts'; import { DOWNLOAD_AHEAD } from '@/modules/downloads/Downloads.constants.ts'; import { MANGA_GRID_WIDTH } from '@/modules/settings/Settings.constants.ts'; +import { NullAndUndefined } from '@/Base.types.ts'; +import { SortSettings } from '@/modules/migration/Migration.types.ts'; +import { ISourceMetadata } from '@/modules/source/Source.types.ts'; +import { LibraryOptions } from '@/modules/library/Library.types.ts'; +import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; +import { TapZoneInvertMode } from '@/modules/reader/types/TapZoneLayout.types.ts'; export const APP_METADATA_KEY_PREFIX = 'webUI'; -// At the moment any non-primitive types need to be specified as "string" and handled in the according "MetadataService". -// "auto" can be used to try to automatically convert the value to a specific type (string, number, boolean, undefined, null) +const convertToTypeNullAndUndefined = (value: string, convertToType: (value: string) => T): NullAndUndefined => { + if (value === 'null') return null; + if (value === 'undefined') return undefined; + return convertToType(value); +}; +const convertToString = (value: string): string => value; +const convertToNumber = (value: string): number => +value; +const convertToBoolean = (value: string): boolean => value === 'true'; +const convertToStringNullAndUndefined = (value: string) => convertToTypeNullAndUndefined(value, convertToString); +const convertToBooleanNullAndUndefined = (value: string) => convertToTypeNullAndUndefined(value, convertToBoolean); +const convertToObject = (value: string, defaultValue: T): T => + deepmerge(defaultValue, jsonSaveParse(value) ?? defaultValue); + export const APP_METADATA: Record< AppMetadataKeys, { - type: 'auto' | 'string' | 'number' | 'boolean'; - toValidValue?: (value: any) => any; + convert: (value: string, defaultValue: any) => any; + toConstrainedValue?: (value: any) => any; } > = { migration: { - type: 'number', + convert: convertToNumber, }, deleteChaptersManuallyMarkedRead: { - type: 'boolean', + convert: convertToBoolean, }, deleteChaptersWhileReading: { - type: 'number', + convert: convertToNumber, }, deleteChaptersWithBookmark: { - type: 'boolean', + convert: convertToBoolean, }, downloadAheadLimit: { - type: 'number', - toValidValue: (value: number) => coerceIn(value, DOWNLOAD_AHEAD.min, DOWNLOAD_AHEAD.max), + convert: convertToNumber, + toConstrainedValue: (value: number) => coerceIn(value, DOWNLOAD_AHEAD.min, DOWNLOAD_AHEAD.max), }, showAddToLibraryCategorySelectDialog: { - type: 'boolean', + convert: convertToBoolean, }, ignoreFilters: { - type: 'boolean', + convert: convertToBoolean, }, removeMangaFromCategories: { - type: 'boolean', + convert: convertToBoolean, }, showTabSize: { - type: 'boolean', + convert: convertToBoolean, }, devices: { - type: 'string', // string[] + convert: convertToObject, }, migrateChapters: { - type: 'boolean', + convert: convertToBoolean, }, migrateCategories: { - type: 'boolean', + convert: convertToBoolean, }, migrateTracking: { - type: 'boolean', + convert: convertToBoolean, }, deleteChapters: { - type: 'boolean', + convert: convertToBoolean, }, migrateSortSettings: { - type: 'string', // SortSettings (object) + convert: convertToObject, }, hideLibraryEntries: { - type: 'boolean', + convert: convertToBoolean, }, updateProgressAfterReading: { - type: 'boolean', + convert: convertToBoolean, }, updateProgressManualMarkRead: { - type: 'boolean', + convert: convertToBoolean, }, webUIInformAvailableUpdate: { - type: 'boolean', + convert: convertToBoolean, }, serverInformAvailableUpdate: { - type: 'boolean', + convert: convertToBoolean, }, readerWidth: { - type: 'string', // object + convert: convertToObject, }, savedSearches: { - type: 'string', // object + convert: convertToObject, }, showContinueReadingButton: { - type: 'boolean', + convert: convertToBoolean, }, showDownloadBadge: { - type: 'boolean', + convert: convertToBoolean, }, showUnreadBadge: { - type: 'boolean', + convert: convertToBoolean, }, gridLayout: { - type: 'number', // GridLayout (enum) + convert: convertToNumber, // GridLayout (enum) }, sortBy: { - type: 'auto', // LibrarySortMode undefined null + convert: convertToStringNullAndUndefined, // LibrarySortMode }, sortDesc: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, hasDownloadedChapters: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, hasBookmarkedChapters: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, hasUnreadChapters: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, hasReadChapters: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, hasDuplicateChapters: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, hasTrackerBinding: { - type: 'string', // object + convert: convertToObject, }, hasStatus: { - type: 'string', // object + convert: convertToObject, }, customThemes: { - type: 'string', // object + convert: convertToObject, }, mangaThumbnailBackdrop: { - type: 'boolean', + convert: convertToBoolean, }, mangaDynamicColorSchemes: { - type: 'boolean', + convert: convertToBoolean, }, tapZoneLayout: { - type: 'number', // TapZoneLayouts (enum) + convert: convertToNumber, // TapZoneLayouts (enum) }, tapZoneInvertMode: { - type: 'string', // TapZoneInvertMode (object) + convert: convertToObject, // TapZoneInvertMode (object) }, readingDirection: { - type: 'number', // ReadingDirection (enum) + convert: convertToNumber, // ReadingDirection (enum) }, progressBarType: { - type: 'number', // ProgressBarType (enum) + convert: convertToNumber, // ProgressBarType (enum) }, progressBarSize: { - type: 'number', - toValidValue: (value: number) => coerceIn(value, PROGRESS_BAR_SIZE.min, PROGRESS_BAR_SIZE.max), + convert: convertToNumber, + toConstrainedValue: (value: number) => coerceIn(value, PROGRESS_BAR_SIZE.min, PROGRESS_BAR_SIZE.max), }, progressBarPosition: { - type: 'number', // ProgressBarPosition (enum) + convert: convertToNumber, // ProgressBarPosition (enum) }, progressBarPositionAutoVertical: { - type: 'number', // TProgressBarPositionAutoVertical (enum) + convert: convertToNumber, // TProgressBarPositionAutoVertical (enum) }, readingMode: { - type: 'number', // ReadingMode (enum) + convert: convertToNumber, // ReadingMode (enum) }, pageScaleMode: { - type: 'number', // ReaderPageScaleMode (enum) + convert: convertToNumber, // ReaderPageScaleMode (enum) }, shouldOffsetDoubleSpreads: { - type: 'boolean', + convert: convertToBoolean, }, exitMode: { - type: 'number', // ReaderExitMode (enum) + convert: convertToNumber, // ReaderExitMode (enum) }, customFilter: { - type: 'string', // ReaderCustomFilter (object) - toValidValue: (value: ReaderCustomFilter): ReaderCustomFilter => ({ + convert: convertToObject, + toConstrainedValue: (value: ReaderCustomFilter): ReaderCustomFilter => ({ ...value, brightness: { ...value.brightness, @@ -220,120 +239,120 @@ export const APP_METADATA: Record< }), }, shouldSkipDupChapters: { - type: 'boolean', + convert: convertToBoolean, }, isStaticNav: { - type: 'boolean', + convert: convertToBoolean, }, overlayMode: { - type: 'number', // ReaderOverlayMode (enum) + convert: convertToNumber, // ReaderOverlayMode (enum) }, shouldStretchPage: { - type: 'boolean', + convert: convertToBoolean, }, shouldShowPageNumber: { - type: 'boolean', + convert: convertToBoolean, }, backgroundColor: { - type: 'number', // ReaderBackgroundColor (enum) + convert: convertToNumber, // ReaderBackgroundColor (enum) }, pageGap: { - type: 'number', - toValidValue: (value: number) => coerceIn(value, PAGE_GAP.min, PAGE_GAP.max), + convert: convertToNumber, + toConstrainedValue: (value: number) => coerceIn(value, PAGE_GAP.min, PAGE_GAP.max), }, hotkeys: { - type: 'string', // object + convert: convertToObject, }, imagePreLoadAmount: { - type: 'number', - toValidValue: (value: number) => coerceIn(value, IMAGE_PRE_LOAD_AMOUNT.min, IMAGE_PRE_LOAD_AMOUNT.max), + convert: convertToNumber, + toConstrainedValue: (value: number) => coerceIn(value, IMAGE_PRE_LOAD_AMOUNT.min, IMAGE_PRE_LOAD_AMOUNT.max), }, shouldUseAutoWebtoonMode: { - type: 'boolean', + convert: convertToBoolean, }, autoScroll: { - type: 'string', // object - toValidValue: (value: IReaderSettings['autoScroll']): IReaderSettings['autoScroll'] => ({ + convert: convertToObject, + toConstrainedValue: (value: IReaderSettings['autoScroll']): IReaderSettings['autoScroll'] => ({ ...value, value: coerceIn(value.value, AUTO_SCROLL_SPEED.min, AUTO_SCROLL_SPEED.max), }), }, shouldShowReadingModePreview: { - type: 'boolean', + convert: convertToBoolean, }, shouldShowTapZoneLayoutPreview: { - type: 'boolean', + convert: convertToBoolean, }, shouldInformAboutMissingChapter: { - type: 'boolean', + convert: convertToBoolean, }, shouldInformAboutScanlatorChange: { - type: 'boolean', + convert: convertToBoolean, }, hideHistory: { - type: 'boolean', + convert: convertToBoolean, }, scrollAmount: { - type: 'number', // ReaderScrollAmount (enum) - toValidValue: (value: number) => coerceIn(value, SCROLL_AMOUNT.min, SCROLL_AMOUNT.max), + convert: convertToNumber, // ReaderScrollAmount (enum) + toConstrainedValue: (value: number) => coerceIn(value, SCROLL_AMOUNT.min, SCROLL_AMOUNT.max), }, reverse: { - type: 'boolean', + convert: convertToBoolean, }, bookmarked: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, downloaded: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, unread: { - type: 'auto', // boolean undefined null + convert: convertToBooleanNullAndUndefined, }, showChapterNumber: { - type: 'boolean', + convert: convertToBoolean, }, extensionLanguages: { - type: 'string', // string[] + convert: convertToObject, }, sourceLanguages: { - type: 'string', // string[] + convert: convertToObject, }, showNsfw: { - type: 'boolean', + convert: convertToBoolean, }, shouldUseInfiniteScroll: { - type: 'boolean', + convert: convertToBoolean, }, shouldShowTransitionPage: { - type: 'boolean', + convert: convertToBoolean, }, appTheme: { - type: 'string', + convert: convertToString, }, themeMode: { - type: 'string', // ThemeMode (enum) + convert: convertToString, // ThemeMode (enum) }, shouldUsePureBlackMode: { - type: 'boolean', + convert: convertToBoolean, }, mangaGridItemWidth: { - type: 'number', - toValidValue: (value: number) => coerceIn(value, MANGA_GRID_WIDTH.min, MANGA_GRID_WIDTH.max), + convert: convertToNumber, + toConstrainedValue: (value: number) => coerceIn(value, MANGA_GRID_WIDTH.min, MANGA_GRID_WIDTH.max), }, isPinned: { - type: 'boolean', + convert: convertToBoolean, }, isEnabled: { - type: 'boolean', + convert: convertToBoolean, }, lastUsedSourceId: { - type: 'string', + convert: convertToString, }, shouldShowOnlySourcesWithResults: { - type: 'boolean', + convert: convertToBoolean, }, excludedScanlators: { - type: 'string', // string[] + convert: convertToObject, }, } as const; diff --git a/src/modules/metadata/services/MetadataConverter.ts b/src/modules/metadata/services/MetadataConverter.ts index 5a939c05..03bad29d 100644 --- a/src/modules/metadata/services/MetadataConverter.ts +++ b/src/modules/metadata/services/MetadataConverter.ts @@ -13,28 +13,8 @@ import { APP_METADATA } from '@/modules/metadata/Metadata.constants.ts'; export const convertValueFromMetadata = ( key: string, value: string, -): T => { - const typeOfKey = APP_METADATA[key as AppMetadataKeys].type; - const isAutoType = typeOfKey === 'auto'; - - if ((isAutoType && !Number.isNaN(+value)) || typeOfKey === 'number') { - return +value as T; - } - - if ((isAutoType && (value === 'true' || value === 'false')) || typeOfKey === 'boolean') { - return (value === 'true') as T; - } - - if (isAutoType && value === 'undefined') { - return undefined as T; - } - - if (isAutoType && value === 'null') { - return null as T; - } - - return value as T; -}; + defaultValue: any, +): T => APP_METADATA[key as AppMetadataKeys].convert(value, defaultValue); export const convertFromGqlMeta = ( gqlMetadata?: MetaType[], diff --git a/src/modules/metadata/services/MetadataReader.ts b/src/modules/metadata/services/MetadataReader.ts index d9451d0d..86d60ce2 100644 --- a/src/modules/metadata/services/MetadataReader.ts +++ b/src/modules/metadata/services/MetadataReader.ts @@ -38,47 +38,47 @@ const getMetadataValueFrom = >>( +export function getMetadataFrom>>( type: 'global', metadataHolder: MetadataHolder, metadataWithDefaultValues: METADATA, prefixes?: string[], useEffectFn?: typeof useEffect, ): METADATA; -export function getMetadataFrom>>( +export function getMetadataFrom>>( type: 'manga', metadataHolder: MangaIdInfo & MetadataHolder, metadataWithDefaultValues: METADATA, prefixes?: string[], useEffectFn?: typeof useEffect, ): METADATA; -export function getMetadataFrom>>( +export function getMetadataFrom>>( type: 'chapter', metadataHolder: ChapterIdInfo & MetadataHolder, metadataWithDefaultValues: METADATA, prefixes?: string[], useEffectFn?: typeof useEffect, ): METADATA; -export function getMetadataFrom>>( +export function getMetadataFrom>>( type: 'category', metadataHolder: CategoryIdInfo & MetadataHolder, metadataWithDefaultValues: METADATA, prefixes?: string[], useEffectFn?: typeof useEffect, ): METADATA; -export function getMetadataFrom>>( +export function getMetadataFrom>>( type: 'source', metadataHolder: SourceIdInfo & MetadataHolder, metadataWithDefaultValues: METADATA, prefixes?: string[], useEffectFn?: typeof useEffect, ): METADATA; -export function getMetadataFrom>>( +export function getMetadataFrom>>( type: MetadataHolderType, metadataHolder: | MetadataHolder diff --git a/src/modules/reader/services/ReaderSettingsMetadata.ts b/src/modules/reader/services/ReaderSettingsMetadata.ts index 4c18729a..107492c5 100644 --- a/src/modules/reader/services/ReaderSettingsMetadata.ts +++ b/src/modules/reader/services/ReaderSettingsMetadata.ts @@ -8,7 +8,6 @@ import { useEffect, useMemo } from 'react'; // eslint-disable-next-line import/no-extraneous-dependencies,no-restricted-imports -import { deepmerge } from '@mui/utils'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestUpdateMangaMetadata, @@ -20,14 +19,12 @@ import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverte import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts'; import { AllowedMetadataValueTypes, - AppMetadataKeys, GqlMetaHolder, Metadata, MetadataHolder, MetadataHolderType, } from '@/modules/metadata/Metadata.types.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { jsonSaveParse } from '@/lib/HelperFunctions.ts'; import { MangaIdInfo } from '@/modules/manga/Manga.types.ts'; import { DEFAULT_READER_SETTINGS, @@ -103,47 +100,19 @@ export const DEFAULT_READER_SETTINGS_WITH_DEFAULT_FLAG = convertToSettingsWithDe { meta: convertSettingsToMetadata(DEFAULT_READER_SETTINGS) as Metadata }, ); -const convertMetadataToSettings = ( - metadata: Partial>, - defaultSettings: IReaderSettings, -): IReaderSettings => ({ - ...(metadata as unknown as IReaderSettings), - tapZoneInvertMode: - jsonSaveParse((metadata.tapZoneInvertMode as string) ?? '') ?? - defaultSettings.tapZoneInvertMode, - customFilter: deepmerge( - defaultSettings.customFilter, - jsonSaveParse((metadata.customFilter as string) ?? '') ?? - defaultSettings.customFilter, - ), - readerWidth: - jsonSaveParse((metadata.readerWidth as string) ?? '') ?? - defaultSettings.readerWidth, - hotkeys: { - ...defaultSettings.hotkeys, - ...(jsonSaveParse((metadata.hotkeys as string) ?? '') ?? defaultSettings.hotkeys), - }, - autoScroll: - jsonSaveParse((metadata.autoScroll as string) ?? '') ?? - defaultSettings.autoScroll, -}); - export const getReaderSettings = ( type: Extract, metadataHolder: (MangaIdInfo & MetadataHolder) | MetadataHolder, defaultSettings: IReaderSettings = DEFAULT_READER_SETTINGS, useEffectFn?: typeof useEffect, profile?: ReadingMode, -) => - convertMetadataToSettings( - getMetadataFrom( - type as Parameters[0], - metadataHolder as Parameters[1], - convertSettingsToMetadata(defaultSettings), - profile !== undefined ? [profile.toString()] : undefined, - useEffectFn, - ), - defaultSettings as IReaderSettings, +): IReaderSettings => + getMetadataFrom( + type as Parameters[0], + metadataHolder as Parameters[1], + defaultSettings, + profile !== undefined ? [profile.toString()] : undefined, + useEffectFn, ); function getReaderSettingsWithDefaultValueFallback( diff --git a/src/modules/settings/services/ServerSettingsMetadata.ts b/src/modules/settings/services/ServerSettingsMetadata.ts index c066e0d2..967b8ebf 100644 --- a/src/modules/settings/services/ServerSettingsMetadata.ts +++ b/src/modules/settings/services/ServerSettingsMetadata.ts @@ -9,15 +9,12 @@ import { useEffect, useMemo } from 'react'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestUpdateServerMetadata } from '@/modules/metadata/services/MetadataUpdater.ts'; -import { jsonSaveParse } from '@/lib/HelperFunctions.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { MetadataMigrationSettings } from '@/modules/migration/Migration.types.ts'; -import { MetadataThemeSettings } from '@/modules/theme/AppTheme.types.ts'; import { SERVER_SETTINGS_METADATA_DEFAULT } from '@/modules/settings/Settings.constants.ts'; import { MetadataServerSettingKeys, MetadataServerSettings } from '@/modules/settings/Settings.types.ts'; import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts'; import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts'; -import { AllowedMetadataValueTypes, AppMetadataKeys, Metadata } from '@/modules/metadata/Metadata.types.ts'; +import { AllowedMetadataValueTypes, Metadata } from '@/modules/metadata/Metadata.types.ts'; export const convertSettingsToMetadata = ( settings: Partial, @@ -30,37 +27,11 @@ export const convertSettingsToMetadata = ( sourceLanguages: JSON.stringify(settings.sourceLanguages), }); -export const convertMetadataToSettings = ( - metadata: Partial>, -): MetadataServerSettings => - ({ - ...SERVER_SETTINGS_METADATA_DEFAULT, - ...(metadata as unknown as MetadataServerSettings), - devices: - jsonSaveParse((metadata.devices as string) ?? '') ?? SERVER_SETTINGS_METADATA_DEFAULT.devices, - customThemes: - jsonSaveParse((metadata.customThemes as string) ?? '') ?? - SERVER_SETTINGS_METADATA_DEFAULT.customThemes, - migrateSortSettings: - jsonSaveParse( - (metadata.migrateSortSettings as string) ?? '', - ) ?? SERVER_SETTINGS_METADATA_DEFAULT.migrateSortSettings, - extensionLanguages: - jsonSaveParse((metadata.extensionLanguages as string) ?? '') ?? - SERVER_SETTINGS_METADATA_DEFAULT.extensionLanguages, - sourceLanguages: - jsonSaveParse((metadata.sourceLanguages as string) ?? '') ?? - SERVER_SETTINGS_METADATA_DEFAULT.sourceLanguages, - }) satisfies MetadataServerSettings; - const getMetadataServerSettingsWithDefaultFallback = ( meta?: Metadata, defaultSettings: MetadataServerSettings = SERVER_SETTINGS_METADATA_DEFAULT, useEffectFn?: typeof useEffect, -): MetadataServerSettings => - convertMetadataToSettings( - getMetadataFrom('global', { meta }, convertSettingsToMetadata(defaultSettings), undefined, useEffectFn), - ); +): MetadataServerSettings => getMetadataFrom('global', { meta }, defaultSettings, undefined, useEffectFn); export const useMetadataServerSettings = (): { metadata?: Metadata; diff --git a/src/modules/source/services/SourceMetadata.ts b/src/modules/source/services/SourceMetadata.ts index ec72839a..c7bc2f82 100644 --- a/src/modules/source/services/SourceMetadata.ts +++ b/src/modules/source/services/SourceMetadata.ts @@ -7,18 +7,12 @@ */ import { useEffect, useMemo } from 'react'; -import { jsonSaveParse } from '@/lib/HelperFunctions.ts'; import { requestUpdateSourceMetadata } from '@/modules/metadata/services/MetadataUpdater.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { ISourceMetadata, SourceIdInfo, SourceMetadataKeys } from '@/modules/source/Source.types.ts'; import { convertFromGqlMeta } from '@/modules/metadata/services/MetadataConverter.ts'; import { getMetadataFrom } from '@/modules/metadata/services/MetadataReader.ts'; -import { - AllowedMetadataValueTypes, - AppMetadataKeys, - GqlMetaHolder, - Metadata, -} from '@/modules/metadata/Metadata.types.ts'; +import { AllowedMetadataValueTypes, GqlMetaHolder, Metadata } from '@/modules/metadata/Metadata.types.ts'; const DEFAULT_SOURCE_METADATA: ISourceMetadata = { savedSearches: undefined, @@ -33,22 +27,13 @@ const convertAppMetadataToGqlMetadata = ( savedSearches: metadata.savedSearches ? JSON.stringify(metadata.savedSearches) : undefined, }); -const convertGqlMetadataToAppMetadata = ( - metadata: Partial>, -): ISourceMetadata => ({ - ...(metadata as unknown as ISourceMetadata), - savedSearches: jsonSaveParse(metadata.savedSearches as string) ?? undefined, -}); - const getMetadata = (metaHolder: SourceIdInfo & GqlMetaHolder, useEffectFn?: typeof useEffect): ISourceMetadata => - convertGqlMetadataToAppMetadata( - getMetadataFrom( - 'source', - { ...metaHolder, meta: convertFromGqlMeta(metaHolder.meta) }, - convertAppMetadataToGqlMetadata(DEFAULT_SOURCE_METADATA), - undefined, - useEffectFn, - ), + getMetadataFrom( + 'source', + { ...metaHolder, meta: convertFromGqlMeta(metaHolder.meta) }, + DEFAULT_SOURCE_METADATA, + undefined, + useEffectFn, ); export const getSourceMetadata = (metaHolder: SourceIdInfo & GqlMetaHolder): ISourceMetadata => getMetadata(metaHolder);