diff --git a/src/public/javascripts/services/context_menu.js b/src/public/javascripts/services/context_menu.js index a0baa028e..895b968c4 100644 --- a/src/public/javascripts/services/context_menu.js +++ b/src/public/javascripts/services/context_menu.js @@ -4,10 +4,11 @@ const $contextMenuContainer = $("#context-menu-container"); let dateContextMenuOpenedMs = 0; /** + * @param {NoteTreeWidget} treeWidget * @param event - originating click event (used to get coordinates to display menu at position) * @param {object} contextMenu - needs to have getContextMenuItems() and selectContextMenuItem(e, cmd) */ -async function initContextMenu(event, contextMenu) { +async function initContextMenu(treeWidget, event, contextMenu) { event.stopPropagation(); $contextMenuContainer.empty(); diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index 4c31c33ad..1a2fd5ddc 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -18,6 +18,10 @@ import keyboardActionService from "./keyboard_actions.js"; let tree; +function setTree(treeInstance) { + tree = treeInstance; +} + let setFrontendAsLoaded; const frontendLoaded = new Promise(resolve => { setFrontendAsLoaded = resolve; }); @@ -424,104 +428,6 @@ async function treeInitialized() { setFrontendAsLoaded(); } -async function initFancyTree($tree, treeData) { - utils.assertArguments(treeData); - - $tree.fancytree({ - autoScroll: true, - keyboard: false, // we takover keyboard handling in the hotkeys plugin - extensions: ["hotkeys", "dnd5", "clones"], - source: treeData, - scrollParent: $tree, - minExpandLevel: 2, // root can't be collapsed - click: (event, data) => { - const targetType = data.targetType; - const node = data.node; - - if (targetType === 'title' || targetType === 'icon') { - if (event.shiftKey) { - node.setSelected(!node.isSelected()); - node.setFocus(true); - } - else if (event.ctrlKey) { - noteDetailService.loadNoteDetail(node.data.noteId, { newTab: true }); - } - else { - node.setActive(); - - clearSelectedNodes(); - } - - return false; - } - }, - activate: async (event, data) => { - // click event won't propagate so let's close context menu manually - contextMenuWidget.hideContextMenu(); - - const notePath = await treeUtils.getNotePath(data.node); - - noteDetailService.switchToNote(notePath); - }, - expand: (event, data) => setExpandedToServer(data.node.data.branchId, true), - collapse: (event, data) => setExpandedToServer(data.node.data.branchId, false), - init: (event, data) => treeInitialized(), // don't collapse to short form - hotkeys: { - keydown: await treeKeyBindingService.getKeyboardBindings() - }, - dnd5: dragAndDropSetup, - lazyLoad: function(event, data) { - const noteId = data.node.data.noteId; - - data.result = treeCache.getNote(noteId).then(note => treeBuilder.prepareBranch(note)); - }, - clones: { - highlightActiveClones: true - }, - enhanceTitle: async function (event, data) { - const node = data.node; - const $span = $(node.span); - - if (node.data.noteId !== 'root' - && node.data.noteId === await hoistedNoteService.getHoistedNoteId() - && $span.find('.unhoist-button').length === 0) { - - const unhoistButton = $('  (unhoist)'); - - $span.append(unhoistButton); - } - - const note = await treeCache.getNote(node.data.noteId); - - if (note.type === 'search' && $span.find('.refresh-search-button').length === 0) { - const refreshSearchButton = $('  '); - - $span.append(refreshSearchButton); - } - }, - // this is done to automatically lazy load all expanded search notes after tree load - loadChildren: (event, data) => { - data.node.visit((subNode) => { - // Load all lazy/unloaded child nodes - // (which will trigger `loadChildren` recursively) - if (subNode.isUndefined() && subNode.isExpanded()) { - subNode.load(); - } - }); - } - }); - - $tree.on('contextmenu', '.fancytree-node', function(e) { - const node = $.ui.fancytree.getNode(e); - - contextMenuWidget.initContextMenu(e, new TreeContextMenu(node)); - - return false; // blocks default browser right click menu - }); - - tree = $.ui.fancytree.getTree("#tree"); -} - async function reload() { const notes = await loadTreeData(); @@ -745,12 +651,6 @@ async function sortAlphabetically(noteId) { await reload(); } -async function showTree($tree) { - const treeData = await loadTreeData(); - - await initFancyTree($tree, treeData); -} - ws.subscribeToMessages(message => { if (message.type === 'refresh-tree') { reload(); @@ -908,7 +808,6 @@ export default { getSelectedOrActiveNodes, clearSelectedNodes, sortAlphabetically, - showTree, loadTreeData, treeInitialized, setExpandedToServer, @@ -923,5 +822,6 @@ export default { scrollToActiveNote, createNewTopLevelNote, duplicateNote, - getNodeByKey + getNodeByKey, + setTree }; \ No newline at end of file diff --git a/src/public/javascripts/services/tree_context_menu.js b/src/public/javascripts/services/tree_context_menu.js index dc9facebd..3739621dd 100644 --- a/src/public/javascripts/services/tree_context_menu.js +++ b/src/public/javascripts/services/tree_context_menu.js @@ -12,7 +12,12 @@ import protectedSessionHolder from "./protected_session_holder.js"; import searchNotesService from "./search_notes.js"; class TreeContextMenu { - constructor(node) { + /** + * @param {NoteTreeWidget} treeWidget + * @param {FancytreeNode} node + */ + constructor(treeWidget, node) { + this.treeWidget = treeWidget; this.node = node; } @@ -37,7 +42,7 @@ class TreeContextMenu { // some actions don't support multi-note so they are disabled when notes are selected // the only exception is when the only selected note is the one that was right-clicked, then // it's clear what the user meant to do. - const selNodes = treeService.getSelectedNodes(); + const selNodes = this.treeWidget.getSelectedNodes(); const noSelectedNotes = selNodes.length === 0 || (selNodes.length === 1 && selNodes[0] === this.node); @@ -128,19 +133,19 @@ class TreeContextMenu { protectedSessionService.protectSubtree(this.node.data.noteId, false); } else if (cmd === "copy") { - clipboard.copy(treeService.getSelectedOrActiveNodes(this.node)); + clipboard.copy(this.treeWidget.getSelectedOrActiveNodes(this.node)); } else if (cmd === "cloneTo") { - const nodes = treeService.getSelectedOrActiveNodes(this.node); + const nodes = this.treeWidget.getSelectedOrActiveNodes(this.node); const noteIds = nodes.map(node => node.data.noteId); import("../dialogs/clone_to.js").then(d => d.showDialog(noteIds)); } else if (cmd === "cut") { - clipboard.cut(treeService.getSelectedOrActiveNodes(this.node)); + clipboard.cut(this.treeWidget.getSelectedOrActiveNodes(this.node)); } else if (cmd === "moveTo") { - const nodes = treeService.getSelectedOrActiveNodes(this.node); + const nodes = this.treeWidget.getSelectedOrActiveNodes(this.node); import("../dialogs/move_to.js").then(d => d.showDialog(nodes)); } @@ -151,7 +156,7 @@ class TreeContextMenu { clipboard.pasteInto(this.node); } else if (cmd === "delete") { - treeChangesService.deleteNodes(treeService.getSelectedOrActiveNodes(this.node)); + treeChangesService.deleteNodes(this.treeWidget.getSelectedOrActiveNodes(this.node)); } else if (cmd === "export") { const exportDialog = await import('../dialogs/export.js'); @@ -162,7 +167,7 @@ class TreeContextMenu { importDialog.showDialog(this.node); } else if (cmd === "collapseSubtree") { - treeService.collapseTree(this.node); + this.treeWidget.collapseTree(this.node); } else if (cmd === "forceNoteSync") { syncService.forceNoteSync(this.node.data.noteId); diff --git a/src/public/javascripts/widgets/note_tree.js b/src/public/javascripts/widgets/note_tree.js index c2f4da4e7..4e53e16cf 100644 --- a/src/public/javascripts/widgets/note_tree.js +++ b/src/public/javascripts/widgets/note_tree.js @@ -5,6 +5,13 @@ import keyboardActionService from "../services/keyboard_actions.js"; import treeService from "../services/tree.js"; import treeUtils from "../services/tree_utils.js"; import noteDetailService from "../services/note_detail.js"; +import utils from "../services/utils.js"; +import contextMenuWidget from "../services/context_menu.js"; +import treeKeyBindingService from "../services/tree_keybindings.js"; +import dragAndDropSetup from "../services/drag_and_drop.js"; +import treeCache from "../services/tree_cache.js"; +import treeBuilder from "../services/tree_builder.js"; +import TreeContextMenu from "../services/tree_context_menu.js"; const TPL = `