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": { "electron": {
"version": "9.0.0-beta.22", "version": "9.0.0-beta.21",
"resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.22.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.21.tgz",
"integrity": "sha512-dfqAf+CXXTKcNDj7DU7mYsmx+oZQcXOvJnZ8ZsgAHjrE9Tv8zsYUgCP3JlO4Z8CIazgleKXYmgh6H2stdK7fEA==", "integrity": "sha512-xFOD8I4RB9IkpVKnzoHwHvDNGvGl1IinpYTyQ7o7FAgSnkvP/upI1JtzE5Ff6PlAdyIGnbC+Rz1hJIfmAXxVuQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@electron/get": "^1.0.1", "@electron/get": "^1.0.1",

View File

@ -78,7 +78,7 @@
"yazl": "^2.5.1" "yazl": "^2.5.1"
}, },
"devDependencies": { "devDependencies": {
"electron": "9.0.0-beta.22", "electron": "9.0.0-beta.21",
"electron-builder": "22.6.0", "electron-builder": "22.6.0",
"electron-packager": "14.2.1", "electron-packager": "14.2.1",
"electron-rebuild": "1.10.1", "electron-rebuild": "1.10.1",

View File

@ -8,6 +8,8 @@ const RELATION = 'relation';
const RELATION_DEFINITION = 'relation-definition'; 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. * This note's representation is used in note tree and is kept in TreeCache.
*/ */
class NoteShort { class NoteShort {

View File

@ -246,10 +246,10 @@ class TreeCache {
return this.notes[noteId]; return this.notes[noteId];
} }
getBranches(branchIds) { getBranches(branchIds, silentNotFoundError = false) {
return branchIds return branchIds
.map(branchId => this.getBranch(branchId)) .map(branchId => this.getBranch(branchId, silentNotFoundError))
.filter(b => b !== null); .filter(b => !!b);
} }
/** @return {Branch} */ /** @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 // this is done to automatically lazy load all expanded notes after tree load
loadChildren: (event, data) => { loadChildren: (event, data) => {
// semaphore since the conflict when two processes are trying to load the same data data.node.visit((subNode) => {
// breaks the fancytree // Load all lazy/unloaded child nodes
if (!this.tree || !this.tree.autoLoadingDisabled) { // (which will trigger `loadChildren` recursively)
data.node.visit((subNode) => { if (subNode.isUndefined() && subNode.isExpanded()) {
// Load all lazy/unloaded child nodes subNode.load();
// (which will trigger `loadChildren` recursively) }
if (subNode.isUndefined() && subNode.isExpanded()) { });
subNode.load();
}
});
}
} }
}); });
@ -596,47 +592,30 @@ export default class NoteTreeWidget extends TabAwareWidget {
return notes; return notes;
} }
async expandTree(node = null) { async setExpandedStatusForSubtree(node, isExpanded) {
if (!node) { if (!node) {
const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); const hoistedNoteId = hoistedNoteService.getHoistedNoteId();
node = this.getNodesByNoteId(hoistedNoteId)[0]; node = this.getNodesByNoteId(hoistedNoteId)[0];
} }
this.batchUpdate(async () => { const {branchIds} = await server.put(`branches/${node.data.branchId}/expanded-subtree/${isExpanded ? 1 : 0}`);
try {
this.tree.autoLoadingDisabled = true;
// trick - first force load of the whole subtree and then visit and expand. treeCache.getBranches(branchIds, true).forEach(branch => branch.isExpanded = isExpanded);
// unfortunately the two steps can't be combined
await node.visitAndLoad(_ => {}, true);
node.visit(node => { await this.batchUpdate(async () => {
if (node.isFolder()) { await node.load(true);
node.setExpanded(true);
} await node.setExpanded(isExpanded, {noEvents: true});
}, true);
}
finally {
this.tree.autoLoadingDisabled = false;
}
}); });
} }
collapseTree(node = null) { async expandTree(node = null) {
if (!node) { await this.setExpandedStatusForSubtree(node, true);
const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); }
node = this.getNodesByNoteId(hoistedNoteId)[0]; async collapseTree(node = null) {
} await this.setExpandedStatusForSubtree(node, false);
this.batchUpdate(() => {
node.visit(node => {
if (node.isFolder()) {
node.setExpanded(false);
}
}, true);
});
} }
/** /**

View File

@ -118,6 +118,27 @@ async function setExpanded(req) {
// we don't sync expanded label // 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) { async function deleteBranch(req) {
const last = req.query.last === 'true'; const last = req.query.last === 'true';
const branch = await repository.getBranch(req.params.branchId); const branch = await repository.getBranch(req.params.branchId);
@ -149,6 +170,7 @@ module.exports = {
moveBranchBeforeNote, moveBranchBeforeNote,
moveBranchAfterNote, moveBranchAfterNote,
setExpanded, setExpanded,
setExpandedForSubtree,
deleteBranch, deleteBranch,
setPrefix 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-before/:beforeBranchId', branchesApiRoute.moveBranchBeforeNote);
apiRoute(PUT, '/api/branches/:branchId/move-after/:afterBranchId', branchesApiRoute.moveBranchAfterNote); 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/:expanded', branchesApiRoute.setExpanded);
apiRoute(PUT, '/api/branches/:branchId/expanded-subtree/:expanded', branchesApiRoute.setExpandedForSubtree);
apiRoute(DELETE, '/api/branches/:branchId', branchesApiRoute.deleteBranch); apiRoute(DELETE, '/api/branches/:branchId', branchesApiRoute.deleteBranch);
apiRoute(GET, '/api/autocomplete', autocompleteApiRoute.getAutocomplete); apiRoute(GET, '/api/autocomplete', autocompleteApiRoute.getAutocomplete);