| 
									
										
										
										
											2017-10-21 21:10:33 -04:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 11:52:40 +02:00
										 |  |  | import optionService from "../../services/options.js"; | 
					
						
							| 
									
										
										
										
											2024-07-18 21:35:17 +03:00
										 |  |  | import log from "../../services/log.js"; | 
					
						
							|  |  |  | import searchService from "../../services/search/services/search.js"; | 
					
						
							|  |  |  | import ValidationError from "../../errors/validation_error.js"; | 
					
						
							| 
									
										
										
										
											2025-01-09 18:36:24 +02:00
										 |  |  | import type { Request } from "express"; | 
					
						
							| 
									
										
										
										
											2025-02-20 12:27:33 +02:00
										 |  |  | import { changeLanguage, getLocales } from "../../services/i18n.js"; | 
					
						
							| 
									
										
										
										
											2025-04-18 12:39:52 +03:00
										 |  |  | import type { OptionNames } from "@triliumnext/commons"; | 
					
						
							| 
									
										
										
										
											2025-05-21 17:24:00 +02:00
										 |  |  | import config from "../../services/config.js"; | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-28 19:03:53 +03:00
										 |  |  | interface UserTheme { | 
					
						
							|  |  |  |     val: string; // value of the theme, used in the URL
 | 
					
						
							|  |  |  |     title: string; // title of the theme, displayed in the UI
 | 
					
						
							|  |  |  |     noteId: string; // ID of the note containing the theme
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-30 11:18:34 +02:00
										 |  |  | // options allowed to be updated directly in the Options dialog
 | 
					
						
							| 
									
										
										
										
											2025-03-22 10:27:42 +02:00
										 |  |  | const ALLOWED_OPTIONS = new Set<OptionNames>([ | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "eraseEntitiesAfterTimeInSeconds", | 
					
						
							| 
									
										
										
										
											2025-02-08 11:55:16 +01:00
										 |  |  |     "eraseEntitiesAfterTimeScale", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "protectedSessionTimeout", | 
					
						
							| 
									
										
										
										
											2025-02-18 09:20:57 +01:00
										 |  |  |     "protectedSessionTimeoutTimeScale", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "revisionSnapshotTimeInterval", | 
					
						
							| 
									
										
										
										
											2025-02-18 08:57:58 +01:00
										 |  |  |     "revisionSnapshotTimeIntervalTimeScale", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "revisionSnapshotNumberLimit", | 
					
						
							|  |  |  |     "zoomFactor", | 
					
						
							|  |  |  |     "theme", | 
					
						
							|  |  |  |     "codeBlockTheme", | 
					
						
							| 
									
										
										
										
											2024-10-27 21:51:56 +02:00
										 |  |  |     "codeBlockWordWrap", | 
					
						
							| 
									
										
										
										
											2025-05-11 20:52:26 +03:00
										 |  |  |     "codeNoteTheme", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "syncServerHost", | 
					
						
							|  |  |  |     "syncServerTimeout", | 
					
						
							|  |  |  |     "syncProxy", | 
					
						
							|  |  |  |     "hoistedNoteId", | 
					
						
							|  |  |  |     "mainFontSize", | 
					
						
							|  |  |  |     "mainFontFamily", | 
					
						
							|  |  |  |     "treeFontSize", | 
					
						
							|  |  |  |     "treeFontFamily", | 
					
						
							|  |  |  |     "detailFontSize", | 
					
						
							|  |  |  |     "detailFontFamily", | 
					
						
							|  |  |  |     "monospaceFontSize", | 
					
						
							|  |  |  |     "monospaceFontFamily", | 
					
						
							|  |  |  |     "openNoteContexts", | 
					
						
							|  |  |  |     "vimKeymapEnabled", | 
					
						
							|  |  |  |     "codeLineWrapEnabled", | 
					
						
							|  |  |  |     "codeNotesMimeTypes", | 
					
						
							|  |  |  |     "spellCheckEnabled", | 
					
						
							|  |  |  |     "spellCheckLanguageCode", | 
					
						
							|  |  |  |     "imageMaxWidthHeight", | 
					
						
							|  |  |  |     "imageJpegQuality", | 
					
						
							|  |  |  |     "leftPaneWidth", | 
					
						
							|  |  |  |     "rightPaneWidth", | 
					
						
							|  |  |  |     "leftPaneVisible", | 
					
						
							|  |  |  |     "rightPaneVisible", | 
					
						
							|  |  |  |     "nativeTitleBarVisible", | 
					
						
							|  |  |  |     "headingStyle", | 
					
						
							|  |  |  |     "autoCollapseNoteTree", | 
					
						
							|  |  |  |     "autoReadonlySizeText", | 
					
						
							| 
									
										
										
										
											2025-06-01 15:27:50 +08:00
										 |  |  |     "customDateTimeFormat", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "autoReadonlySizeCode", | 
					
						
							|  |  |  |     "overrideThemeFonts", | 
					
						
							|  |  |  |     "dailyBackupEnabled", | 
					
						
							|  |  |  |     "weeklyBackupEnabled", | 
					
						
							|  |  |  |     "monthlyBackupEnabled", | 
					
						
							|  |  |  |     "maxContentWidth", | 
					
						
							|  |  |  |     "compressImages", | 
					
						
							|  |  |  |     "downloadImagesAutomatically", | 
					
						
							|  |  |  |     "minTocHeadings", | 
					
						
							|  |  |  |     "highlightsList", | 
					
						
							|  |  |  |     "checkForUpdates", | 
					
						
							|  |  |  |     "disableTray", | 
					
						
							|  |  |  |     "eraseUnusedAttachmentsAfterSeconds", | 
					
						
							| 
									
										
										
										
											2025-02-16 14:00:28 +01:00
										 |  |  |     "eraseUnusedAttachmentsAfterTimeScale", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "disableTray", | 
					
						
							|  |  |  |     "customSearchEngineName", | 
					
						
							|  |  |  |     "customSearchEngineUrl", | 
					
						
							|  |  |  |     "promotedAttributesOpenInRibbon", | 
					
						
							|  |  |  |     "editedNotesOpenInRibbon", | 
					
						
							|  |  |  |     "locale", | 
					
						
							| 
									
										
										
										
											2025-03-25 19:56:07 +02:00
										 |  |  |     "formattingLocale", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "firstDayOfWeek", | 
					
						
							| 
									
										
										
										
											2025-03-31 21:40:33 +02:00
										 |  |  |     "firstWeekOfYear", | 
					
						
							|  |  |  |     "minDaysInFirstWeek", | 
					
						
							| 
									
										
										
										
											2025-03-02 21:58:40 +02:00
										 |  |  |     "languages", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "textNoteEditorType", | 
					
						
							|  |  |  |     "textNoteEditorMultilineToolbar", | 
					
						
							| 
									
										
										
										
											2025-06-23 22:38:40 +03:00
										 |  |  |     "textNoteEmojiCompletionEnabled", | 
					
						
							| 
									
										
										
										
											2025-06-23 23:20:51 +03:00
										 |  |  |     "textNoteCompletionEnabled", | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     "layoutOrientation", | 
					
						
							|  |  |  |     "backgroundEffects", | 
					
						
							| 
									
										
										
										
											2025-02-16 22:47:50 -07:00
										 |  |  |     "allowedHtmlTags", | 
					
						
							|  |  |  |     "redirectBareDomain", | 
					
						
							| 
									
										
										
										
											2025-03-02 18:58:25 -08:00
										 |  |  |     "showLoginInShareTheme", | 
					
						
							| 
									
										
										
										
											2025-04-17 23:28:04 +02:00
										 |  |  |     "splitEditorOrientation", | 
					
						
							| 
									
										
										
										
											2025-08-12 19:37:32 +03:00
										 |  |  |     "seenCallToActions", | 
					
						
							| 
									
										
										
										
											2025-03-31 15:55:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-07 18:30:46 +00:00
										 |  |  |     // AI/LLM integration options
 | 
					
						
							| 
									
										
										
										
											2025-03-02 18:58:25 -08:00
										 |  |  |     "aiEnabled", | 
					
						
							| 
									
										
										
										
											2025-04-01 20:38:03 +00:00
										 |  |  |     "aiTemperature", | 
					
						
							|  |  |  |     "aiSystemPrompt", | 
					
						
							| 
									
										
										
										
											2025-06-04 20:13:13 +00:00
										 |  |  |     "aiSelectedProvider", | 
					
						
							| 
									
										
										
										
											2025-03-02 18:58:25 -08:00
										 |  |  |     "openaiApiKey", | 
					
						
							| 
									
										
										
										
											2025-04-01 20:38:03 +00:00
										 |  |  |     "openaiBaseUrl", | 
					
						
							| 
									
										
										
										
											2025-03-02 18:58:25 -08:00
										 |  |  |     "openaiDefaultModel", | 
					
						
							|  |  |  |     "anthropicApiKey", | 
					
						
							| 
									
										
										
										
											2025-04-01 20:38:03 +00:00
										 |  |  |     "anthropicBaseUrl", | 
					
						
							| 
									
										
										
										
											2025-03-02 18:58:25 -08:00
										 |  |  |     "anthropicDefaultModel", | 
					
						
							|  |  |  |     "ollamaBaseUrl", | 
					
						
							|  |  |  |     "ollamaDefaultModel", | 
					
						
							| 
									
										
										
										
											2025-03-28 01:00:58 +01:00
										 |  |  |     "mfaEnabled", | 
					
						
							|  |  |  |     "mfaMethod" | 
					
						
							| 
									
										
										
										
											2019-11-19 20:53:04 +01:00
										 |  |  | ]); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getOptions() { | 
					
						
							| 
									
										
										
										
											2023-06-29 22:10:13 +02:00
										 |  |  |     const optionMap = optionService.getOptionMap(); | 
					
						
							| 
									
										
										
										
											2024-04-06 21:57:09 +03:00
										 |  |  |     const resultMap: Record<string, string> = {}; | 
					
						
							| 
									
										
										
										
											2019-11-19 20:53:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (const optionName in optionMap) { | 
					
						
							|  |  |  |         if (isAllowed(optionName)) { | 
					
						
							| 
									
										
										
										
											2025-01-03 17:54:05 +02:00
										 |  |  |             resultMap[optionName] = optionMap[optionName as OptionNames]; | 
					
						
							| 
									
										
										
										
											2019-11-19 20:53:04 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     resultMap["isPasswordSet"] = optionMap["passwordVerificationHash"] ? "true" : "false"; | 
					
						
							| 
									
										
										
										
											2025-05-21 17:24:00 +02:00
										 |  |  |     // if database is read-only, disable editing in UI by setting 0 here
 | 
					
						
							|  |  |  |     if (config.General.readOnly) { | 
					
						
							|  |  |  |         resultMap["autoReadonlySizeText"] = "0"; | 
					
						
							|  |  |  |         resultMap["autoReadonlySizeCode"] = "0"; | 
					
						
							|  |  |  |         resultMap["databaseReadonly"] = "true"; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-30 22:54:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 20:53:04 +01:00
										 |  |  |     return resultMap; | 
					
						
							| 
									
										
										
										
											2018-03-30 13:56:46 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-06 21:57:09 +03:00
										 |  |  | function updateOption(req: Request) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     const { name, value } = req.params; | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |     if (!update(name, value)) { | 
					
						
							| 
									
										
										
										
											2022-12-09 16:04:13 +01:00
										 |  |  |         throw new ValidationError("not allowed option to change"); | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-06 21:57:09 +03:00
										 |  |  | function updateOptions(req: Request) { | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |     for (const optionName in req.body) { | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |         if (!update(optionName, req.body[optionName])) { | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |             // this should be improved
 | 
					
						
							|  |  |  |             // it should return 400 instead of current 500, but at least it now rollbacks transaction
 | 
					
						
							| 
									
										
										
										
											2023-05-04 22:16:18 +02:00
										 |  |  |             throw new Error(`Option '${optionName}' is not allowed to be changed`); | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-06 21:57:09 +03:00
										 |  |  | function update(name: string, value: string) { | 
					
						
							| 
									
										
										
										
											2019-11-19 20:53:04 +01:00
										 |  |  |     if (!isAllowed(name)) { | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2017-10-14 23:31:44 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     if (name !== "openNoteContexts") { | 
					
						
							| 
									
										
										
										
											2023-04-11 22:00:04 +02:00
										 |  |  |         log.info(`Updating option '${name}' to '${value}'`); | 
					
						
							| 
									
										
										
										
											2019-11-05 20:59:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-02 13:02:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-03 17:54:05 +02:00
										 |  |  |     optionService.setOption(name as OptionNames, value); | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-23 19:56:06 +03:00
										 |  |  |     if (name === "locale") { | 
					
						
							|  |  |  |         // This runs asynchronously, so it's not perfect, but it does the trick for now.
 | 
					
						
							|  |  |  |         changeLanguage(value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2018-03-30 13:56:46 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | function getUserThemes() { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |     const notes = searchService.searchNotes("#appTheme", { ignoreHoistedNote: true }); | 
					
						
							| 
									
										
										
										
											2025-05-28 19:03:53 +03:00
										 |  |  |     const ret: UserTheme[] = []; | 
					
						
							| 
									
										
										
										
											2019-02-03 00:12:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (const note of notes) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         let value = note.getOwnedLabelValue("appTheme"); | 
					
						
							| 
									
										
										
										
											2019-02-03 00:12:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 15:35:37 +01:00
										 |  |  |         if (!value) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |             value = note.title.toLowerCase().replace(/[^a-z0-9]/gi, "-"); | 
					
						
							| 
									
										
										
										
											2019-02-03 00:12:57 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ret.push({ | 
					
						
							|  |  |  |             val: value, | 
					
						
							|  |  |  |             title: note.title, | 
					
						
							|  |  |  |             noteId: note.noteId | 
					
						
							| 
									
										
										
										
											2019-01-27 21:18:11 +01:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-02-03 00:12:57 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2019-01-27 21:18:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 07:36:09 +03:00
										 |  |  | function getSupportedLocales() { | 
					
						
							| 
									
										
										
										
											2025-02-20 12:27:33 +02:00
										 |  |  |     return getLocales(); | 
					
						
							| 
									
										
										
										
											2024-08-11 07:36:09 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-06 21:57:09 +03:00
										 |  |  | function isAllowed(name: string) { | 
					
						
							| 
									
										
										
										
											2025-03-22 10:27:42 +02:00
										 |  |  |     return (ALLOWED_OPTIONS as Set<string>).has(name) | 
					
						
							|  |  |  |         || name.startsWith("keyboardShortcuts") | 
					
						
							|  |  |  |         || name.endsWith("Collapsed") | 
					
						
							|  |  |  |         || name.startsWith("hideArchivedNotes"); | 
					
						
							| 
									
										
										
										
											2019-11-19 20:53:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-18 21:47:30 +03:00
										 |  |  | export default { | 
					
						
							| 
									
										
										
										
											2018-04-01 20:33:10 -04:00
										 |  |  |     getOptions, | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |     updateOption, | 
					
						
							| 
									
										
										
										
											2019-01-27 21:18:11 +01:00
										 |  |  |     updateOptions, | 
					
						
							| 
									
										
										
										
											2024-08-11 07:36:09 +03:00
										 |  |  |     getUserThemes, | 
					
						
							|  |  |  |     getSupportedLocales | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | }; |