mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	Merge branch 'stable'
# Conflicts: # src/services/notes.js
This commit is contained in:
		| @@ -76,8 +76,7 @@ async function initContextMenu(event, contextMenu) { | |||||||
|     // in such case we'll position it above click coordinates so it will fit into client |     // in such case we'll position it above click coordinates so it will fit into client | ||||||
|     const clickPosition = event.pageY; |     const clickPosition = event.pageY; | ||||||
|     const clientHeight = document.documentElement.clientHeight; |     const clientHeight = document.documentElement.clientHeight; | ||||||
|     const contextMenuHeight = $contextMenuContainer.height(); |     const contextMenuHeight = $contextMenuContainer.outerHeight() + 30; | ||||||
|  |  | ||||||
|     let top; |     let top; | ||||||
|  |  | ||||||
|     if (clickPosition + contextMenuHeight > clientHeight) { |     if (clickPosition + contextMenuHeight > clientHeight) { | ||||||
|   | |||||||
| @@ -201,17 +201,13 @@ async function loadNoteDetail(origNotePath, options = {}) { | |||||||
|     const newTab = !!options.newTab; |     const newTab = !!options.newTab; | ||||||
|     const activate = !!options.activate; |     const activate = !!options.activate; | ||||||
|  |  | ||||||
|     const notePath = await treeService.resolveNotePath(origNotePath); |     let notePath = await treeService.resolveNotePath(origNotePath); | ||||||
|  |  | ||||||
|     if (!notePath) { |     if (!notePath) { | ||||||
|         console.error(`Cannot resolve note path ${origNotePath}`); |         console.error(`Cannot resolve note path ${origNotePath}`); | ||||||
|  |  | ||||||
|         // fallback to display something |         // fallback to display something | ||||||
|         if (tabContexts.length === 0) { |         notePath = 'root'; | ||||||
|             await openEmptyTab(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const noteId = treeUtils.getNoteIdFromNotePath(notePath); |     const noteId = treeUtils.getNoteIdFromNotePath(notePath); | ||||||
|   | |||||||
| @@ -47,6 +47,7 @@ class NoteDetailText { | |||||||
|         this.ctx = ctx; |         this.ctx = ctx; | ||||||
|         this.$component = ctx.$tabContent.find('.note-detail-text'); |         this.$component = ctx.$tabContent.find('.note-detail-text'); | ||||||
|         this.$editorEl = this.$component.find('.note-detail-text-editor'); |         this.$editorEl = this.$component.find('.note-detail-text-editor'); | ||||||
|  |         this.textEditorPromise = null; | ||||||
|         this.textEditor = null; |         this.textEditor = null; | ||||||
|  |  | ||||||
|         this.$component.on("dblclick", "img", e => { |         this.$component.on("dblclick", "img", e => { | ||||||
| @@ -67,44 +68,12 @@ class NoteDetailText { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async render() { |     async render() { | ||||||
|         if (!this.textEditor) { |         if (!this.textEditorPromise) { | ||||||
|             await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); |             this.textEditorPromise = this.initEditor(); | ||||||
|  |  | ||||||
|             const codeBlockLanguages = |  | ||||||
|                 (await mimeTypesService.getMimeTypes()) |  | ||||||
|                     .filter(mt => mt.enabled) |  | ||||||
|                     .map(mt => { |  | ||||||
|                         return { |  | ||||||
|                             language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"), |  | ||||||
|                             label: mt.title |  | ||||||
|                         } |  | ||||||
|                     }); |  | ||||||
|  |  | ||||||
|             // CKEditor since version 12 needs the element to be visible before initialization. At the same time |  | ||||||
|             // we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate |  | ||||||
|             // display of $component in both branches. |  | ||||||
|             this.$component.show(); |  | ||||||
|  |  | ||||||
|             // textEditor might have been initialized during previous await so checking again |  | ||||||
|             // looks like double initialization can freeze CKEditor pretty badly |  | ||||||
|             if (!this.textEditor) { |  | ||||||
|                 this.textEditor = await BalloonEditor.create(this.$editorEl[0], { |  | ||||||
|                     placeholder: "Type the content of your note here ...", |  | ||||||
|                     mention: mentionSetup, |  | ||||||
|                     codeBlock: { |  | ||||||
|                         languages: codeBlockLanguages |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|  |  | ||||||
|                 if (glob.isDev && ENABLE_INSPECTOR) { |  | ||||||
|                     await import('../../libraries/ckeditor/inspector.js'); |  | ||||||
|                     CKEditorInspector.attach(this.textEditor); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 this.onNoteChange(() => this.ctx.noteChanged()); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         await this.textEditorPromise; | ||||||
|  |  | ||||||
|         // lazy loading above can take time and tab might have been already switched to another note |         // lazy loading above can take time and tab might have been already switched to another note | ||||||
|         if (this.ctx.note && this.ctx.note.type === 'text') { |         if (this.ctx.note && this.ctx.note.type === 'text') { | ||||||
|             this.textEditor.isReadOnly = await this.isReadOnly(); |             this.textEditor.isReadOnly = await this.isReadOnly(); | ||||||
| @@ -115,6 +84,42 @@ class NoteDetailText { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async initEditor() { | ||||||
|  |         await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); | ||||||
|  |  | ||||||
|  |         const codeBlockLanguages = | ||||||
|  |             (await mimeTypesService.getMimeTypes()) | ||||||
|  |                 .filter(mt => mt.enabled) | ||||||
|  |                 .map(mt => { | ||||||
|  |                     return { | ||||||
|  |                         language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"), | ||||||
|  |                         label: mt.title | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |         // CKEditor since version 12 needs the element to be visible before initialization. At the same time | ||||||
|  |         // we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate | ||||||
|  |         // display of $component in both branches. | ||||||
|  |         this.$component.show(); | ||||||
|  |  | ||||||
|  |         const textEditorInstance = await BalloonEditor.create(this.$editorEl[0], { | ||||||
|  |             placeholder: "Type the content of your note here ...", | ||||||
|  |             mention: mentionSetup, | ||||||
|  |             codeBlock: { | ||||||
|  |                 languages: codeBlockLanguages | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         if (glob.isDev && ENABLE_INSPECTOR) { | ||||||
|  |             await import('../../libraries/ckeditor/inspector.js'); | ||||||
|  |             CKEditorInspector.attach(textEditorInstance); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.textEditor = textEditorInstance; | ||||||
|  |  | ||||||
|  |         this.onNoteChange(() => this.ctx.noteChanged()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     getContent() { |     getContent() { | ||||||
|         const content = this.textEditor.getData(); |         const content = this.textEditor.getData(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -350,8 +350,6 @@ class TabContext { | |||||||
|  |  | ||||||
|         this.$savedIndicator.fadeIn(); |         this.$savedIndicator.fadeIn(); | ||||||
|  |  | ||||||
|         this.$scriptArea.empty(); |  | ||||||
|  |  | ||||||
|         // run async |         // run async | ||||||
|         bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this); |         bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ body { | |||||||
|  |  | ||||||
| #context-menu-container { | #context-menu-container { | ||||||
|     max-height: 100vh; |     max-height: 100vh; | ||||||
|     overflow: auto; /* make it scrollable when exceeding total height of the window */ |     /* !!! Cannot set overflow: auto, submenus will break !!! */ | ||||||
| } | } | ||||||
|  |  | ||||||
| #context-menu-container, #context-menu-container .dropdown-menu { | #context-menu-container, #context-menu-container .dropdown-menu { | ||||||
|   | |||||||
| @@ -594,6 +594,8 @@ async function eraseDeletedNotes() { | |||||||
|         SET name = 'deleted', |         SET name = 'deleted', | ||||||
|             value = '' |             value = '' | ||||||
|         WHERE noteId IN (???)`, noteIdsToErase); |         WHERE noteId IN (???)`, noteIdsToErase); | ||||||
|  |  | ||||||
|  |     log.info(`Erased notes: ${JSON.stringify(noteIdsToErase)}`); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function duplicateNote(noteId, parentNoteId) { | async function duplicateNote(noteId, parentNoteId) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user