mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	context menu refactoring
This commit is contained in:
		
							
								
								
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "trilium", | ||||
|   "version": "0.31.3", | ||||
|   "version": "0.31.4", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|   | ||||
							
								
								
									
										85
									
								
								src/public/javascripts/services/clipboard.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/public/javascripts/services/clipboard.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| import treeUtils from "./tree_utils.js"; | ||||
| import treeChangesService from "./branches.js"; | ||||
| import cloningService from "./cloning.js"; | ||||
| import infoService from "./info.js"; | ||||
|  | ||||
| let clipboardIds = []; | ||||
| let clipboardMode = null; | ||||
|  | ||||
| async function pasteAfter(node) { | ||||
|     if (clipboardMode === 'cut') { | ||||
|         const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey)); | ||||
|  | ||||
|         await treeChangesService.moveAfterNode(nodes, node); | ||||
|  | ||||
|         clipboardIds = []; | ||||
|         clipboardMode = null; | ||||
|     } | ||||
|     else if (clipboardMode === 'copy') { | ||||
|         for (const noteId of clipboardIds) { | ||||
|             await cloningService.cloneNoteAfter(noteId, node.data.branchId); | ||||
|         } | ||||
|  | ||||
|         // copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places | ||||
|     } | ||||
|     else if (clipboardIds.length === 0) { | ||||
|         // just do nothing | ||||
|     } | ||||
|     else { | ||||
|         infoService.throwError("Unrecognized clipboard mode=" + clipboardMode); | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function pasteInto(node) { | ||||
|     if (clipboardMode === 'cut') { | ||||
|         const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey)); | ||||
|  | ||||
|         await treeChangesService.moveToNode(nodes, node); | ||||
|  | ||||
|         await node.setExpanded(true); | ||||
|  | ||||
|         clipboardIds = []; | ||||
|         clipboardMode = null; | ||||
|     } | ||||
|     else if (clipboardMode === 'copy') { | ||||
|         for (const noteId of clipboardIds) { | ||||
|             await cloningService.cloneNoteTo(noteId, node.data.noteId); | ||||
|         } | ||||
|  | ||||
|         await node.setExpanded(true); | ||||
|  | ||||
|         // copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places | ||||
|     } | ||||
|     else if (clipboardIds.length === 0) { | ||||
|         // just do nothing | ||||
|     } | ||||
|     else { | ||||
|         infoService.throwError("Unrecognized clipboard mode=" + mode); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function copy(nodes) { | ||||
|     clipboardIds = nodes.map(node => node.data.noteId); | ||||
|     clipboardMode = 'copy'; | ||||
|  | ||||
|     infoService.showMessage("Note(s) have been copied into clipboard."); | ||||
| } | ||||
|  | ||||
| function cut(nodes) { | ||||
|     clipboardIds = nodes.map(node => node.key); | ||||
|     clipboardMode = 'cut'; | ||||
|  | ||||
|     infoService.showMessage("Note(s) have been cut into clipboard."); | ||||
| } | ||||
|  | ||||
| function isEmpty() { | ||||
|     return clipboardIds.length === 0; | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     pasteAfter, | ||||
|     pasteInto, | ||||
|     cut, | ||||
|     copy, | ||||
|     isEmpty | ||||
| } | ||||
| @@ -2,7 +2,7 @@ const $contextMenuContainer = $("#context-menu-container"); | ||||
|  | ||||
| let dateContextMenuOpenedMs = 0; | ||||
|  | ||||
| function initContextMenu(event, contextMenuItems, selectContextMenuItem) { | ||||
| async function initContextMenu(event, contextMenu) { | ||||
|     event.stopPropagation(); | ||||
|  | ||||
|     $contextMenuContainer.empty(); | ||||
| @@ -34,7 +34,7 @@ function initContextMenu(event, contextMenuItems, selectContextMenuItem) { | ||||
|  | ||||
|                         e.originalTarget = event.target; | ||||
|  | ||||
|                         selectContextMenuItem(e, cmd); | ||||
|                         contextMenu.selectContextMenuItem(e, cmd); | ||||
|  | ||||
|                         // it's important to stop the propagation especially for sub-menus, otherwise the event | ||||
|                         // might be handled again by top-level menu | ||||
| @@ -61,7 +61,7 @@ function initContextMenu(event, contextMenuItems, selectContextMenuItem) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     addItems($contextMenuContainer, contextMenuItems); | ||||
|     addItems($contextMenuContainer, await contextMenu.getContextMenuItems()); | ||||
|  | ||||
|     // code below tries to detect when dropdown would overflow from page | ||||
|     // in such case we'll position it above click coordinates so it will fit into client | ||||
|   | ||||
| @@ -16,6 +16,7 @@ import Branch from '../entities/branch.js'; | ||||
| import NoteShort from '../entities/note_short.js'; | ||||
| import hoistedNoteService from '../services/hoisted_note.js'; | ||||
| import confirmDialog from "../dialogs/confirm.js"; | ||||
| import TreeContextMenu from "./tree_context_menu.js"; | ||||
|  | ||||
| const $tree = $("#tree"); | ||||
| const $createTopLevelNoteButton = $("#create-top-level-note-button"); | ||||
| @@ -485,9 +486,15 @@ function initFancyTree(tree) { | ||||
|     }); | ||||
|  | ||||
|     $tree.on('contextmenu', '.fancytree-node', function(e) { | ||||
|         treeContextMenuService.getContextMenuItems(e).then(([node, contextMenuItems]) => { | ||||
|             contextMenuWidget.initContextMenu(e, contextMenuItems, treeContextMenuService.selectContextMenuItem); | ||||
|         }); | ||||
|         const node = $.ui.fancytree.getNode(e); | ||||
|  | ||||
|         // right click resets selection to just this node | ||||
|         // this is important when e.g. you right click on a note while having different note active | ||||
|         // and then click on delete - obviously you want to delete only that one right-clicked | ||||
|         node.setSelected(true); | ||||
|         clearSelectedNodes(); | ||||
|  | ||||
|         contextMenuWidget.initContextMenu(e, new TreeContextMenu(node)); | ||||
|  | ||||
|         return false; // blocks default browser right click menu | ||||
|     }); | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import treeService from './tree.js'; | ||||
| import cloningService from './cloning.js'; | ||||
| import messagingService from './messaging.js'; | ||||
| import protectedSessionService from './protected_session.js'; | ||||
| import treeChangesService from './branches.js'; | ||||
| @@ -7,235 +6,147 @@ import treeUtils from './tree_utils.js'; | ||||
| import branchPrefixDialog from '../dialogs/branch_prefix.js'; | ||||
| import exportDialog from '../dialogs/export.js'; | ||||
| import importDialog from '../dialogs/import.js'; | ||||
| import infoService from "./info.js"; | ||||
| import treeCache from "./tree_cache.js"; | ||||
| import syncService from "./sync.js"; | ||||
| import hoistedNoteService from './hoisted_note.js'; | ||||
| import noteDetailService from './note_detail.js'; | ||||
| import clipboard from './clipboard.js'; | ||||
|  | ||||
| let clipboardIds = []; | ||||
| let clipboardMode = null; | ||||
|  | ||||
| async function pasteAfter(node) { | ||||
|     if (clipboardMode === 'cut') { | ||||
|         const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey)); | ||||
|  | ||||
|         await treeChangesService.moveAfterNode(nodes, node); | ||||
|  | ||||
|         clipboardIds = []; | ||||
|         clipboardMode = null; | ||||
| class TreeContextMenu { | ||||
|     constructor(node) { | ||||
|         this.node = node; | ||||
|     } | ||||
|     else if (clipboardMode === 'copy') { | ||||
|         for (const noteId of clipboardIds) { | ||||
|             await cloningService.cloneNoteAfter(noteId, node.data.branchId); | ||||
|  | ||||
|     getNoteTypeItems(baseCmd) { | ||||
|         return [ | ||||
|             { title: "Text", cmd: baseCmd + "_text", uiIcon: "file" }, | ||||
|             { title: "Code", cmd: baseCmd + "_code", uiIcon: "terminal" }, | ||||
|             { title: "Saved search", cmd: baseCmd + "_search", uiIcon: "search-folder" }, | ||||
|             { title: "Relation Map", cmd: baseCmd + "_relation-map", uiIcon: "map" }, | ||||
|             { title: "Render HTML note", cmd: baseCmd + "_render", uiIcon: "play" } | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     async getContextMenuItems() { | ||||
|         const branch = await treeCache.getBranch(this.node.data.branchId); | ||||
|         const note = await treeCache.getNote(this.node.data.noteId); | ||||
|         const parentNote = await treeCache.getNote(branch.parentNoteId); | ||||
|         const isNotRoot = note.noteId !== 'root'; | ||||
|         const isHoisted = note.noteId === await hoistedNoteService.getHoistedNoteId(); | ||||
|  | ||||
|         const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNote.type !== 'search'; | ||||
|         const insertChildNoteEnabled = note.type !== 'search'; | ||||
|  | ||||
|         return [ | ||||
|             { title: "Open in new tab", cmd: "openInTab", uiIcon: "empty" }, | ||||
|             { title: "Insert note after <kbd>Ctrl+O</kbd>", cmd: "insertNoteAfter", uiIcon: "plus", | ||||
|                 items: insertNoteAfterEnabled ? this.getNoteTypeItems("insertNoteAfter") : null, | ||||
|                 enabled: insertNoteAfterEnabled }, | ||||
|             { title: "Insert child note <kbd>Ctrl+P</kbd>", cmd: "insertChildNote", uiIcon: "plus", | ||||
|                 items: insertChildNoteEnabled ? this.getNoteTypeItems("insertChildNote") : null, | ||||
|                 enabled: insertChildNoteEnabled }, | ||||
|             { title: "Delete <kbd>Delete</kbd>", cmd: "delete", uiIcon: "trash", | ||||
|                 enabled: isNotRoot && !isHoisted && parentNote.type !== 'search' }, | ||||
|             { title: "----" }, | ||||
|             isHoisted ? null : { title: "Hoist note <kbd>Ctrl-H</kbd>", cmd: "hoist", uiIcon: "empty" }, | ||||
|             !isHoisted || !isNotRoot ? null : { title: "Unhoist note <kbd>Ctrl-H</kbd>", cmd: "unhoist", uiIcon: "arrow-up" }, | ||||
|             { title: "Edit branch prefix <kbd>F2</kbd>", cmd: "editBranchPrefix", uiIcon: "empty", | ||||
|                 enabled: isNotRoot && parentNote.type !== 'search'}, | ||||
|             { title: "----" }, | ||||
|             { title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check" }, | ||||
|             { title: "Unprotect subtree", cmd: "unprotectSubtree", uiIcon: "shield-close" }, | ||||
|             { title: "----" }, | ||||
|             { title: "Copy / clone <kbd>Ctrl+C</kbd>", cmd: "copy", uiIcon: "files", | ||||
|                 enabled: isNotRoot }, | ||||
|             { title: "Cut <kbd>Ctrl+X</kbd>", cmd: "cut", uiIcon: "scissors", | ||||
|                 enabled: isNotRoot }, | ||||
|             { title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "clipboard", | ||||
|                 enabled: !clipboard.isEmpty() && note.type !== 'search' }, | ||||
|             { title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard", | ||||
|                 enabled: !clipboard.isEmpty() && isNotRoot && parentNote.type !== 'search' }, | ||||
|             { title: "----" }, | ||||
|             { title: "Export", cmd: "export", uiIcon: "empty", | ||||
|                 enabled: note.type !== 'search' }, | ||||
|             { title: "Import into note", cmd: "importIntoNote", uiIcon: "empty", | ||||
|                 enabled: note.type !== 'search' }, | ||||
|             { title: "----" }, | ||||
|             { title: "Collapse subtree <kbd>Alt+-</kbd>", cmd: "collapseSubtree", uiIcon: "align-justify" }, | ||||
|             { title: "Force note sync", cmd: "forceNoteSync", uiIcon: "refresh" }, | ||||
|             { title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "empty" } | ||||
|         ].filter(row => row !== null); | ||||
|     } | ||||
|  | ||||
|     async selectContextMenuItem(event, cmd) { | ||||
|         if (cmd === 'openInTab') { | ||||
|             noteDetailService.openInTab(this.node.data.noteId); | ||||
|         } | ||||
|         else if (cmd.startsWith("insertNoteAfter")) { | ||||
|             const parentNoteId = this.node.data.parentNoteId; | ||||
|             const isProtected = await treeUtils.getParentProtectedStatus(this.node); | ||||
|             const type = cmd.split("_")[1]; | ||||
|  | ||||
|         // copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places | ||||
|     } | ||||
|     else if (clipboardIds.length === 0) { | ||||
|         // just do nothing | ||||
|     } | ||||
|     else { | ||||
|         infoService.throwError("Unrecognized clipboard mode=" + clipboardMode); | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function pasteInto(node) { | ||||
|     if (clipboardMode === 'cut') { | ||||
|         const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey)); | ||||
|  | ||||
|         await treeChangesService.moveToNode(nodes, node); | ||||
|  | ||||
|         await node.setExpanded(true); | ||||
|  | ||||
|         clipboardIds = []; | ||||
|         clipboardMode = null; | ||||
|     } | ||||
|     else if (clipboardMode === 'copy') { | ||||
|         for (const noteId of clipboardIds) { | ||||
|             await cloningService.cloneNoteTo(noteId, node.data.noteId); | ||||
|             treeService.createNote(this.node, parentNoteId, 'after', { | ||||
|                 type: type, | ||||
|                 isProtected: isProtected | ||||
|             }); | ||||
|         } | ||||
|         else if (cmd.startsWith("insertChildNote")) { | ||||
|             const type = cmd.split("_")[1]; | ||||
|  | ||||
|         await node.setExpanded(true); | ||||
|  | ||||
|         // copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places | ||||
|     } | ||||
|     else if (clipboardIds.length === 0) { | ||||
|         // just do nothing | ||||
|     } | ||||
|     else { | ||||
|         infoService.throwError("Unrecognized clipboard mode=" + mode); | ||||
|             treeService.createNote(this.node, this.node.data.noteId, 'into', { | ||||
|                 type: type, | ||||
|                 isProtected: this.node.data.isProtected | ||||
|             }); | ||||
|         } | ||||
|         else if (cmd === "editBranchPrefix") { | ||||
|             branchPrefixDialog.showDialog(this.node); | ||||
|         } | ||||
|         else if (cmd === "protectSubtree") { | ||||
|             protectedSessionService.protectSubtree(this.node.data.noteId, true); | ||||
|         } | ||||
|         else if (cmd === "unprotectSubtree") { | ||||
|             protectedSessionService.protectSubtree(this.node.data.noteId, false); | ||||
|         } | ||||
|         else if (cmd === "copy") { | ||||
|             clipboard.copy(treeService.getSelectedNodes()); | ||||
|         } | ||||
|         else if (cmd === "cut") { | ||||
|             clipboard.cut(treeService.getSelectedNodes()); | ||||
|         } | ||||
|         else if (cmd === "pasteAfter") { | ||||
|             clipboard.pasteAfter(this.node); | ||||
|         } | ||||
|         else if (cmd === "pasteInto") { | ||||
|             clipboard.pasteInto(this.node); | ||||
|         } | ||||
|         else if (cmd === "delete") { | ||||
|             treeChangesService.deleteNodes(treeService.getSelectedNodes(true)); | ||||
|         } | ||||
|         else if (cmd === "export") { | ||||
|             exportDialog.showDialog("subtree"); | ||||
|         } | ||||
|         else if (cmd === "importIntoNote") { | ||||
|             importDialog.showDialog(); | ||||
|         } | ||||
|         else if (cmd === "collapseSubtree") { | ||||
|             treeService.collapseTree(this.node); | ||||
|         } | ||||
|         else if (cmd === "forceNoteSync") { | ||||
|             syncService.forceNoteSync(this.node.data.noteId); | ||||
|         } | ||||
|         else if (cmd === "sortAlphabetically") { | ||||
|             treeService.sortAlphabetically(this.node.data.noteId); | ||||
|         } | ||||
|         else if (cmd === "hoist") { | ||||
|             hoistedNoteService.setHoistedNoteId(this.node.data.noteId); | ||||
|         } | ||||
|         else if (cmd === "unhoist") { | ||||
|             hoistedNoteService.unhoist(); | ||||
|         } | ||||
|         else { | ||||
|             messagingService.logError("Unknown command: " + cmd); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| function copy(nodes) { | ||||
|     clipboardIds = nodes.map(node => node.data.noteId); | ||||
|     clipboardMode = 'copy'; | ||||
|  | ||||
|     infoService.showMessage("Note(s) have been copied into clipboard."); | ||||
| } | ||||
|  | ||||
| function cut(nodes) { | ||||
|     clipboardIds = nodes.map(node => node.key); | ||||
|     clipboardMode = 'cut'; | ||||
|  | ||||
|     infoService.showMessage("Note(s) have been cut into clipboard."); | ||||
| } | ||||
|  | ||||
| function getNoteTypeItems(baseCmd) { | ||||
|     return [ | ||||
|         { title: "Text", cmd: baseCmd + "_text", uiIcon: "file" }, | ||||
|         { title: "Code", cmd: baseCmd + "_code", uiIcon: "terminal" }, | ||||
|         { title: "Saved search", cmd: baseCmd + "_search", uiIcon: "search-folder" }, | ||||
|         { title: "Relation Map", cmd: baseCmd + "_relation-map", uiIcon: "map" }, | ||||
|         { title: "Render HTML note", cmd: baseCmd + "_render", uiIcon: "play" } | ||||
|     ]; | ||||
| } | ||||
|  | ||||
| async function getTopLevelItems(event) { | ||||
|     const node = $.ui.fancytree.getNode(event); | ||||
|     const branch = await treeCache.getBranch(node.data.branchId); | ||||
|     const note = await treeCache.getNote(node.data.noteId); | ||||
|     const parentNote = await treeCache.getNote(branch.parentNoteId); | ||||
|     const isNotRoot = note.noteId !== 'root'; | ||||
|     const isHoisted = note.noteId === await hoistedNoteService.getHoistedNoteId(); | ||||
|  | ||||
|     const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNote.type !== 'search'; | ||||
|     const insertChildNoteEnabled = note.type !== 'search'; | ||||
|  | ||||
|     return [ | ||||
|         { title: "Open in new tab", cmd: "openInTab", uiIcon: "empty" }, | ||||
|         { title: "Insert note after <kbd>Ctrl+O</kbd>", cmd: "insertNoteAfter", uiIcon: "plus", | ||||
|             items: insertNoteAfterEnabled ? getNoteTypeItems("insertNoteAfter") : null, | ||||
|             enabled: insertNoteAfterEnabled }, | ||||
|         { title: "Insert child note <kbd>Ctrl+P</kbd>", cmd: "insertChildNote", uiIcon: "plus", | ||||
|             items: insertChildNoteEnabled ? getNoteTypeItems("insertChildNote") : null, | ||||
|             enabled: insertChildNoteEnabled }, | ||||
|         { title: "Delete <kbd>Delete</kbd>", cmd: "delete", uiIcon: "trash", | ||||
|             enabled: isNotRoot && !isHoisted && parentNote.type !== 'search' }, | ||||
|         { title: "----" }, | ||||
|         isHoisted ? null : { title: "Hoist note <kbd>Ctrl-H</kbd>", cmd: "hoist", uiIcon: "empty" }, | ||||
|         !isHoisted || !isNotRoot ? null : { title: "Unhoist note <kbd>Ctrl-H</kbd>", cmd: "unhoist", uiIcon: "arrow-up" }, | ||||
|         { title: "Edit branch prefix <kbd>F2</kbd>", cmd: "editBranchPrefix", uiIcon: "empty", | ||||
|             enabled: isNotRoot && parentNote.type !== 'search'}, | ||||
|         { title: "----" }, | ||||
|         { title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check" }, | ||||
|         { title: "Unprotect subtree", cmd: "unprotectSubtree", uiIcon: "shield-close" }, | ||||
|         { title: "----" }, | ||||
|         { title: "Copy / clone <kbd>Ctrl+C</kbd>", cmd: "copy", uiIcon: "files", | ||||
|             enabled: isNotRoot }, | ||||
|         { title: "Cut <kbd>Ctrl+X</kbd>", cmd: "cut", uiIcon: "scissors", | ||||
|             enabled: isNotRoot }, | ||||
|         { title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "clipboard", | ||||
|             enabled: clipboardIds.length > 0 && note.type !== 'search' }, | ||||
|         { title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard", | ||||
|             enabled: clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search' }, | ||||
|         { title: "----" }, | ||||
|         { title: "Export", cmd: "export", uiIcon: "empty", | ||||
|             enabled: note.type !== 'search' }, | ||||
|         { title: "Import into note", cmd: "importIntoNote", uiIcon: "empty", | ||||
|             enabled: note.type !== 'search' }, | ||||
|         { title: "----" }, | ||||
|         { title: "Collapse subtree <kbd>Alt+-</kbd>", cmd: "collapseSubtree", uiIcon: "align-justify" }, | ||||
|         { title: "Force note sync", cmd: "forceNoteSync", uiIcon: "refresh" }, | ||||
|         { title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "empty" } | ||||
|     ].filter(row => row !== null); | ||||
| } | ||||
|  | ||||
| async function getContextMenuItems(event) { | ||||
|     const items = await getTopLevelItems(event); | ||||
|  | ||||
|     const node = $.ui.fancytree.getNode(event); | ||||
|  | ||||
|     // right click resets selection to just this node | ||||
|     // this is important when e.g. you right click on a note while having different note active | ||||
|     // and then click on delete - obviously you want to delete only that one right-clicked | ||||
|     node.setSelected(true); | ||||
|     treeService.clearSelectedNodes(); | ||||
|  | ||||
|     return [node, items]; | ||||
| } | ||||
|  | ||||
| async function selectContextMenuItem(event, cmd) { | ||||
|     // context menu is always triggered on current node | ||||
|     const node = treeService.getActiveNode(); | ||||
|  | ||||
|     if (cmd === 'openInTab') { | ||||
|         noteDetailService.openInTab(node.data.noteId); | ||||
|     } | ||||
|     else if (cmd.startsWith("insertNoteAfter")) { | ||||
|         const parentNoteId = node.data.parentNoteId; | ||||
|         const isProtected = await treeUtils.getParentProtectedStatus(node); | ||||
|         const type = cmd.split("_")[1]; | ||||
|  | ||||
|         treeService.createNote(node, parentNoteId, 'after', { | ||||
|             type: type, | ||||
|             isProtected: isProtected | ||||
|         }); | ||||
|     } | ||||
|     else if (cmd.startsWith("insertChildNote")) { | ||||
|         const type = cmd.split("_")[1]; | ||||
|  | ||||
|         treeService.createNote(node, node.data.noteId, 'into', { | ||||
|             type: type, | ||||
|             isProtected: node.data.isProtected | ||||
|         }); | ||||
|     } | ||||
|     else if (cmd === "editBranchPrefix") { | ||||
|         branchPrefixDialog.showDialog(node); | ||||
|     } | ||||
|     else if (cmd === "protectSubtree") { | ||||
|         protectedSessionService.protectSubtree(node.data.noteId, true); | ||||
|     } | ||||
|     else if (cmd === "unprotectSubtree") { | ||||
|         protectedSessionService.protectSubtree(node.data.noteId, false); | ||||
|     } | ||||
|     else if (cmd === "copy") { | ||||
|         copy(treeService.getSelectedNodes()); | ||||
|     } | ||||
|     else if (cmd === "cut") { | ||||
|         cut(treeService.getSelectedNodes()); | ||||
|     } | ||||
|     else if (cmd === "pasteAfter") { | ||||
|         pasteAfter(node); | ||||
|     } | ||||
|     else if (cmd === "pasteInto") { | ||||
|         pasteInto(node); | ||||
|     } | ||||
|     else if (cmd === "delete") { | ||||
|         treeChangesService.deleteNodes(treeService.getSelectedNodes(true)); | ||||
|     } | ||||
|     else if (cmd === "export") { | ||||
|         exportDialog.showDialog("subtree"); | ||||
|     } | ||||
|     else if (cmd === "importIntoNote") { | ||||
|         importDialog.showDialog(); | ||||
|     } | ||||
|     else if (cmd === "collapseSubtree") { | ||||
|         treeService.collapseTree(node); | ||||
|     } | ||||
|     else if (cmd === "forceNoteSync") { | ||||
|         syncService.forceNoteSync(node.data.noteId); | ||||
|     } | ||||
|     else if (cmd === "sortAlphabetically") { | ||||
|         treeService.sortAlphabetically(node.data.noteId); | ||||
|     } | ||||
|     else if (cmd === "hoist") { | ||||
|         hoistedNoteService.setHoistedNoteId(node.data.noteId); | ||||
|     } | ||||
|     else if (cmd === "unhoist") { | ||||
|         hoistedNoteService.unhoist(); | ||||
|     } | ||||
|     else { | ||||
|         messagingService.logError("Unknown command: " + cmd); | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     pasteAfter, | ||||
|     pasteInto, | ||||
|     cut, | ||||
|     copy, | ||||
|     getContextMenuItems, | ||||
|     selectContextMenuItem | ||||
| }; | ||||
| export default TreeContextMenu; | ||||
| @@ -1,10 +1,9 @@ | ||||
| import noteDetailService from "./note_detail.js"; | ||||
| import utils from "./utils.js"; | ||||
| import treeChangesService from "./branches.js"; | ||||
| import contextMenuService from "./tree_context_menu.js"; | ||||
| import treeService from "./tree.js"; | ||||
| import editBranchPrefixDialog from "../dialogs/branch_prefix.js"; | ||||
| import hoistedNoteService from "./hoisted_note.js"; | ||||
| import clipboard from "./clipboard.js"; | ||||
|  | ||||
| const keyBindings = { | ||||
|     "del": node => { | ||||
| @@ -90,17 +89,17 @@ const keyBindings = { | ||||
|         return false; | ||||
|     }, | ||||
|     "ctrl+c": () => { | ||||
|         contextMenuService.copy(treeService.getSelectedNodes()); | ||||
|         clipboard.copy(treeService.getSelectedNodes()); | ||||
|  | ||||
|         return false; | ||||
|     }, | ||||
|     "ctrl+x": () => { | ||||
|         contextMenuService.cut(treeService.getSelectedNodes()); | ||||
|         clipboard.cut(treeService.getSelectedNodes()); | ||||
|  | ||||
|         return false; | ||||
|     }, | ||||
|     "ctrl+v": node => { | ||||
|         contextMenuService.pasteInto(node); | ||||
|         clipboard.pasteInto(node); | ||||
|  | ||||
|         return false; | ||||
|     }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user