mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
initializing note tree synchronously
This commit is contained in:
parent
87161cfe0d
commit
6aa61ca306
@ -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
|
||||||
|
),
|
||||||
|
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 tree`, [hoistedNoteId]);
|
SELECT noteId FROM treeWithDescendantsAndAscendants`, [subTreeNoteId, subTreeNoteId]);
|
||||||
|
|
||||||
noteIds.push('root');
|
noteIds.push(subTreeNoteId);
|
||||||
|
|
||||||
return getNotesAndBranchesAndAttributes(noteIds);
|
return getNotesAndBranchesAndAttributes(noteIds);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user