mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	initializing note tree synchronously
This commit is contained in:
		| @@ -28,6 +28,11 @@ class Branch { | |||||||
|         return this.treeCache.getNote(this.noteId); |         return this.treeCache.getNote(this.noteId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** @returns {NoteShort} */ | ||||||
|  |     getNoteFromCache() { | ||||||
|  |         return this.treeCache.getNoteFromCache(this.noteId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** @returns {NoteShort} */ |     /** @returns {NoteShort} */ | ||||||
|     async getParentNote() { |     async getParentNote() { | ||||||
|         return this.treeCache.getNote(this.parentNoteId); |         return this.treeCache.getNote(this.parentNoteId); | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ async function resolveNotePathToSegments(notePath, logErrors = true) { | |||||||
|  |  | ||||||
|             if (!parents.some(p => p.noteId === parentNoteId)) { |             if (!parents.some(p => p.noteId === parentNoteId)) { | ||||||
|                 if (logErrors) { |                 if (logErrors) { | ||||||
|                     console.log(utils.now(), `Did not find parent ${parentNoteId} for child ${childNoteId}, available parents: ${parents}`); |                     console.log(utils.now(), `Did not find parent ${parentNoteId} for child ${childNoteId}, available parents: ${parents.map(p => p.noteId)}`); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 const someNotePath = getSomeNotePath(parents[0]); |                 const someNotePath = getSomeNotePath(parents[0]); | ||||||
|   | |||||||
| @@ -20,8 +20,6 @@ class TreeCache { | |||||||
|     async loadInitialTree() { |     async loadInitialTree() { | ||||||
|         const resp = await server.get('tree'); |         const resp = await server.get('tree'); | ||||||
|  |  | ||||||
|         await this.loadParents(resp, false); |  | ||||||
|  |  | ||||||
|         // clear the cache only directly before adding new content which is important for e.g. switching to protected session |         // clear the cache only directly before adding new content which is important for e.g. switching to protected session | ||||||
|  |  | ||||||
|         /** @type {Object.<string, NoteShort>} */ |         /** @type {Object.<string, NoteShort>} */ | ||||||
| @@ -39,6 +37,14 @@ class TreeCache { | |||||||
|         this.addResp(resp); |         this.addResp(resp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async loadSubTree(subTreeNoteId) { | ||||||
|  |         const resp = await server.get('tree?subTreeNoteId=' + subTreeNoteId); | ||||||
|  |  | ||||||
|  |         this.addResp(resp); | ||||||
|  |  | ||||||
|  |         return this.notes[subTreeNoteId]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async loadParents(resp, additiveLoad) { |     async loadParents(resp, additiveLoad) { | ||||||
|         const noteIds = new Set(resp.notes.map(note => note.noteId)); |         const noteIds = new Set(resp.notes.map(note => note.noteId)); | ||||||
|         const missingNoteIds = []; |         const missingNoteIds = []; | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ const TPL = ` | |||||||
| export default class NotePathsWidget extends TabAwareWidget { | export default class NotePathsWidget extends TabAwareWidget { | ||||||
|     doRender() { |     doRender() { | ||||||
|         this.$widget = $(TPL); |         this.$widget = $(TPL); | ||||||
|         this.contentSized(); |         this.overflowing(); | ||||||
|  |  | ||||||
|         this.$currentPath = this.$widget.find('.current-path'); |         this.$currentPath = this.$widget.find('.current-path'); | ||||||
|         this.$dropdown = this.$widget.find(".dropdown"); |         this.$dropdown = this.$widget.find(".dropdown"); | ||||||
|   | |||||||
| @@ -297,8 +297,8 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|         await options.save("hideIncludedImages_" + this.treeName, val.toString()); |         await options.save("hideIncludedImages_" + this.treeName, val.toString()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async initFancyTree() { |     initFancyTree() { | ||||||
|         const treeData = [await this.prepareRootNode()]; |         const treeData = [this.prepareRootNode()]; | ||||||
|  |  | ||||||
|         this.$tree.fancytree({ |         this.$tree.fancytree({ | ||||||
|             titlesTabbable: true, |             titlesTabbable: true, | ||||||
| @@ -354,7 +354,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|             }, |             }, | ||||||
|             expand: (event, data) => this.setExpanded(data.node.data.branchId, true), |             expand: (event, data) => this.setExpanded(data.node.data.branchId, true), | ||||||
|             collapse: (event, data) => this.setExpanded(data.node.data.branchId, false), |             collapse: (event, data) => this.setExpanded(data.node.data.branchId, false), | ||||||
|             hotkeys: utils.isMobile() ? undefined : { keydown: await this.getHotKeys() }, |             //hotkeys: utils.isMobile() ? undefined : { keydown: await this.getHotKeys() }, | ||||||
|             dnd5: { |             dnd5: { | ||||||
|                 autoExpandMS: 600, |                 autoExpandMS: 600, | ||||||
|                 dragStart: (node, data) => { |                 dragStart: (node, data) => { | ||||||
| @@ -443,34 +443,41 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|                         data.result = []; |                         data.result = []; | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 data.result = treeCache.getNote(noteId).then(note => this.prepareChildren(note)); |                     data.result = treeCache.reloadNotes([noteId]).then(() => { | ||||||
|  |                        const note = treeCache.getNoteFromCache(noteId); | ||||||
|  |  | ||||||
|  |                        return this.prepareChildren(note); | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     data.result = treeCache.loadSubTree(noteId).then(note => this.prepareChildren(note)); | ||||||
|  |                 } | ||||||
|             }, |             }, | ||||||
|             clones: { |             clones: { | ||||||
|                 highlightActiveClones: true |                 highlightActiveClones: true | ||||||
|             }, |             }, | ||||||
|             enhanceTitle: async function (event, data) { |             // enhanceTitle: async function (event, data) { | ||||||
|                 const node = data.node; |             //     const node = data.node; | ||||||
|                 const $span = $(node.span); |             //     const $span = $(node.span); | ||||||
|  |             // | ||||||
|                 if (node.data.noteId !== 'root' |             //     if (node.data.noteId !== 'root' | ||||||
|                     && node.data.noteId === hoistedNoteService.getHoistedNoteId() |             //         && node.data.noteId === hoistedNoteService.getHoistedNoteId() | ||||||
|                     && $span.find('.unhoist-button').length === 0) { |             //         && $span.find('.unhoist-button').length === 0) { | ||||||
|  |             // | ||||||
|                     const unhoistButton = $('<span>  (<a class="unhoist-button">unhoist</a>)</span>'); |             //         const unhoistButton = $('<span>  (<a class="unhoist-button">unhoist</a>)</span>'); | ||||||
|  |             // | ||||||
|                     $span.append(unhoistButton); |             //         $span.append(unhoistButton); | ||||||
|                 } |             //     } | ||||||
|  |             // | ||||||
|                 const note = await treeCache.getNote(node.data.noteId); |             //     const note = await treeCache.getNote(node.data.noteId); | ||||||
|  |             // | ||||||
|                 if (note.type === 'search' && $span.find('.refresh-search-button').length === 0) { |             //     if (note.type === 'search' && $span.find('.refresh-search-button').length === 0) { | ||||||
|                     const refreshSearchButton = $('<span>  <span class="refresh-search-button bx bx-refresh" title="Refresh saved search results"></span></span>'); |             //         const refreshSearchButton = $('<span>  <span class="refresh-search-button bx bx-refresh" title="Refresh saved search results"></span></span>'); | ||||||
|  |             // | ||||||
|                     $span.append(refreshSearchButton); |             //         $span.append(refreshSearchButton); | ||||||
|                 } |             //     } | ||||||
|             }, |             // }, | ||||||
|             // this is done to automatically lazy load all expanded notes after tree load |             // this is done to automatically lazy load all expanded notes after tree load | ||||||
|             loadChildren: (event, data) => { |             loadChildren: (event, data) => { | ||||||
|                 data.node.visit((subNode) => { |                 data.node.visit((subNode) => { | ||||||
| @@ -497,9 +504,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|         this.tree = $.ui.fancytree.getTree(this.$tree); |         this.tree = $.ui.fancytree.getTree(this.$tree); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async prepareRootNode() { |     prepareRootNode() { | ||||||
|         await treeCache.initializedPromise; |  | ||||||
|  |  | ||||||
|         const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); |         const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); | ||||||
|  |  | ||||||
|         let hoistedBranch; |         let hoistedBranch; | ||||||
| @@ -508,31 +513,17 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|             hoistedBranch = treeCache.getBranch('root'); |             hoistedBranch = treeCache.getBranch('root'); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             const hoistedNote = await treeCache.getNote(hoistedNoteId); |             const hoistedNote = treeCache.getNoteFromCache(hoistedNoteId); | ||||||
|             hoistedBranch = (await hoistedNote.getBranches())[0]; |             hoistedBranch = hoistedNote.getBranches()[0]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return await this.prepareNode(hoistedBranch); |         return this.prepareNode(hoistedBranch); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async prepareChildren(note) { |     /** | ||||||
|         if (note.type === 'search') { |      * @param {NoteShort} parentNote | ||||||
|             return await this.prepareSearchNoteChildren(note); |      */ | ||||||
|         } |     prepareChildren(parentNote) { | ||||||
|         else { |  | ||||||
|             return await this.prepareNormalNoteChildren(note); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async prepareSearchNoteChildren(note) { |  | ||||||
|         await treeCache.reloadNotes([note.noteId]); |  | ||||||
|  |  | ||||||
|         const newNote = await treeCache.getNote(note.noteId); |  | ||||||
|  |  | ||||||
|         return await this.prepareNormalNoteChildren(newNote); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async prepareNormalNoteChildren(parentNote) { |  | ||||||
|         utils.assertArguments(parentNote); |         utils.assertArguments(parentNote); | ||||||
|  |  | ||||||
|         const noteList = []; |         const noteList = []; | ||||||
| @@ -541,14 +532,14 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|  |  | ||||||
|         for (const branch of this.getChildBranches(parentNote)) { |         for (const branch of this.getChildBranches(parentNote)) { | ||||||
|             if (hideArchivedNotes) { |             if (hideArchivedNotes) { | ||||||
|                 const note = await branch.getNote(); |                 const note = branch.getNoteFromCache(); | ||||||
|  |  | ||||||
|                 if (note.hasLabel('archived')) { |                 if (note.hasLabel('archived')) { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             const node = await this.prepareNode(branch); |             const node = this.prepareNode(branch); | ||||||
|  |  | ||||||
|             noteList.push(node); |             noteList.push(node); | ||||||
|         } |         } | ||||||
| @@ -613,10 +604,15 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|         node.renderTitle(); |         node.renderTitle(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async prepareNode(branch) { |     /** | ||||||
|         const note = await branch.getNote(); |      * @param {Branch} branch | ||||||
|  |      */ | ||||||
|  |     prepareNode(branch) { | ||||||
|  |         const note = branch.getNoteFromCache(); | ||||||
|  |  | ||||||
|         if (!note) { |         if (!note) { | ||||||
|  |             console.log("branch", branch); | ||||||
|  |  | ||||||
|             throw new Error(`Branch has no note "${branch.noteId}": ${JSON.stringify(note)}`); |             throw new Error(`Branch has no note "${branch.noteId}": ${JSON.stringify(note)}`); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -642,7 +638,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         if (node.folder && node.expanded) { |         if (node.folder && node.expanded) { | ||||||
|             node.children = await this.prepareChildren(note); |             node.children = this.prepareChildren(note); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return node; |         return node; | ||||||
| @@ -1141,9 +1137,6 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async setExpanded(branchId, isExpanded) { |     async setExpanded(branchId, isExpanded) { | ||||||
|         console.log("expand", isExpanded); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         utils.assertArguments(branchId); |         utils.assertArguments(branchId); | ||||||
|  |  | ||||||
|         const branch = treeCache.getBranch(branchId); |         const branch = treeCache.getBranch(branchId); | ||||||
| @@ -1157,7 +1150,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|  |  | ||||||
|         const activeNotePath = activeNode !== null ? treeService.getNotePath(activeNode) : null; |         const activeNotePath = activeNode !== null ? treeService.getNotePath(activeNode) : null; | ||||||
|  |  | ||||||
|         const rootNode = await this.prepareRootNode(); |         const rootNode = this.prepareRootNode(); | ||||||
|  |  | ||||||
|         await this.batchUpdate(async () => { |         await this.batchUpdate(async () => { | ||||||
|             await this.tree.reload([rootNode]); |             await this.tree.reload([rootNode]); | ||||||
|   | |||||||
| @@ -50,23 +50,30 @@ function getNotesAndBranchesAndAttributes(noteIds) { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| function getTree() { | function getTree(req) { | ||||||
|     const hoistedNoteId = optionService.getOption('hoistedNoteId'); |     const subTreeNoteId = req.query.subTreeNoteId || optionService.getOption('hoistedNoteId'); | ||||||
|  |  | ||||||
|     // we fetch all branches of notes, even if that particular branch isn't visible |  | ||||||
|     // this allows us to e.g. detect and properly display clones |  | ||||||
|     const noteIds = sql.getColumn(` |     const noteIds = sql.getColumn(` | ||||||
|         WITH RECURSIVE |         WITH RECURSIVE | ||||||
|             tree(branchId, noteId, isExpanded) AS ( |             treeWithDescendants(noteId, isExpanded) AS ( | ||||||
|             SELECT branchId, noteId, isExpanded FROM branches WHERE noteId = ?  |                 SELECT noteId, 1 FROM branches WHERE parentNoteId = ? AND isDeleted = 0 | ||||||
|             UNION ALL |                 UNION | ||||||
|             SELECT branches.branchId, branches.noteId, branches.isExpanded FROM branches |                 SELECT branches.noteId, branches.isExpanded FROM branches | ||||||
|               JOIN tree ON branches.parentNoteId = tree.noteId |                   JOIN treeWithDescendants ON branches.parentNoteId = treeWithDescendants.noteId | ||||||
|               WHERE tree.isExpanded = 1 AND branches.isDeleted = 0 |                 WHERE treeWithDescendants.isExpanded = 1  | ||||||
|           ) |                   AND branches.isDeleted = 0 | ||||||
|         SELECT noteId FROM tree`, [hoistedNoteId]); |             ), | ||||||
|  |             treeWithDescendantsAndAscendants AS ( | ||||||
|  |                 SELECT noteId FROM treeWithDescendants | ||||||
|  |                 UNION | ||||||
|  |                 SELECT branches.parentNoteId FROM branches | ||||||
|  |                   JOIN treeWithDescendantsAndAscendants ON branches.noteId = treeWithDescendantsAndAscendants.noteId | ||||||
|  |                 WHERE branches.isDeleted = 0 | ||||||
|  |                   AND branches.parentNoteId != ? | ||||||
|  |             ) | ||||||
|  |         SELECT noteId FROM treeWithDescendantsAndAscendants`, [subTreeNoteId, subTreeNoteId]); | ||||||
|  |  | ||||||
|     noteIds.push('root'); |     noteIds.push(subTreeNoteId); | ||||||
|  |  | ||||||
|     return getNotesAndBranchesAndAttributes(noteIds); |     return getNotesAndBranchesAndAttributes(noteIds); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user