Improve metadata value conversion

The current approach has issues with numbers of type long
This commit is contained in:
schroda
2025-05-17 23:17:36 +02:00
parent 822e47084e
commit bf90d95266
3 changed files with 97 additions and 90 deletions

View File

@@ -12,91 +12,93 @@ import { DEFAULT_READER_SETTINGS } from '@/modules/reader/constants/ReaderSettin
export const APP_METADATA_KEY_PREFIX = 'webUI'; export const APP_METADATA_KEY_PREFIX = 'webUI';
const APP_METADATA_OBJECT: Record<AppMetadataKeys, undefined> = { // At the moment any non-primitive types need to be specified as "string" and handled in the according "MetadataService".
migration: undefined, // "auto" can be used to try to automatically convert the value to a specific type (string, number, boolean, undefined, null)
deleteChaptersManuallyMarkedRead: undefined, export const APP_METADATA_KEY_TO_TYPE = {
deleteChaptersWhileReading: undefined, migration: 'number',
deleteChaptersWithBookmark: undefined, deleteChaptersManuallyMarkedRead: 'boolean',
downloadAheadLimit: undefined, deleteChaptersWhileReading: 'number',
showAddToLibraryCategorySelectDialog: undefined, deleteChaptersWithBookmark: 'boolean',
ignoreFilters: undefined, downloadAheadLimit: 'number',
removeMangaFromCategories: undefined, showAddToLibraryCategorySelectDialog: 'boolean',
showTabSize: undefined, ignoreFilters: 'boolean',
devices: undefined, removeMangaFromCategories: 'boolean',
migrateChapters: undefined, showTabSize: 'boolean',
migrateCategories: undefined, devices: 'string', // string[]
migrateTracking: undefined, migrateChapters: 'boolean',
deleteChapters: undefined, migrateCategories: 'boolean',
migrateSortSettings: undefined, migrateTracking: 'boolean',
hideLibraryEntries: undefined, deleteChapters: 'boolean',
updateProgressAfterReading: undefined, migrateSortSettings: 'string', // SortSettings (object)
updateProgressManualMarkRead: undefined, hideLibraryEntries: 'boolean',
webUIInformAvailableUpdate: undefined, updateProgressAfterReading: 'boolean',
serverInformAvailableUpdate: undefined, updateProgressManualMarkRead: 'boolean',
readerWidth: undefined, webUIInformAvailableUpdate: 'boolean',
savedSearches: undefined, serverInformAvailableUpdate: 'boolean',
showContinueReadingButton: undefined, readerWidth: 'string', // object
showDownloadBadge: undefined, savedSearches: 'string', // object
showUnreadBadge: undefined, showContinueReadingButton: 'boolean',
gridLayout: undefined, showDownloadBadge: 'boolean',
sortBy: undefined, showUnreadBadge: 'boolean',
sortDesc: undefined, gridLayout: 'number', // GridLayout (enum)
hasDownloadedChapters: undefined, sortBy: 'auto', // LibrarySortMode undefined null
hasBookmarkedChapters: undefined, sortDesc: 'auto', // boolean undefined null
hasUnreadChapters: undefined, hasDownloadedChapters: 'auto', // boolean undefined null
hasReadChapters: undefined, hasBookmarkedChapters: 'auto', // boolean undefined null
hasDuplicateChapters: undefined, hasUnreadChapters: 'auto', // boolean undefined null
hasTrackerBinding: undefined, hasReadChapters: 'auto', // boolean undefined null
hasStatus: undefined, hasDuplicateChapters: 'auto', // boolean undefined null
customThemes: undefined, hasTrackerBinding: 'string', // object
mangaThumbnailBackdrop: undefined, hasStatus: 'string', // object
mangaDynamicColorSchemes: undefined, customThemes: 'string', // object
tapZoneLayout: undefined, mangaThumbnailBackdrop: 'boolean',
tapZoneInvertMode: undefined, mangaDynamicColorSchemes: 'boolean',
readingDirection: undefined, tapZoneLayout: 'number', // TapZoneLayouts (enum)
progressBarType: undefined, tapZoneInvertMode: 'string', // TapZoneInvertMode (object)
progressBarSize: undefined, readingDirection: 'number', // ReadingDirection (enum)
progressBarPosition: undefined, progressBarType: 'number', // ProgressBarType (enum)
progressBarPositionAutoVertical: undefined, progressBarSize: 'number',
readingMode: undefined, progressBarPosition: 'number', // ProgressBarPosition (enum)
pageScaleMode: undefined, progressBarPositionAutoVertical: 'number', // TProgressBarPositionAutoVertical (enum)
shouldOffsetDoubleSpreads: undefined, readingMode: 'number', // ReadingMode (enum)
exitMode: undefined, pageScaleMode: 'number', // ReaderPageScaleMode (enum)
customFilter: undefined, shouldOffsetDoubleSpreads: 'boolean',
shouldSkipDupChapters: undefined, exitMode: 'number', // ReaderExitMode (enum)
isStaticNav: undefined, customFilter: 'string', // ReaderCustomFilter (object)
overlayMode: undefined, shouldSkipDupChapters: 'boolean',
shouldStretchPage: undefined, isStaticNav: 'boolean',
shouldShowPageNumber: undefined, overlayMode: 'number', // ReaderOverlayMode (enum)
backgroundColor: undefined, shouldStretchPage: 'boolean',
pageGap: undefined, shouldShowPageNumber: 'boolean',
hotkeys: undefined, backgroundColor: 'number', // ReaderBackgroundColor (enum)
imagePreLoadAmount: undefined, pageGap: 'number',
shouldUseAutoWebtoonMode: undefined, hotkeys: 'string', // object
autoScroll: undefined, imagePreLoadAmount: 'number',
shouldShowReadingModePreview: undefined, shouldUseAutoWebtoonMode: 'boolean',
shouldShowTapZoneLayoutPreview: undefined, autoScroll: 'string', // object
shouldInformAboutMissingChapter: undefined, shouldShowReadingModePreview: 'boolean',
shouldInformAboutScanlatorChange: undefined, shouldShowTapZoneLayoutPreview: 'boolean',
hideHistory: undefined, shouldInformAboutMissingChapter: 'boolean',
scrollAmount: undefined, shouldInformAboutScanlatorChange: 'boolean',
reverse: undefined, hideHistory: 'boolean',
bookmarked: undefined, scrollAmount: 'number', // ReaderScrollAmount (enum)
downloaded: undefined, reverse: 'boolean',
unread: undefined, bookmarked: 'auto', // boolean undefined null
showChapterNumber: undefined, downloaded: 'auto', // boolean undefined null
extensionLanguages: undefined, unread: 'auto', // boolean undefined null
showNsfw: undefined, showChapterNumber: 'boolean',
shouldUseInfiniteScroll: undefined, extensionLanguages: 'string', // string[]
shouldShowTransitionPage: undefined, showNsfw: 'boolean',
appTheme: undefined, shouldUseInfiniteScroll: 'boolean',
themeMode: undefined, shouldShowTransitionPage: 'boolean',
shouldUsePureBlackMode: undefined, appTheme: 'string',
mangaGridItemWidth: undefined, themeMode: 'string', // ThemeMode (enum)
isPinned: undefined, shouldUsePureBlackMode: 'boolean',
}; mangaGridItemWidth: 'number',
isPinned: 'boolean',
} as const satisfies Record<AppMetadataKeys, 'auto' | 'string' | 'number' | 'boolean'>;
export const VALID_APP_METADATA_KEYS = Object.keys(APP_METADATA_OBJECT); export const VALID_APP_METADATA_KEYS = Object.keys(APP_METADATA_KEY_TO_TYPE);
export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [ export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [
// metadata applied migration id // metadata applied migration id

View File

@@ -7,24 +7,29 @@
*/ */
import { MetaType } from '@/lib/graphql/generated/graphql.ts'; import { MetaType } from '@/lib/graphql/generated/graphql.ts';
import { AllowedMetadataValueTypes, Metadata } from '@/modules/metadata/Metadata.types.ts'; import { AllowedMetadataValueTypes, AppMetadataKeys, Metadata } from '@/modules/metadata/Metadata.types.ts';
import { APP_METADATA_KEY_TO_TYPE } from '@/modules/metadata/Metadata.constants.ts';
export const convertValueFromMetadata = <T extends AllowedMetadataValueTypes = AllowedMetadataValueTypes>( export const convertValueFromMetadata = <T extends AllowedMetadataValueTypes = AllowedMetadataValueTypes>(
key: string,
value: string, value: string,
): T => { ): T => {
if (!Number.isNaN(+value)) { const typeOfKey = APP_METADATA_KEY_TO_TYPE[key as AppMetadataKeys];
const isAutoType = typeOfKey === 'auto';
if ((isAutoType && !Number.isNaN(+value)) || typeOfKey === 'number') {
return +value as T; return +value as T;
} }
if (value === 'true' || value === 'false') { if ((isAutoType && (value === 'true' || value === 'false')) || typeOfKey === 'boolean') {
return (value === 'true') as T; return (value === 'true') as T;
} }
if (value === 'undefined') { if (isAutoType && value === 'undefined') {
return undefined as T; return undefined as T;
} }
if (value === 'null') { if (isAutoType && value === 'null') {
return null as T; return null as T;
} }

View File

@@ -37,7 +37,7 @@ const getMetadataValueFrom = <Key extends AppMetadataKeys, Value extends Allowed
return defaultValue; return defaultValue;
} }
return convertValueFromMetadata(metadata[getMetadataKey(key, prefixes)]); return convertValueFromMetadata(key, metadata[getMetadataKey(key, prefixes)]);
}; };
export function getMetadataFrom<METADATA extends Partial<Metadata<AppMetadataKeys, AllowedMetadataValueTypes>>>( export function getMetadataFrom<METADATA extends Partial<Metadata<AppMetadataKeys, AllowedMetadataValueTypes>>>(