mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	Merge branch 'master' into next61
# Conflicts: # package-lock.json # package.json # src/public/app/components/note_context.js # src/public/app/services/open.js # src/public/app/widgets/buttons/note_actions.js # src/public/app/widgets/find_in_code.js # src/public/app/widgets/type_widgets/canvas.js # src/services/options.js
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							| @@ -2,7 +2,7 @@ | |||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "productName": "Trilium Notes", |   "productName": "Trilium Notes", | ||||||
|   "description": "Trilium Notes", |   "description": "Trilium Notes", | ||||||
|   "version": "0.59.4", |   "version": "0.60.0-beta", | ||||||
|   "license": "AGPL-3.0-only", |   "license": "AGPL-3.0-only", | ||||||
|   "main": "electron.js", |   "main": "electron.js", | ||||||
|   "bin": { |   "bin": { | ||||||
| @@ -28,7 +28,7 @@ | |||||||
|     "test": "npm run test-jasmine && npm run test-es6", |     "test": "npm run test-jasmine && npm run test-es6", | ||||||
|     "postinstall": "rimraf ./node_modules/canvas", |     "postinstall": "rimraf ./node_modules/canvas", | ||||||
|     "lint": "eslint .  --cache", |     "lint": "eslint .  --cache", | ||||||
|     "prepare": "husky install" |     "prepare": "husky install || echo 'Husky install failed, expected on flatpak build'" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@braintree/sanitize-url": "6.0.2", |     "@braintree/sanitize-url": "6.0.2", | ||||||
| @@ -45,8 +45,8 @@ | |||||||
|     "cookie-parser": "1.4.6", |     "cookie-parser": "1.4.6", | ||||||
|     "csurf": "1.11.0", |     "csurf": "1.11.0", | ||||||
|     "dayjs": "1.11.7", |     "dayjs": "1.11.7", | ||||||
|     "dayjs-plugin-utc": "^0.1.2", |     "dayjs-plugin-utc": "0.1.2", | ||||||
|     "debounce": "^1.2.1", |     "debounce": "1.2.1", | ||||||
|     "ejs": "3.1.9", |     "ejs": "3.1.9", | ||||||
|     "electron-debug": "3.2.0", |     "electron-debug": "3.2.0", | ||||||
|     "electron-dl": "3.5.0", |     "electron-dl": "3.5.0", | ||||||
|   | |||||||
| @@ -57,10 +57,8 @@ export default class RootCommandExecutor extends Component { | |||||||
|  |  | ||||||
|     openNoteCustomCommand() { |     openNoteCustomCommand() { | ||||||
|         const noteId = appContext.tabManager.getActiveContextNoteId(); |         const noteId = appContext.tabManager.getActiveContextNoteId(); | ||||||
|         const mime = appContext.tabManager.getActiveContextNoteMime() |  | ||||||
|  |  | ||||||
|         if (noteId) { |         if (noteId) { | ||||||
|             openService.openNoteCustom(noteId, mime); |             openService.openNoteCustom(noteId); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -41,14 +41,19 @@ function downloadAttachment(attachmentId) { | |||||||
|     download(url); |     download(url); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function openNoteCustom(noteId, mime) { | async function openNoteCustom(noteId) { | ||||||
|     if (utils.isElectron()) { |     if (!utils.isElectron() || utils.isMac()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const resp = await server.post(`notes/${noteId}/save-to-tmp-dir`); |     const resp = await server.post(`notes/${noteId}/save-to-tmp-dir`); | ||||||
|       const filePath = resp.tmpFilePath; |     let filePath = resp.tmpFilePath; | ||||||
|       const { exec } = utils.dynamicRequire('child_process'); |     const {exec} = utils.dynamicRequire('child_process'); | ||||||
|     const platform = process.platform; |     const platform = process.platform; | ||||||
|  |  | ||||||
|     if (platform === 'linux') { |     if (platform === 'linux') { | ||||||
|         const terminals = ['gnome-terminal', 'konsole', 'xterm', 'xfce4-terminal', 'mate-terminal', 'rxvt', 'terminator', 'terminology']; |         // we don't know which terminal is available, try in succession | ||||||
|  |         const terminals = ['x-terminal-emulator', 'gnome-terminal', 'konsole', 'xterm', 'xfce4-terminal', 'mate-terminal', 'rxvt', 'terminator', 'terminology']; | ||||||
|         const openFileWithTerminal = (terminal) => { |         const openFileWithTerminal = (terminal) => { | ||||||
|             const command = `${terminal} -e 'mimeopen -d "${filePath}"'`; |             const command = `${terminal} -e 'mimeopen -d "${filePath}"'`; | ||||||
|             console.log(`Open Note custom: ${command} `); |             console.log(`Open Note custom: ${command} `); | ||||||
| @@ -57,15 +62,16 @@ async function openNoteCustom(noteId, mime) { | |||||||
|                     console.error(`Open Note custom: Failed to open file with ${terminal}: ${error}`); |                     console.error(`Open Note custom: Failed to open file with ${terminal}: ${error}`); | ||||||
|                     searchTerminal(terminals.indexOf(terminal) + 1); |                     searchTerminal(terminals.indexOf(terminal) + 1); | ||||||
|                 } else { |                 } else { | ||||||
|               console.log(`Open Note custom: File opened with ${terminal}. ${stdout}`); |                     console.log(`Open Note custom: File opened with ${terminal}: ${stdout}`); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         const searchTerminal = (index) => { |         const searchTerminal = (index) => { | ||||||
|             const terminal = terminals[index]; |             const terminal = terminals[index]; | ||||||
|             if (!terminal) { |             if (!terminal) { | ||||||
|                 console.error('Open Note custom: No terminal found!'); |                 console.error('Open Note custom: No terminal found!'); | ||||||
|             open(getFileUrl(noteId), { url: true }); |                 open(getFileUrl(noteId), {url: true}); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             exec(`which ${terminal}`, (error, stdout, stderr) => { |             exec(`which ${terminal}`, (error, stdout, stderr) => { | ||||||
| @@ -79,23 +85,22 @@ async function openNoteCustom(noteId, mime) { | |||||||
|         searchTerminal(0); |         searchTerminal(0); | ||||||
|     } else if (platform === 'win32') { |     } else if (platform === 'win32') { | ||||||
|         if (filePath.indexOf("/") !== -1) { |         if (filePath.indexOf("/") !== -1) { | ||||||
|           //Note that the path separator must be \ instead of / |             // Note that the path separator must be \ instead of / | ||||||
|             filePath = filePath.replace(/\//g, "\\"); |             filePath = filePath.replace(/\//g, "\\"); | ||||||
|         } |         } | ||||||
|         const command = `rundll32.exe shell32.dll,OpenAs_RunDLL ` + filePath; |         const command = `rundll32.exe shell32.dll,OpenAs_RunDLL ` + filePath; | ||||||
|         exec(command, (err, stdout, stderr) => { |         exec(command, (err, stdout, stderr) => { | ||||||
|             if (err) { |             if (err) { | ||||||
|                 console.error("Open Note custom: ", err); |                 console.error("Open Note custom: ", err); | ||||||
|             open(getFileUrl(noteId), { url: true }); |                 open(getFileUrl(noteId), {url: true}); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } else { |     } else { | ||||||
|         console.log('Currently "Open Note custom" only supports linux and windows systems'); |         console.log('Currently "Open Note custom" only supports linux and windows systems'); | ||||||
|         open(getFileUrl(noteId), { url: true }); |         open(getFileUrl(noteId), {url: true}); | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function downloadNoteRevision(noteId, noteRevisionId) { | function downloadNoteRevision(noteId, noteRevisionId) { | ||||||
|     const url = getUrlForDownload(`api/revisions/${noteRevisionId}/download`); |     const url = getUrlForDownload(`api/revisions/${noteRevisionId}/download`); | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ const TPL = ` | |||||||
|             <kbd data-command="openNoteExternally"></kbd>  |             <kbd data-command="openNoteExternally"></kbd>  | ||||||
|             Open note externally |             Open note externally | ||||||
|         </a> |         </a> | ||||||
|         <a data-trigger-command="openNoteCustom" class="dropdown-item open-note-custom-button"><kbd data-command="openNoteCustom"></kbd> Open note custom (beta)</a> |         <a data-trigger-command="openNoteCustom" class="dropdown-item open-note-custom-button"><kbd data-command="openNoteCustom"></kbd> Open note custom</a> | ||||||
|         <a class="dropdown-item import-files-button">Import files</a> |         <a class="dropdown-item import-files-button">Import files</a> | ||||||
|         <a class="dropdown-item export-note-button">Export note</a> |         <a class="dropdown-item export-note-button">Export note</a> | ||||||
|         <a class="dropdown-item delete-note-button">Delete note</a> |         <a class="dropdown-item delete-note-button">Delete note</a> | ||||||
| @@ -104,7 +104,7 @@ export default class NoteActionsWidget extends NoteContextAwareWidget { | |||||||
|         this.$renderNoteButton.toggle(note.type === 'render'); |         this.$renderNoteButton.toggle(note.type === 'render'); | ||||||
|  |  | ||||||
|         this.$openNoteExternallyButton.toggle(utils.isElectron()); |         this.$openNoteExternallyButton.toggle(utils.isElectron()); | ||||||
|         this.$openNoteCustomButton.toggle(utils.isElectron()); |         this.$openNoteCustomButton.toggle(utils.isElectron() && !utils.isMac()); // no implementation for Mac yet | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async convertNoteIntoAttachmentCommand() { |     async convertNoteIntoAttachmentCommand() { | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ export default class ScrollingContainer extends Container { | |||||||
|  |  | ||||||
|         this.class("scrolling-container"); |         this.class("scrolling-container"); | ||||||
|         this.css('overflow', 'auto'); |         this.css('overflow', 'auto'); | ||||||
|  |         this.css('scroll-behavior', 'smooth'); | ||||||
|         this.css('position', 'relative'); |         this.css('position', 'relative'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -146,20 +146,31 @@ export default class FindWidget extends NoteContextAwareWidget { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         this.handler = await this.getHandler(); | ||||||
|  |  | ||||||
|  |         const selectedText = window.getSelection().toString() || ""; | ||||||
|  |  | ||||||
|         this.$findBox.show(); |         this.$findBox.show(); | ||||||
|         this.$input.focus(); |         this.$input.focus(); | ||||||
|         this.handler = await this.getHandler(); |  | ||||||
|  |  | ||||||
|         const isAlreadyVisible = this.$findBox.is(":visible"); |         const isAlreadyVisible = this.$findBox.is(":visible"); | ||||||
|  |  | ||||||
|         if (isAlreadyVisible) { |         if (isAlreadyVisible) { | ||||||
|  |             if (selectedText) { | ||||||
|  |                 this.$input.val(selectedText); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (this.$input.val()) { | ||||||
|  |                 await this.performFind(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             this.$input.select(); |             this.$input.select(); | ||||||
|         } else { |         } else { | ||||||
|             this.$totalFound.text(0); |             this.$totalFound.text(0); | ||||||
|             this.$currentFound.text(0); |             this.$currentFound.text(0); | ||||||
|             const searchTerm = await this.handler.getInitialSearchTerm(); |             this.$input.val(selectedText); | ||||||
|             this.$input.val(searchTerm || ""); |  | ||||||
|             if (searchTerm !== "") { |             if (selectedText) { | ||||||
|                 this.$input.select(); |                 this.$input.select(); | ||||||
|                 await this.performFind(); |                 await this.performFind(); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -16,23 +16,6 @@ export default class FindInCode { | |||||||
|         return this.parent.noteContext.getCodeEditor(); |         return this.parent.noteContext.getCodeEditor(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async getInitialSearchTerm() { |  | ||||||
|         const codeEditor = await this.getCodeEditor(); |  | ||||||
|  |  | ||||||
|         // highlightSelectionMatches is the overlay that highlights |  | ||||||
|         // the words under the cursor. This occludes the search |  | ||||||
|         // markers style, save it, disable it. It will be restored when |  | ||||||
|         // the focus is back into the note |  | ||||||
|         this.oldHighlightSelectionMatches = codeEditor.getOption("highlightSelectionMatches"); |  | ||||||
|         codeEditor.setOption("highlightSelectionMatches", false); |  | ||||||
|  |  | ||||||
|         // Fill in the findbox with the current selection if any |  | ||||||
|         const selectedText = codeEditor.getSelection() |  | ||||||
|         if (selectedText !== "") { |  | ||||||
|             return selectedText; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async performFind(searchTerm, matchCase, wholeWord) { |     async performFind(searchTerm, matchCase, wholeWord) { | ||||||
|         let findResult = null; |         let findResult = null; | ||||||
|         let totalFound = 0; |         let totalFound = 0; | ||||||
|   | |||||||
| @@ -16,10 +16,6 @@ export default class FindInHtml { | |||||||
|         this.$results = null; |         this.$results = null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async getInitialSearchTerm() { |  | ||||||
|         return ""; // FIXME |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async performFind(searchTerm, matchCase, wholeWord) { |     async performFind(searchTerm, matchCase, wholeWord) { | ||||||
|         await libraryLoader.requireLibrary(libraryLoader.MARKJS); |         await libraryLoader.requireLibrary(libraryLoader.MARKJS); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,19 +8,6 @@ export default class FindInText { | |||||||
|         return this.parent.noteContext.getTextEditor(); |         return this.parent.noteContext.getTextEditor(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async getInitialSearchTerm() { |  | ||||||
|         const textEditor = await this.getTextEditor(); |  | ||||||
|  |  | ||||||
|         const selection = textEditor.model.document.selection; |  | ||||||
|         const range = selection.getFirstRange(); |  | ||||||
|  |  | ||||||
|         // FIXME |  | ||||||
|         for (const item of range.getItems()) { |  | ||||||
|             // Fill in the findbox with the current selection if any |  | ||||||
|             return item.data; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async performFind(searchTerm, matchCase, wholeWord) { |     async performFind(searchTerm, matchCase, wholeWord) { | ||||||
|         // Do this even if the searchTerm is empty so the markers are cleared and |         // Do this even if the searchTerm is empty so the markers are cleared and | ||||||
|         // the counters updated |         // the counters updated | ||||||
|   | |||||||
| @@ -177,7 +177,7 @@ export default class TocWidget extends RightPanelWidget { | |||||||
|             const headingElement = $container.find(":header")[headingIndex]; |             const headingElement = $container.find(":header")[headingIndex]; | ||||||
|  |  | ||||||
|             if (headingElement != null) { |             if (headingElement != null) { | ||||||
|                 headingElement.scrollIntoView(); |                 headingElement.scrollIntoView({ behavior: "smooth" }); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             const textEditor = await this.noteContext.getTextEditor(); |             const textEditor = await this.noteContext.getTextEditor(); | ||||||
| @@ -193,50 +193,9 @@ export default class TocWidget extends RightPanelWidget { | |||||||
|             // navigate (note that the TOC rendering and other TOC |             // navigate (note that the TOC rendering and other TOC | ||||||
|             // entries' navigation could be wrong too) |             // entries' navigation could be wrong too) | ||||||
|             if (headingNode != null) { |             if (headingNode != null) { | ||||||
|                 // Setting the selection alone doesn't scroll to the |                 $(textEditor.editing.view.domRoots.values().next().value).find(':header')[headingIndex].scrollIntoView({ | ||||||
|                 // caret, needs to be done explicitly and outside of |                     behavior: 'smooth' | ||||||
|                 // the writer change callback so the scroll is |  | ||||||
|                 // guaranteed to happen after the selection is |  | ||||||
|                 // updated. |  | ||||||
|  |  | ||||||
|                 // In addition, scrolling to a caret later in the |  | ||||||
|                 // document (ie "forward scrolls"), only scrolls |  | ||||||
|                 // barely enough to place the caret at the bottom of |  | ||||||
|                 // the screen, which is a usability issue, you would |  | ||||||
|                 // like the caret to be placed at the top or center |  | ||||||
|                 // of the screen. |  | ||||||
|  |  | ||||||
|                 // To work around that issue, first scroll to the |  | ||||||
|                 // end of the document, then scroll to the desired |  | ||||||
|                 // point. This causes all the scrolls to be |  | ||||||
|                 // "backward scrolls" no matter the current caret |  | ||||||
|                 // position, which places the caret at the top of |  | ||||||
|                 // the screen. |  | ||||||
|  |  | ||||||
|                 // XXX This could be fixed in another way by using |  | ||||||
|                 //     the underlying CKEditor5 |  | ||||||
|                 //     scrollViewportToShowTarget, which allows to |  | ||||||
|                 //     provide a larger "viewportOffset", but that |  | ||||||
|                 //     has coding complications (requires calling an |  | ||||||
|                 //     internal CKEditor utils funcion and passing |  | ||||||
|                 //     an HTML element, not a CKEditor node, and |  | ||||||
|                 //     CKEditor5 doesn't seem to have a |  | ||||||
|                 //     straightforward way to convert a node to an |  | ||||||
|                 //     HTML element? (in CKEditor4 this was done |  | ||||||
|                 //     with $(node.$) ) |  | ||||||
|  |  | ||||||
|                 // Scroll to the end of the note to guarantee the |  | ||||||
|                 // next scroll is a backwards scroll that places the |  | ||||||
|                 // caret at the top of the screen |  | ||||||
|                 model.change(writer => { |  | ||||||
|                     writer.setSelection(root.getChild(root.childCount - 1), 0); |  | ||||||
|                 }); |                 }); | ||||||
|                 textEditor.editing.view.scrollToTheSelection(); |  | ||||||
|                 // Backwards scroll to the heading |  | ||||||
|                 model.change(writer => { |  | ||||||
|                     writer.setSelection(headingNode, 0); |  | ||||||
|                 }); |  | ||||||
|                 textEditor.editing.view.scrollToTheSelection(); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ const TPL = ` | |||||||
|             display: block; |             display: block; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         .excalidraw-wrapper { |         .excalidraw-wrapper { | ||||||
|             height: 100%; |             height: 100%; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ export default class ImageOptions extends OptionsWidget { | |||||||
|             this.updateOption('imageMaxWidthHeight', this.$imageMaxWidthHeight.val())); |             this.updateOption('imageMaxWidthHeight', this.$imageMaxWidthHeight.val())); | ||||||
|  |  | ||||||
|         this.$imageJpegQuality.on('change', () => |         this.$imageJpegQuality.on('change', () => | ||||||
|             this.updateOption('imageJpegQuality', this.$imageJpegQuality.val())); |             this.updateOption('imageJpegQuality', this.$imageJpegQuality.val().trim() || "75")); | ||||||
|  |  | ||||||
|         this.$downloadImagesAutomatically = this.$widget.find(".download-images-automatically"); |         this.$downloadImagesAutomatically = this.$widget.find(".download-images-automatically"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -402,6 +402,42 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th | |||||||
| .bs-tooltip-left .arrow::before   { border-left-color: var(--main-border-color) !important; } | .bs-tooltip-left .arrow::before   { border-left-color: var(--main-border-color) !important; } | ||||||
| .bs-tooltip-right .arrow::before  { border-right-color: var(--main-border-color) !important; } | .bs-tooltip-right .arrow::before  { border-right-color: var(--main-border-color) !important; } | ||||||
|  |  | ||||||
|  | .bs-tooltip-bottom .arrow::after { border-bottom-color: var(--tooltip-background-color) !important; } | ||||||
|  | .bs-tooltip-top .arrow::after    { border-top-color: var(--tooltip-background-color) !important; } | ||||||
|  | .bs-tooltip-left .arrow::after   { border-left-color: var(--tooltip-background-color) !important; } | ||||||
|  | .bs-tooltip-right .arrow::after  { border-right-color: var(--tooltip-background-color) !important; } | ||||||
|  |  | ||||||
|  | .tooltip .arrow::after { | ||||||
|  |     position: absolute; | ||||||
|  |     content: ''; | ||||||
|  |     border-color: transparent; | ||||||
|  |     border-style: solid; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .bs-tooltip-auto[x-placement^='left'] .arrow::after, | ||||||
|  | .bs-tooltip-left .arrow::after { | ||||||
|  |     left: -1px; | ||||||
|  |     border-width: 0.4rem 0 0.4rem 0.4rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .bs-tooltip-auto[x-placement^='bottom'] .arrow::after, | ||||||
|  | .bs-tooltip-bottom .arrow::after { | ||||||
|  |     bottom: -1px; | ||||||
|  |     border-width: 0 0.4rem 0.4rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .bs-tooltip-auto[x-placement^='right'] .arrow::after, | ||||||
|  | .bs-tooltip-right .arrow::after { | ||||||
|  |     right: -1px; | ||||||
|  |     border-width: 0.4rem 0.4rem 0.4rem 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .bs-tooltip-auto[x-placement^='top'] .arrow::after, | ||||||
|  | .bs-tooltip-top .arrow::after { | ||||||
|  |     top: -1px; | ||||||
|  |     border-width: 0.4rem 0.4rem 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| .note-tooltip.tooltip .arrow { | .note-tooltip.tooltip .arrow { | ||||||
|     display: none; |     display: none; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -110,8 +110,8 @@ function checkCredentials(req, res, next) { | |||||||
|  |  | ||||||
|     const header = req.headers['trilium-cred'] || ''; |     const header = req.headers['trilium-cred'] || ''; | ||||||
|     const auth = new Buffer.from(header, 'base64').toString(); |     const auth = new Buffer.from(header, 'base64').toString(); | ||||||
|     const [username, password] = auth.split(/:/); |     const colonIndex = auth.indexOf(':'); | ||||||
|  |     const password = colonIndex === -1 ? "" : auth.substr(colonIndex + 1); | ||||||
|     // username is ignored |     // username is ignored | ||||||
|  |  | ||||||
|     if (!passwordEncryptionService.verifyPassword(password)) { |     if (!passwordEncryptionService.verifyPassword(password)) { | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| module.exports = { buildDate:"2023-04-17T21:40:35+02:00", buildRevision: "1d3272e9f8c27106a66227fbb580677ae5d70427" }; | module.exports = { buildDate:"2023-05-18T23:31:57+02:00", buildRevision: "14dd2b882750ea5484d1aba1f2b57c931bc76e9c" }; | ||||||
|   | |||||||
| @@ -169,7 +169,7 @@ function saveImageToAttachment(noteId, uploadBuffer, originalName, shrinkImageSw | |||||||
| } | } | ||||||
|  |  | ||||||
| async function shrinkImage(buffer, originalName) { | async function shrinkImage(buffer, originalName) { | ||||||
|     let jpegQuality = optionService.getOptionInt('imageJpegQuality'); |     let jpegQuality = optionService.getOptionInt('imageJpegQuality', 0); | ||||||
|  |  | ||||||
|     if (jpegQuality < 10 || jpegQuality > 100) { |     if (jpegQuality < 10 || jpegQuality > 100) { | ||||||
|         jpegQuality = 75; |         jpegQuality = 75; | ||||||
|   | |||||||
| @@ -29,13 +29,17 @@ function getOption(name) { | |||||||
| /** | /** | ||||||
|  * @returns {integer} |  * @returns {integer} | ||||||
|  */ |  */ | ||||||
| function getOptionInt(name) { | function getOptionInt(name, defaultValue = undefined) { | ||||||
|     const val = getOption(name); |     const val = getOption(name); | ||||||
|  |  | ||||||
|     const intVal = parseInt(val); |     const intVal = parseInt(val); | ||||||
|  |  | ||||||
|     if (isNaN(intVal)) { |     if (isNaN(intVal)) { | ||||||
|  |         if (defaultValue === undefined) { | ||||||
|             throw new Error(`Could not parse '${val}' into integer for option '${name}'`); |             throw new Error(`Could not parse '${val}' into integer for option '${name}'`); | ||||||
|  |         } else { | ||||||
|  |             return defaultValue; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return intVal; |     return intVal; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user