2024-10-05 22:53:22 +02:00
/*
* 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/.
*/
2026-03-11 00:11:29 +01:00
import type { MessageDescriptor } from '@lingui/core' ;
2026-01-10 19:45:02 +01:00
import { msg } from '@lingui/core/macro' ;
2025-10-11 00:39:44 +02:00
import { d } from 'koration' ;
2025-08-15 22:02:58 +02:00
import { DEFAULT_DEVICE } from '@/features/device/services/Device.ts' ;
import { DEFAULT_SORT_SETTINGS } from '@/features/migration/Migration.constants.ts' ;
2026-03-11 00:11:29 +01:00
import type {
2025-12-22 21:33:23 +01:00
GlobalUpdateSkipEntriesSettings ,
MetadataServerSettings ,
2025-12-22 22:04:05 +01:00
ServerSettings ,
2025-12-22 21:33:23 +01:00
} from '@/features/settings/Settings.types.ts' ;
2026-03-11 00:11:29 +01:00
import { ImageProcessingTargetMode , ImageProcessingType } from '@/features/settings/Settings.types.ts' ;
2026-01-10 19:45:02 +01:00
import { GridLayout } from '@/base/Base.types' ;
2025-08-16 02:48:46 +02:00
import { getDefaultLanguages } from '@/base/utils/Languages.ts' ;
2026-03-11 00:11:29 +01:00
import type { SelectSettingValue , SelectSettingValueDisplayInfo } from '@/base/components/settings/SelectSetting.tsx' ;
2025-12-06 12:59:39 -06:00
import {
AuthMode ,
KoreaderSyncChecksumMethod ,
KoreaderSyncConflictStrategy ,
2026-07-02 22:44:10 +02:00
StartSyncResult ,
SyncState ,
2025-12-06 12:59:39 -06:00
WebUiChannel ,
WebUiFlavor ,
WebUiInterface ,
2026-05-15 20:40:31 +02:00
} from '@/lib/graphql/generated/graphql-base.types.ts' ;
2025-09-20 18:19:34 +02:00
import { ThemeMode } from '@/features/theme/AppTheme.types.ts' ;
2026-01-22 00:12:22 +01:00
import { getPreferredISOLanguageCodes } from '@/lib/ISOLanguageUtil.ts' ;
2026-06-30 15:08:17 +02:00
import type { BackupFlag } from '@/features/backup/Backup.types.ts' ;
2024-10-05 22:53:22 +02:00
2025-06-24 22:22:53 +02:00
export const MANGA_GRID_WIDTH = {
min : 100 ,
max : 1000 ,
step : 10 ,
default : 300 ,
};
2024-10-05 22:53:22 +02:00
export const SERVER_SETTINGS_METADATA_DEFAULT : MetadataServerSettings = {
// downloads
deleteChaptersManuallyMarkedRead : false ,
deleteChaptersWhileReading : 0 ,
deleteChaptersWithBookmark : false ,
downloadAheadLimit : 0 ,
// library
showAddToLibraryCategorySelectDialog : true ,
ignoreFilters : false ,
removeMangaFromCategories : false ,
showTabSize : false ,
2024-12-30 03:49:39 +01:00
showContinueReadingButton : false ,
showDownloadBadge : false ,
showUnreadBadge : false ,
2025-01-25 00:12:56 +01:00
gridLayout : GridLayout.Compact ,
2024-10-05 22:53:22 +02:00
// client
devices : [ DEFAULT_DEVICE ],
// migration
migrateChapters : true ,
migrateCategories : true ,
migrateTracking : true ,
deleteChapters : true ,
2026-03-07 03:07:40 +01:00
migrateMetadata : true ,
2024-10-05 22:53:22 +02:00
migrateSortSettings : DEFAULT_SORT_SETTINGS ,
// browse
hideLibraryEntries : false ,
2026-01-25 17:31:02 +01:00
browseLanguages : getDefaultLanguages (),
2025-04-21 19:18:42 +02:00
showNsfw : true ,
2025-05-17 23:37:00 +02:00
lastUsedSourceId : null ,
2025-05-18 00:59:01 +02:00
shouldShowOnlySourcesWithResults : true ,
2024-10-05 22:53:22 +02:00
2025-03-22 01:16:38 +01:00
// history
hideHistory : false ,
2024-10-05 22:53:22 +02:00
// tracking
updateProgressAfterReading : true ,
updateProgressManualMarkRead : false ,
// updates
webUIInformAvailableUpdate : true ,
2026-01-25 17:53:32 +01:00
webUIInformVersionUpdated : true ,
2024-10-05 22:53:22 +02:00
serverInformAvailableUpdate : true ,
2026-01-25 17:57:30 +01:00
serverInformVersionUpdated : true ,
2024-10-05 22:53:22 +02:00
// themes
2026-01-22 00:12:22 +01:00
locale : getPreferredISOLanguageCodes ()[ 0 ],
2025-05-17 21:04:44 +02:00
appTheme : 'default' ,
themeMode : ThemeMode.SYSTEM ,
shouldUsePureBlackMode : false ,
2024-10-05 22:53:22 +02:00
customThemes : {},
mangaThumbnailBackdrop : true ,
2025-01-26 03:53:19 +01:00
mangaDynamicColorSchemes : true ,
2025-06-24 22:22:53 +02:00
mangaGridItemWidth : MANGA_GRID_WIDTH.default ,
2024-10-05 22:53:22 +02:00
};
2025-07-12 01:08:40 +02:00
const AUTH_MODES = [ AuthMode . None ]. concat ( Object . values ( AuthMode ). filter (( mode ) => mode !== AuthMode . None ));
2026-01-10 19:45:02 +01:00
const AUTH_MODES_TO_TRANSLATION : { [ mode in AuthMode ] : SelectSettingValueDisplayInfo } = {
2025-07-12 01:08:40 +02:00
[ AuthMode . None ] : {
2026-01-10 19:45:02 +01:00
text : msg `None` ,
description : msg `Disable authentication` ,
disclaimer : msg `Your library will be accessible. Use this only on private networks or when otherwise securing access.` ,
2025-07-12 01:08:40 +02:00
},
[ AuthMode . BasicAuth ] : {
2026-01-10 19:45:02 +01:00
text : msg `Basic Authentication` ,
description : msg `Your browser will prompt you to enter credentials with a dialog.` ,
2025-07-12 01:08:40 +02:00
},
[ AuthMode . SimpleLogin ] : {
2026-01-10 19:45:02 +01:00
text : msg `Simple Login` ,
description : msg `The login will be handled by the server.` ,
disclaimer : msg `When you enable this, you may need to refresh this tab for the login page to appear.` ,
2025-07-27 00:03:51 +02:00
},
[ AuthMode . UiLogin ] : {
2026-01-10 19:45:02 +01:00
text : msg `UI Login` ,
description : msg `The login will be handled by the client.` ,
2025-07-12 01:08:40 +02:00
},
};
export const AUTH_MODES_SELECT_VALUES : SelectSettingValue < AuthMode >[] = AUTH_MODES . map (( mode ) => [
mode ,
2026-01-10 19:45:02 +01:00
AUTH_MODES_TO_TRANSLATION [ mode ],
2025-07-12 01:08:40 +02:00
]);
const WEB_UI_FLAVORS = Object . values ( WebUiFlavor );
2026-01-10 19:45:02 +01:00
const WEB_UI_FLAVOR_TO_TRANSLATION : { [ flavor in WebUiFlavor ] : SelectSettingValueDisplayInfo } = {
2025-07-12 01:08:40 +02:00
[ WebUiFlavor . Webui ] : {
2026-01-10 19:45:02 +01:00
text : msg `WebUI` ,
description : msg `Use the default WebUI` ,
disclaimer : msg `After changing this setting go to the "About" page and check for a webUI update and install it` ,
2025-07-12 01:08:40 +02:00
},
[ WebUiFlavor . Vui ] : {
2026-01-10 19:45:02 +01:00
text : msg `VUI` ,
description : msg `A preview focused web frontend built with svelte` ,
disclaimer : msg `After changing this setting go to the "About" page and check for a webUI update and install it` ,
2025-07-12 01:08:40 +02:00
},
[ WebUiFlavor . Custom ] : {
2026-01-10 19:45:02 +01:00
text : msg `Custom` ,
description : msg `Use a custom WebUI. \ nTo use a custom WebUI replace the content of the "webUI" directory in the root directory on the server with the files of the custom WebUI` ,
2025-07-12 01:08:40 +02:00
},
};
export const WEB_UI_FLAVOR_SELECT_VALUES : SelectSettingValue < WebUiFlavor >[] = WEB_UI_FLAVORS . map (( flavor ) => [
flavor ,
2026-01-10 19:45:02 +01:00
WEB_UI_FLAVOR_TO_TRANSLATION [ flavor ],
2025-07-12 01:08:40 +02:00
]);
const WEB_UI_CHANNELS = Object . values ( WebUiChannel );
2026-01-10 19:45:02 +01:00
const WEB_UI_CHANNEL_TO_TRANSLATIONS : {
2025-07-12 01:08:40 +02:00
[ channel in WebUiChannel ] : SelectSettingValueDisplayInfo ;
} = {
[ WebUiChannel . Bundled ] : {
2026-01-10 19:45:02 +01:00
text : msg `Bundled` ,
description : msg `Use the version that was delivered with the server release` ,
disclaimer : msg `After changing this setting go to the "About" page and check for a webUI update and install it` ,
2025-07-12 01:08:40 +02:00
},
[ WebUiChannel . Stable ] : {
2026-01-10 19:45:02 +01:00
text : msg `Stable` ,
description : msg `Use the latest released version.` ,
disclaimer : msg `After changing this setting go to the "About" page and check for a webUI update and install it` ,
2025-07-12 01:08:40 +02:00
},
[ WebUiChannel . Preview ] : {
2026-01-10 19:45:02 +01:00
text : msg `Preview` ,
description : msg `Use the latest features and help us get them ready for a stable release.` ,
disclaimer : msg `Features and changes in this version might not be completely ready yet and can cause bugs. \ nMake sure that you have automatic backups enabled to prevent loss of your library! \ n \ nAfter changing this setting go to the "About" page and check for a webUI update and install it` ,
2025-07-12 01:08:40 +02:00
},
};
export const WEB_UI_CHANNEL_SELECT_VALUES : SelectSettingValue < WebUiChannel >[] = WEB_UI_CHANNELS . map (( channel ) => [
channel ,
2026-01-10 19:45:02 +01:00
WEB_UI_CHANNEL_TO_TRANSLATIONS [ channel ],
2025-07-12 01:08:40 +02:00
]);
const WEB_UI_INTERFACES = Object . values ( WebUiInterface );
2026-01-10 19:45:02 +01:00
const WEB_UI_INTERFACE_TO_TRANSLATIONS : {
2025-07-12 01:08:40 +02:00
[ webUIInterface in WebUiInterface ] : SelectSettingValueDisplayInfo ;
} = {
[ WebUiInterface . Browser ] : {
2026-01-10 19:45:02 +01:00
text : msg `Browser` ,
description : msg `Where to start the WebUI when starting the server` ,
2025-07-12 01:08:40 +02:00
},
[ WebUiInterface . Electron ] : {
2026-01-10 19:45:02 +01:00
text : msg `Electron` ,
description : msg `Where to start the WebUI when starting the server` ,
2025-07-12 01:08:40 +02:00
},
};
export const WEB_UI_INTERFACE_SELECT_VALUES : SelectSettingValue < WebUiInterface >[] = WEB_UI_INTERFACES . map (
2026-01-10 19:45:02 +01:00
( webUIInterface ) => [ webUIInterface , WEB_UI_INTERFACE_TO_TRANSLATIONS [ webUIInterface ]],
2025-07-12 01:08:40 +02:00
);
export const GLOBAL_UPDATE_INTERVAL = {
2025-10-11 00:39:44 +02:00
default : d ( 12 ). hours . inWholeHours ,
min : d ( 6 ). hours . inWholeHours ,
max : d ( 1 ). months . inWholeHours ,
2025-07-12 01:08:40 +02:00
};
export const GLOBAL_UPDATE_SKIP_ENTRIES_TO_TRANSLATION : {
2026-01-10 19:45:02 +01:00
[ setting in keyof GlobalUpdateSkipEntriesSettings ] : MessageDescriptor ;
2025-07-12 01:08:40 +02:00
} = {
2026-01-10 19:45:02 +01:00
excludeUnreadChapters : msg `With unread chapter(s)` ,
excludeNotStarted : msg `That haven't been started` ,
excludeCompleted : msg `With "Completed" status` ,
2025-07-12 01:08:40 +02:00
};
export const WEB_UI_UPDATE_INTERVAL = {
2025-10-11 00:39:44 +02:00
default : d ( 23 ). hours . inWholeHours ,
min : d ( 1 ). hours . inWholeHours ,
max : d ( 23 ). hours . inWholeHours ,
2025-07-12 01:08:40 +02:00
};
2025-07-27 00:03:51 +02:00
export const JWT_ACCESS_TOKEN_EXPIRY = {
2025-10-11 00:39:44 +02:00
default : d ( 5 ). minutes . inWholeMinutes ,
min : d ( 1 ). minutes . inWholeMinutes ,
max : d ( 4 ). hours . inWholeMinutes ,
2025-07-27 00:03:51 +02:00
};
export const JWT_REFRESH_TOKEN_EXPIRY = {
2025-10-11 00:39:44 +02:00
default : d ( 60 ). days . inWholeDays ,
min : d ( 1 ). days . inWholeDays ,
max : d ( 1 ). years . inWholeDays ,
2025-07-27 00:03:51 +02:00
};
2025-09-08 00:24:32 +02:00
export const KOREADER_SYNC_PERCENTAGE_TOLERANCE = {
default : 1.0 e - 15 ,
min : 1.0e - 15 ,
max : 1 ,
2025-09-18 19:20:41 +02:00
step : 0.05 ,
2025-09-08 00:24:32 +02:00
};
2025-12-06 12:59:39 -06:00
export const KOREADER_SYNC_CONFLICT_STRATEGIES = Object . values ( KoreaderSyncConflictStrategy );
2026-01-10 19:45:02 +01:00
export const KOREADER_SYNC_CONFLICT_STRATEGY_TO_TRANSLATIONS : Record <
2025-12-06 12:59:39 -06:00
KoreaderSyncConflictStrategy ,
SelectSettingValueDisplayInfo
> = {
[ KoreaderSyncConflictStrategy . Disabled ] : {
2026-01-10 19:45:02 +01:00
text : msg `Disabled` ,
2025-12-06 12:59:39 -06:00
},
[ KoreaderSyncConflictStrategy . KeepLocal ] : {
2026-01-10 19:45:02 +01:00
text : msg `Keep local` ,
2025-12-06 12:59:39 -06:00
},
[ KoreaderSyncConflictStrategy . KeepRemote ] : {
2026-01-10 19:45:02 +01:00
text : msg `Keep remote` ,
2025-12-06 12:59:39 -06:00
},
[ KoreaderSyncConflictStrategy . Prompt ] : {
2026-01-10 19:45:02 +01:00
text : msg `Prompt` ,
2025-12-06 12:59:39 -06:00
},
};
export const KOREADER_SYNC_CONFLICT_STRATEGY_SELECT_VALUES : SelectSettingValue < KoreaderSyncConflictStrategy >[] =
KOREADER_SYNC_CONFLICT_STRATEGIES . map (( strategy ) => [
strategy ,
2026-01-10 19:45:02 +01:00
KOREADER_SYNC_CONFLICT_STRATEGY_TO_TRANSLATIONS [ strategy ],
2025-12-06 12:59:39 -06:00
]);
export const KOREADER_SYNC_CHECKSUM_METHODES = Object . values ( KoreaderSyncChecksumMethod );
2026-01-10 19:45:02 +01:00
export const KOREADER_SYNC_CHECKSUM_METHOD_TO_TRANSLATIONS : Record <
2025-12-06 12:59:39 -06:00
KoreaderSyncChecksumMethod ,
SelectSettingValueDisplayInfo
> = {
[ KoreaderSyncChecksumMethod . Binary ] : {
2026-01-10 19:45:02 +01:00
text : msg `Binary` ,
2025-12-06 12:59:39 -06:00
},
[ KoreaderSyncChecksumMethod . Filename ] : {
2026-01-10 19:45:02 +01:00
text : msg `Filename` ,
2025-12-06 12:59:39 -06:00
},
};
export const KOREADER_SYNC_CHECKSUM_METHOD_SELECT_VALUES : SelectSettingValue < KoreaderSyncChecksumMethod >[] =
2026-01-10 19:45:02 +01:00
KOREADER_SYNC_CHECKSUM_METHODES . map (( method ) => [ method , KOREADER_SYNC_CHECKSUM_METHOD_TO_TRANSLATIONS [ method ]]);
2025-12-22 21:11:12 +01:00
export const IMAGE_PROCESSING_COMPRESSION = {
min : 0 ,
max : 1 ,
step : 0.01 ,
};
export const IMAGE_PROCESSING_CALL_TIMEOUT = {
min : d ( 10 ). seconds . inWholeSeconds ,
max : d ( 10 ). minutes . inWholeSeconds ,
step : d ( 10 ). seconds . inWholeSeconds ,
};
export const IMAGE_PROCESSING_CONNECT_TIMEOUT = {
min : d ( 10 ). seconds . inWholeSeconds ,
max : d ( 10 ). minutes . inWholeSeconds ,
step : d ( 10 ). seconds . inWholeSeconds ,
};
2025-12-22 21:33:23 +01:00
const IMAGE_PROCESSING_TARGET_MODES = Object . values ( ImageProcessingTargetMode );
2026-01-10 19:45:02 +01:00
const IMAGE_PROCESSING_TARGET_MODES_TO_TRANSLATION : {
2025-12-22 21:33:23 +01:00
[ flavor in ImageProcessingTargetMode ] : SelectSettingValueDisplayInfo ;
} = {
2025-12-23 02:31:25 +01:00
[ ImageProcessingTargetMode . DISABLED ] : {
2026-01-10 19:45:02 +01:00
text : msg `Disabled` ,
2025-12-23 02:31:25 +01:00
},
2025-12-22 21:33:23 +01:00
[ ImageProcessingTargetMode . IMAGE ] : {
2026-01-10 19:45:02 +01:00
text : msg `Image` ,
description : msg `Convert images to different formats` ,
2025-12-22 21:33:23 +01:00
},
[ ImageProcessingTargetMode . URL ] : {
2026-01-10 19:45:02 +01:00
text : msg `URL` ,
description : msg `Convert images to different formats` ,
2025-12-22 21:33:23 +01:00
},
};
export const IMAGE_PROCESSING_TARGET_MODES_SELECT_VALUES : SelectSettingValue < ImageProcessingTargetMode >[] =
2026-01-10 19:45:02 +01:00
IMAGE_PROCESSING_TARGET_MODES . map (( mode ) => [ mode , IMAGE_PROCESSING_TARGET_MODES_TO_TRANSLATION [ mode ]]);
2025-12-22 21:33:23 +01:00
export const IMAGE_PROCESSING_INPUT_WIDTH = 250 ;
export const DEFAULT_MIME_TYPE = 'default' ;
export const MIME_TYPE_PREFIX = 'image/' ;
2025-12-23 02:31:25 +01:00
export const TARGET_DISABLED = 'none' ;
2025-12-22 22:04:05 +01:00
2026-01-10 19:45:02 +01:00
export const IMAGE_PROCESSING_TYPE_TO_TRANSLATION : Record < ImageProcessingType , MessageDescriptor > = {
[ ImageProcessingType . DOWNLOAD ] : msg `Image download processing` ,
[ ImageProcessingType . SERVE ] : msg `Image serve processing` ,
2025-12-22 22:04:05 +01:00
};
export const IMAGE_PROCESSING_TYPE_TO_SETTING : Record <
ImageProcessingType ,
Extract < keyof ServerSettings , 'downloadConversions' | 'serveConversions' >
> = {
[ ImageProcessingType . DOWNLOAD ] : 'downloadConversions' ,
[ ImageProcessingType . SERVE ] : 'serveConversions' ,
};
2026-06-30 15:08:17 +02:00
const SYNC_INTERVAL_TO_TRANSLATION : Record < string , SelectSettingValueDisplayInfo > = {
[ d ( 0 ). seconds . asWholeMinutes . toISOString ()] : {
text : msg `Disabled` ,
},
[ d ( 30 ). minutes . asWholeMinutes . toISOString ()] : {
text : msg `Every 30 minutes` ,
},
[ d ( 1 ). hours . asWholeMinutes . toISOString ()] : {
text : msg `Every hour` ,
},
[ d ( 3 ). hours . asWholeMinutes . toISOString ()] : {
text : msg `Every 3 hours` ,
},
[ d ( 6 ). hours . asWholeMinutes . toISOString ()] : {
text : msg `Every 6 hours` ,
},
[ d ( 12 ). hours . asWholeMinutes . toISOString ()] : {
text : msg `Every 12 hours` ,
},
[ d ( 1 ). days . asWholeMinutes . toISOString ()] : {
text : msg `Daily` ,
},
[ d ( 7 ). days . asWholeMinutes . toISOString ()] : {
text : msg `Weekly` ,
},
};
export const SYNC_INTERVAL_CUSTOM_VALUE = d ( 10 ). days . asWholeMinutes . toISOString ();
export const SYNC_INTERVAL_VALUES = Object . keys ( SYNC_INTERVAL_TO_TRANSLATION );
export const SYNC_INTERVAL_SELECT_VALUES : SelectSettingValue < string >[] = SYNC_INTERVAL_VALUES . map (( value ) => [
value ,
SYNC_INTERVAL_TO_TRANSLATION [ value ],
]);
export const SYNC_INTERVAL_SELECT_VALUES_WITH_CUSTOM : SelectSettingValue < string >[] = [
... SYNC_INTERVAL_SELECT_VALUES ,
[ SYNC_INTERVAL_CUSTOM_VALUE , { text : msg `Custom` }],
];
export const SYNC_SETTINGS_HIDDEN_BACKUP_FLAGS = [
'includeServerSettings' ,
'includeClientData' ,
] as const satisfies BackupFlag [];
2026-07-02 22:44:10 +02:00
export const SYNC_START_RESULT_TRANSLATION : Record < StartSyncResult , MessageDescriptor > = {
[ StartSyncResult . Success ] : msg `Sync started` ,
[ StartSyncResult . SyncDisabled ] : msg `Sync disabled` ,
[ StartSyncResult . SyncInProgress ] : msg `Sync in progress` ,
};
export const SYNC_STATE_TRANSLATION : Record < SyncState , MessageDescriptor > = {
[ SyncState . CreatingBackup ] : msg `Creating backup` ,
[ SyncState . Downloading ] : msg `Downloading` ,
[ SyncState . Error ] : msg `Error` ,
[ SyncState . Merging ] : msg `Merging` ,
[ SyncState . Restoring ] : msg `Restoring` ,
[ SyncState . Started ] : msg `Started` ,
[ SyncState . Success ] : msg `Success` ,
[ SyncState . Uploading ] : msg `Uploading` ,
};