diff --git a/package-lock.json b/package-lock.json index 5e3957808..d1b5a9a5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3345,9 +3345,9 @@ } }, "electron": { - "version": "9.0.0-beta.22", - "resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.22.tgz", - "integrity": "sha512-dfqAf+CXXTKcNDj7DU7mYsmx+oZQcXOvJnZ8ZsgAHjrE9Tv8zsYUgCP3JlO4Z8CIazgleKXYmgh6H2stdK7fEA==", + "version": "9.0.0-beta.21", + "resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.21.tgz", + "integrity": "sha512-xFOD8I4RB9IkpVKnzoHwHvDNGvGl1IinpYTyQ7o7FAgSnkvP/upI1JtzE5Ff6PlAdyIGnbC+Rz1hJIfmAXxVuQ==", "dev": true, "requires": { "@electron/get": "^1.0.1", diff --git a/package.json b/package.json index cb68c60c4..4d96ee213 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "yazl": "^2.5.1" }, "devDependencies": { - "electron": "9.0.0-beta.22", + "electron": "9.0.0-beta.21", "electron-builder": "22.6.0", "electron-packager": "14.2.1", "electron-rebuild": "1.10.1", diff --git a/src/public/app/entities/note_short.js b/src/public/app/entities/note_short.js index 68e14f3be..2b1dbf610 100644 --- a/src/public/app/entities/note_short.js +++ b/src/public/app/entities/note_short.js @@ -8,6 +8,8 @@ const RELATION = 'relation'; const RELATION_DEFINITION = 'relation-definition'; /** + * FIXME: since there's no "full note" anymore we can rename this to Note + * * This note's representation is used in note tree and is kept in TreeCache. */ class NoteShort { diff --git a/src/public/app/services/tree_cache.js b/src/public/app/services/tree_cache.js index 7f4095f40..3f92901e6 100644 --- a/src/public/app/services/tree_cache.js +++ b/src/public/app/services/tree_cache.js @@ -246,10 +246,10 @@ class TreeCache { return this.notes[noteId]; } - getBranches(branchIds) { + getBranches(branchIds, silentNotFoundError = false) { return branchIds - .map(branchId => this.getBranch(branchId)) - .filter(b => b !== null); + .map(branchId => this.getBranch(branchId, silentNotFoundError)) + .filter(b => !!b); } /** @return {Branch} */ diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index 2aa86a861..0959dafdd 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -362,17 +362,13 @@ export default class NoteTreeWidget extends TabAwareWidget { }, // this is done to automatically lazy load all expanded notes after tree load loadChildren: (event, data) => { - // semaphore since the conflict when two processes are trying to load the same data - // breaks the fancytree - if (!this.tree || !this.tree.autoLoadingDisabled) { - data.node.visit((subNode) => { - // Load all lazy/unloaded child nodes - // (which will trigger `loadChildren` recursively) - if (subNode.isUndefined() && subNode.isExpanded()) { - subNode.load(); - } - }); - } + data.node.visit((subNode) => { + // Load all lazy/unloaded child nodes + // (which will trigger `loadChildren` recursively) + if (subNode.isUndefined() && subNode.isExpanded()) { + subNode.load(); + } + }); } }); @@ -596,47 +592,30 @@ export default class NoteTreeWidget extends TabAwareWidget { return notes; } - async expandTree(node = null) { + async setExpandedStatusForSubtree(node, isExpanded) { if (!node) { const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); node = this.getNodesByNoteId(hoistedNoteId)[0]; } - this.batchUpdate(async () => { - try { - this.tree.autoLoadingDisabled = true; + const {branchIds} = await server.put(`branches/${node.data.branchId}/expanded-subtree/${isExpanded ? 1 : 0}`); - // trick - first force load of the whole subtree and then visit and expand. - // unfortunately the two steps can't be combined - await node.visitAndLoad(_ => {}, true); + treeCache.getBranches(branchIds, true).forEach(branch => branch.isExpanded = isExpanded); - node.visit(node => { - if (node.isFolder()) { - node.setExpanded(true); - } - }, true); - } - finally { - this.tree.autoLoadingDisabled = false; - } + await this.batchUpdate(async () => { + await node.load(true); + + await node.setExpanded(isExpanded, {noEvents: true}); }); } - collapseTree(node = null) { - if (!node) { - const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); + async expandTree(node = null) { + await this.setExpandedStatusForSubtree(node, true); + } - node = this.getNodesByNoteId(hoistedNoteId)[0]; - } - - this.batchUpdate(() => { - node.visit(node => { - if (node.isFolder()) { - node.setExpanded(false); - } - }, true); - }); + async collapseTree(node = null) { + await this.setExpandedStatusForSubtree(node, false); } /** diff --git a/src/routes/api/branches.js b/src/routes/api/branches.js index 6917f5981..7bceaa4cc 100644 --- a/src/routes/api/branches.js +++ b/src/routes/api/branches.js @@ -118,6 +118,27 @@ async function setExpanded(req) { // we don't sync expanded label } +async function setExpandedForSubtree(req) { + const {branchId, expanded} = req.params; + + const branchIds = await sql.getColumn(` + WITH RECURSIVE + tree(branchId, noteId) AS ( + SELECT branchId, noteId FROM branches WHERE branchId = ? + UNION + SELECT branches.branchId, branches.noteId FROM branches + JOIN tree ON branches.parentNoteId = tree.noteId + WHERE branches.isDeleted = 0 + ) + SELECT branchId FROM tree`, [branchId]); + + await sql.executeMany(`UPDATE branches SET isExpanded = ${expanded} WHERE branchId IN (???)`, branchIds); + + return { + branchIds + }; +} + async function deleteBranch(req) { const last = req.query.last === 'true'; const branch = await repository.getBranch(req.params.branchId); @@ -149,6 +170,7 @@ module.exports = { moveBranchBeforeNote, moveBranchAfterNote, setExpanded, + setExpandedForSubtree, deleteBranch, setPrefix }; \ No newline at end of file diff --git a/src/routes/routes.js b/src/routes/routes.js index 13783ec35..439ae1201 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -127,6 +127,7 @@ function register(app) { apiRoute(PUT, '/api/branches/:branchId/move-before/:beforeBranchId', branchesApiRoute.moveBranchBeforeNote); apiRoute(PUT, '/api/branches/:branchId/move-after/:afterBranchId', branchesApiRoute.moveBranchAfterNote); apiRoute(PUT, '/api/branches/:branchId/expanded/:expanded', branchesApiRoute.setExpanded); + apiRoute(PUT, '/api/branches/:branchId/expanded-subtree/:expanded', branchesApiRoute.setExpandedForSubtree); apiRoute(DELETE, '/api/branches/:branchId', branchesApiRoute.deleteBranch); apiRoute(GET, '/api/autocomplete', autocompleteApiRoute.getAutocomplete);