reimplemented expand/collapse differently for better performance

This commit is contained in:
zadam 2020-05-03 13:15:08 +02:00
parent 742df25bc2
commit 2a3091f788
7 changed files with 51 additions and 47 deletions

6
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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 {

View file

@ -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} */

View file

@ -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);
}
/**

View file

@ -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
};

View file

@ -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);