mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			v0.27.0-be
			...
			v0.27.1-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ecdc5865a6 | ||
|  | 1771ddb787 | ||
|  | 3ab657fe46 | ||
|  | 8785dae753 | ||
|  | 2f1c5b29d4 | ||
|  | 7135349a10 | ||
|  | 66c639d5e3 | ||
|  | 6704b755d8 | 
							
								
								
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "version": "0.26.1", |   "version": "0.27.0-beta", | ||||||
|   "lockfileVersion": 1, |   "lockfileVersion": 1, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "productName": "Trilium Notes", |   "productName": "Trilium Notes", | ||||||
|   "description": "Trilium Notes", |   "description": "Trilium Notes", | ||||||
|   "version": "0.27.0-beta", |   "version": "0.27.1-beta", | ||||||
|   "license": "AGPL-3.0-only", |   "license": "AGPL-3.0-only", | ||||||
|   "main": "electron.js", |   "main": "electron.js", | ||||||
|   "bin": { |   "bin": { | ||||||
|   | |||||||
| @@ -85,8 +85,11 @@ async function showAttributes() { | |||||||
|         $promotedAttributesContainer.empty().append($tbody); |         $promotedAttributesContainer.empty().append($tbody); | ||||||
|     } |     } | ||||||
|     else if (note.type !== 'relation-map') { |     else if (note.type !== 'relation-map') { | ||||||
|         if (attributes.length > 0) { |         // display only "own" notes | ||||||
|             for (const attribute of attributes) { |         const ownedAttributes = attributes.filter(attr => attr.noteId === note.noteId); | ||||||
|  |  | ||||||
|  |         if (ownedAttributes.length > 0) { | ||||||
|  |             for (const attribute of ownedAttributes) { | ||||||
|                 if (attribute.type === 'label') { |                 if (attribute.type === 'label') { | ||||||
|                     $attributeListInner.append(utils.formatLabel(attribute) + " "); |                     $attributeListInner.append(utils.formatLabel(attribute) + " "); | ||||||
|                 } |                 } | ||||||
| @@ -132,7 +135,9 @@ async function createPromotedAttributeRow(definitionAttr, valueAttr) { | |||||||
|     const $inputCell = $("<td>").append($("<div>").addClass("input-group").append($input)); |     const $inputCell = $("<td>").append($("<div>").addClass("input-group").append($input)); | ||||||
|  |  | ||||||
|     const $actionCell = $("<td>"); |     const $actionCell = $("<td>"); | ||||||
|     const $multiplicityCell = $("<td>").addClass("multiplicity"); |     const $multiplicityCell = $("<td>") | ||||||
|  |         .addClass("multiplicity") | ||||||
|  |         .attr("nowrap", true); | ||||||
|  |  | ||||||
|     $tr |     $tr | ||||||
|         .append($labelCell) |         .append($labelCell) | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import treeCache from './tree_cache.js'; | |||||||
| import noteDetailService from './note_detail.js'; | import noteDetailService from './note_detail.js'; | ||||||
| import noteTypeService from './note_type.js'; | import noteTypeService from './note_type.js'; | ||||||
| import noteTooltipService from './note_tooltip.js'; | import noteTooltipService from './note_tooltip.js'; | ||||||
|  | import protectedSessionService from'./protected_session.js'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This is the main frontend API interface for scripts. It's published in the local "api" object. |  * This is the main frontend API interface for scripts. It's published in the local "api" object. | ||||||
| @@ -42,7 +43,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | |||||||
|     this.activateNewNote = async notePath => { |     this.activateNewNote = async notePath => { | ||||||
|         await treeService.reload(); |         await treeService.reload(); | ||||||
|  |  | ||||||
|         await treeService.activateNote(notePath, true); |         await treeService.activateNote(notePath, noteDetailService.focusOnTitle); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -244,7 +245,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) { | |||||||
|      * @method |      * @method | ||||||
|      * @param {object} $el - jquery object on which to setup the tooltip |      * @param {object} $el - jquery object on which to setup the tooltip | ||||||
|      */ |      */ | ||||||
|     this.setupElementTooltip = noteTooltipService.setupElementTooltip |     this.setupElementTooltip = noteTooltipService.setupElementTooltip; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @method | ||||||
|  |      */ | ||||||
|  |     this.protectCurrentNote = protectedSessionService.protectNoteAndSendToServer; | ||||||
| } | } | ||||||
|  |  | ||||||
| export default FrontendScriptApi; | export default FrontendScriptApi; | ||||||
| @@ -37,6 +37,8 @@ let noteChangeDisabled = false; | |||||||
|  |  | ||||||
| let isNoteChanged = false; | let isNoteChanged = false; | ||||||
|  |  | ||||||
|  | let detailLoadedListeners = []; | ||||||
|  |  | ||||||
| const components = { | const components = { | ||||||
|     'code': noteDetailCode, |     'code': noteDetailCode, | ||||||
|     'text': noteDetailText, |     'text': noteDetailText, | ||||||
| @@ -147,12 +149,6 @@ function setNoteBackgroundIfProtected(note) { | |||||||
|     $unprotectButton.prop("disabled", !protectedSessionHolder.isProtectedSessionAvailable()); |     $unprotectButton.prop("disabled", !protectedSessionHolder.isProtectedSessionAvailable()); | ||||||
| } | } | ||||||
|  |  | ||||||
| let isNewNoteCreated = false; |  | ||||||
|  |  | ||||||
| function newNoteCreated() { |  | ||||||
|     isNewNoteCreated = true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function handleProtectedSession() { | async function handleProtectedSession() { | ||||||
|     const newSessionCreated = await protectedSessionService.ensureProtectedSession(currentNote.isProtected, false); |     const newSessionCreated = await protectedSessionService.ensureProtectedSession(currentNote.isProtected, false); | ||||||
|  |  | ||||||
| @@ -191,12 +187,6 @@ async function loadNoteDetail(noteId) { | |||||||
|         attributeService.invalidateAttributes(); |         attributeService.invalidateAttributes(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (isNewNoteCreated) { |  | ||||||
|         isNewNoteCreated = false; |  | ||||||
|  |  | ||||||
|         $noteTitle.focus().select(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $noteIdDisplay.html(noteId); |     $noteIdDisplay.html(noteId); | ||||||
|  |  | ||||||
|     setNoteBackgroundIfProtected(currentNote); |     setNoteBackgroundIfProtected(currentNote); | ||||||
| @@ -240,11 +230,13 @@ async function loadNoteDetail(noteId) { | |||||||
|     // after loading new note make sure editor is scrolled to the top |     // after loading new note make sure editor is scrolled to the top | ||||||
|     getComponent(currentNote.type).scrollToTop(); |     getComponent(currentNote.type).scrollToTop(); | ||||||
|  |  | ||||||
|     if (utils.isDesktop()) { |     fireDetailLoaded(); | ||||||
|  |  | ||||||
|     $scriptArea.empty(); |     $scriptArea.empty(); | ||||||
|  |  | ||||||
|     await bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteView'); |     await bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteView'); | ||||||
|  |  | ||||||
|  |     if (utils.isDesktop()) { | ||||||
|         await attributeService.showAttributes(); |         await attributeService.showAttributes(); | ||||||
|  |  | ||||||
|         await showChildrenOverview(); |         await showChildrenOverview(); | ||||||
| @@ -291,6 +283,30 @@ function focusOnTitle() { | |||||||
|     $noteTitle.focus(); |     $noteTitle.focus(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Since detail loading may take some time and user might just browse through the notes using UP-DOWN keys, | ||||||
|  |  * we intentionally decouple activation of the note in the tree and full load of the note so just avaiting on | ||||||
|  |  * fancytree's activate() won't wait for the full load. | ||||||
|  |  * | ||||||
|  |  * This causes an issue where in some cases you want to do some action after detail is loaded. For this reason | ||||||
|  |  * we provide the listeners here which will be triggered after the detail is loaded and if the loaded note | ||||||
|  |  * is the one registered in the listener. | ||||||
|  |  */ | ||||||
|  | function addDetailLoadedListener(noteId, callback) { | ||||||
|  |     detailLoadedListeners.push({ noteId, callback }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function fireDetailLoaded() { | ||||||
|  |     for (const {noteId, callback} of detailLoadedListeners) { | ||||||
|  |         if (noteId === currentNote.noteId) { | ||||||
|  |             callback(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // all the listeners are one time only | ||||||
|  |     detailLoadedListeners = []; | ||||||
|  | } | ||||||
|  |  | ||||||
| messagingService.subscribeToSyncMessages(syncData => { | messagingService.subscribeToSyncMessages(syncData => { | ||||||
|     if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === getCurrentNoteId())) { |     if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === getCurrentNoteId())) { | ||||||
|         infoService.showMessage('Reloading note because of background changes'); |         infoService.showMessage('Reloading note because of background changes'); | ||||||
| @@ -325,11 +341,11 @@ export default { | |||||||
|     getCurrentNote, |     getCurrentNote, | ||||||
|     getCurrentNoteType, |     getCurrentNoteType, | ||||||
|     getCurrentNoteId, |     getCurrentNoteId, | ||||||
|     newNoteCreated, |  | ||||||
|     focusOnTitle, |     focusOnTitle, | ||||||
|     saveNote, |     saveNote, | ||||||
|     saveNoteIfChanged, |     saveNoteIfChanged, | ||||||
|     noteChanged, |     noteChanged, | ||||||
|     getCurrentNoteContent, |     getCurrentNoteContent, | ||||||
|     onNoteChange |     onNoteChange, | ||||||
|  |     addDetailLoadedListener | ||||||
| }; | }; | ||||||
| @@ -184,5 +184,6 @@ export default { | |||||||
|     protectSubtree, |     protectSubtree, | ||||||
|     ensureDialogIsClosed, |     ensureDialogIsClosed, | ||||||
|     enterProtectedSession, |     enterProtectedSession, | ||||||
|     leaveProtectedSession |     leaveProtectedSession, | ||||||
|  |     protectNoteAndSendToServer | ||||||
| }; | }; | ||||||
| @@ -83,6 +83,10 @@ async function setNodeTitleWithPrefix(node) { | |||||||
|     node.setTitle(utils.escapeHtml(title)); |     node.setTitle(utils.escapeHtml(title)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function getNode(childNoteId, parentNoteId) { | ||||||
|  |     return getNodesByNoteId(childNoteId).find(node => !parentNoteId || node.data.parentNoteId === parentNoteId); | ||||||
|  | } | ||||||
|  |  | ||||||
| async function expandToNote(notePath, expandOpts) { | async function expandToNote(notePath, expandOpts) { | ||||||
|     utils.assertArguments(notePath); |     utils.assertArguments(notePath); | ||||||
|  |  | ||||||
| @@ -94,7 +98,18 @@ async function expandToNote(notePath, expandOpts) { | |||||||
|  |  | ||||||
|     for (const childNoteId of runPath) { |     for (const childNoteId of runPath) { | ||||||
|         // for first node (!parentNoteId) it doesn't matter which node is found |         // for first node (!parentNoteId) it doesn't matter which node is found | ||||||
|         const node = getNodesByNoteId(childNoteId).find(node => !parentNoteId || node.data.parentNoteId === parentNoteId); |         let node = getNode(childNoteId, parentNoteId); | ||||||
|  |  | ||||||
|  |         if (!node && parentNoteId) { | ||||||
|  |             const parents = getNodesByNoteId(parentNoteId); | ||||||
|  |  | ||||||
|  |             for (const parent of parents) { | ||||||
|  |                 // force load parents. This is useful when fancytree doesn't contain recently created notes yet. | ||||||
|  |                 await parent.load(true); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             node = getNode(childNoteId, parentNoteId); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (!node) { |         if (!node) { | ||||||
|             console.error(`Can't find node for noteId=${childNoteId} with parentNoteId=${parentNoteId}`); |             console.error(`Can't find node for noteId=${childNoteId} with parentNoteId=${parentNoteId}`); | ||||||
| @@ -111,7 +126,7 @@ async function expandToNote(notePath, expandOpts) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async function activateNote(notePath, newNote) { | async function activateNote(notePath, noteLoadedListener) { | ||||||
|     utils.assertArguments(notePath); |     utils.assertArguments(notePath); | ||||||
|  |  | ||||||
|     const hoistedNoteId = await hoistedNoteService.getHoistedNoteId(); |     const hoistedNoteId = await hoistedNoteService.getHoistedNoteId(); | ||||||
| @@ -131,8 +146,8 @@ async function activateNote(notePath, newNote) { | |||||||
|  |  | ||||||
|     const node = await expandToNote(notePath); |     const node = await expandToNote(notePath); | ||||||
|  |  | ||||||
|     if (newNote) { |     if (noteLoadedListener) { | ||||||
|         noteDetailService.newNoteCreated(); |         noteDetailService.addDetailLoadedListener(node.data.noteId, noteLoadedListener); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // we use noFocus because when we reload the tree because of background changes |     // we use noFocus because when we reload the tree because of background changes | ||||||
| @@ -547,7 +562,7 @@ async function createNote(node, parentNoteId, target, isProtected, saveSelection | |||||||
|  |  | ||||||
|     await noteDetailService.saveNoteIfChanged(); |     await noteDetailService.saveNoteIfChanged(); | ||||||
|  |  | ||||||
|     noteDetailService.newNoteCreated(); |     noteDetailService.addDetailLoadedListener(note.noteId, noteDetailService.focusOnTitle); | ||||||
|  |  | ||||||
|     const noteEntity = new NoteShort(treeCache, note); |     const noteEntity = new NoteShort(treeCache, note); | ||||||
|     const branchEntity = new Branch(treeCache, branch); |     const branchEntity = new Branch(treeCache, branch); | ||||||
|   | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -53,6 +53,7 @@ | |||||||
|     padding: 10px 0 10px 0; |     padding: 10px 0 10px 0; | ||||||
|     margin: 0 10px 0 16px; |     margin: 0 10px 0 16px; | ||||||
|     border: 1px solid #ccc; |     border: 1px solid #ccc; | ||||||
|  |     border-radius: 5px; | ||||||
| } | } | ||||||
|  |  | ||||||
| #context-menu-container { | #context-menu-container { | ||||||
|   | |||||||
| @@ -70,6 +70,7 @@ body { | |||||||
|     height: 100%; |     height: 100%; | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|  |     min-height: 200px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .note-detail-component { | .note-detail-component { | ||||||
| @@ -311,6 +312,12 @@ div.ui-tooltip { | |||||||
|  |  | ||||||
| .cm-matchhighlight {background-color: #eeeeee} | .cm-matchhighlight {background-color: #eeeeee} | ||||||
|  |  | ||||||
|  | #attribute-list { | ||||||
|  |     overflow: auto; | ||||||
|  |     /* limiting the size since actual note content is more important */ | ||||||
|  |     max-height: 30%; | ||||||
|  | } | ||||||
|  |  | ||||||
| #label-list, #relation-list, #attribute-list { | #label-list, #relation-list, #attribute-list { | ||||||
|     color: #777777; |     color: #777777; | ||||||
|     padding: 5px; |     padding: 5px; | ||||||
| @@ -434,8 +441,13 @@ html.theme-dark body { | |||||||
| } | } | ||||||
|  |  | ||||||
| #note-detail-promoted-attributes { | #note-detail-promoted-attributes { | ||||||
|     max-width: 70%; |  | ||||||
|     margin: auto; |     margin: auto; | ||||||
|  |     /* setting the display to block since "table" doesn't support scrolling */ | ||||||
|  |     display: block; | ||||||
|  |     flex-basis: content; | ||||||
|  |     flex-shrink: 1; | ||||||
|  |     flex-grow: 100; | ||||||
|  |     overflow: auto; | ||||||
| } | } | ||||||
|  |  | ||||||
| #note-detail-promoted-attributes td, #note-detail-promoted-attributes th { | #note-detail-promoted-attributes td, #note-detail-promoted-attributes th { | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| module.exports = { buildDate:"2018-12-30T22:38:11+01:00", buildRevision: "32220476aa6795bab036b7dd9057ea3357d7dd51" }; | module.exports = { buildDate:"2019-01-01T20:54:23+01:00", buildRevision: "1771ddb78783352970ef64906af8c8fe117183d0" }; | ||||||
|   | |||||||
| @@ -153,7 +153,8 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {}) | |||||||
|             noteId: note.noteId, |             noteId: note.noteId, | ||||||
|             type: attr.type, |             type: attr.type, | ||||||
|             name: attr.name, |             name: attr.name, | ||||||
|             value: attr.value |             value: attr.value, | ||||||
|  |             isInheritable: !!attr.isInheritable | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -357,10 +358,12 @@ async function deleteNote(branch) { | |||||||
|     const notDeletedBranches = await note.getBranches(); |     const notDeletedBranches = await note.getBranches(); | ||||||
|  |  | ||||||
|     if (notDeletedBranches.length === 0) { |     if (notDeletedBranches.length === 0) { | ||||||
|         note.isDeleted = true; |         // maybe a bit counter-intuitively, protected notes can be deleted also outside of protected session | ||||||
|         // we don't reset content here, that's postponed and done later to give the user |         // this is because protected notes offer only confidentiality which makes some things simpler - e.g. deletion UI | ||||||
|         // a chance to correct a mistake |         // to allow this, we just set the isDeleted flag, otherwise saving would fail because of attempt to encrypt | ||||||
|         await note.save(); |         // content with non-existent protected session key | ||||||
|  |         // we don't reset content here, that's postponed and done later to give the user a chance to correct a mistake | ||||||
|  |         await sql.execute("UPDATE notes SET isDeleted = 1 WHERE noteId = ?", [note.noteId]); | ||||||
|  |  | ||||||
|         for (const noteRevision of await note.getRevisions()) { |         for (const noteRevision of await note.getRevisions()) { | ||||||
|             await noteRevision.save(); |             await noteRevision.save(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user