A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 123 lines 5.4 kB view raw
1/// #if !MOBILE 2import {getInstanceById, setPanelFocus} from "../layout/util"; 3import {Tab} from "../layout/Tab"; 4import {initSearchMenu} from "./search"; 5import {initDockMenu} from "./dock"; 6import {initFileMenu, initNavigationMenu} from "./navigation"; 7import {initTabMenu} from "./tab"; 8/// #endif 9/// #if !BROWSER 10import {ipcRenderer} from "electron"; 11/// #endif 12import {Menu} from "./Menu"; 13import {hasClosestByClassName, hasTopClosestByTag} from "../protyle/util/hasClosest"; 14import {App} from "../index"; 15import {Constants} from "../constants"; 16import {textMenu} from "./text"; 17import {hideTooltip} from "../dialog/tooltip"; 18 19export class Menus { 20 public menu: Menu; 21 22 constructor(app: App) { 23 this.menu = new Menu(); 24 /// #if !MOBILE 25 window.addEventListener("contextmenu", (event) => { 26 if (event.shiftKey) { 27 return; 28 } 29 let target = event.target as HTMLElement; 30 if (hasClosestByClassName(target, "av__panel") && !hasClosestByClassName(target, "b3-menu")) { 31 document.querySelector(".av__panel").dispatchEvent(new CustomEvent("click", {detail: "close"})); 32 event.stopPropagation(); 33 event.preventDefault(); 34 return; 35 } 36 if (target.classList.contains("b3-text-field") || (target.tagName === "INPUT" && (target as HTMLInputElement).type === "text")) { 37 /// #if !BROWSER 38 ipcRenderer.send(Constants.SIYUAN_CONTEXT_MENU, { 39 undo: window.siyuan.languages.undo, 40 redo: window.siyuan.languages.redo, 41 copy: window.siyuan.languages.copy, 42 cut: window.siyuan.languages.cut, 43 delete: window.siyuan.languages.delete, 44 paste: window.siyuan.languages.paste, 45 pasteAsPlainText: window.siyuan.languages.pasteAsPlainText, 46 selectAll: window.siyuan.languages.selectAll, 47 }); 48 /// #endif 49 event.stopPropagation(); 50 } else { 51 event.preventDefault(); 52 } 53 while (target && target.parentElement // ⌃⇥ 后点击会为空 54 && !target.parentElement.isEqualNode(document.querySelector("body"))) { 55 const dataType = target.getAttribute("data-type"); 56 if (dataType === "tab-header") { 57 this.unselect(); 58 initTabMenu(app, (getInstanceById(target.getAttribute("data-id")) as Tab)).popup({ 59 x: event.clientX, 60 y: event.clientY 61 }); 62 event.stopPropagation(); 63 break; 64 } else if (dataType === "navigation-root" && !window.siyuan.config.readonly) { 65 if (target.querySelector(".b3-list-item__text").classList.contains("ft__on-surface")) { 66 return; 67 } 68 this.unselect(); 69 // navigation 根上:新建文档/文件夹/取消挂在/打开文件位置 70 initNavigationMenu(app, target).popup({x: event.clientX, y: event.clientY}); 71 setPanelFocus(hasClosestByClassName(target, "sy__file") as HTMLElement); 72 event.stopPropagation(); 73 break; 74 } else if (dataType === "navigation-file") { 75 this.unselect(); 76 // navigation 文件上:删除/重命名/打开文件位置/导出 77 initFileMenu(app, this.getDir(target), target.getAttribute("data-path"), target).popup({ 78 x: event.clientX, 79 y: event.clientY 80 }); 81 setPanelFocus(hasClosestByClassName(target, "sy__file") as HTMLElement); 82 event.stopPropagation(); 83 break; 84 } else if (dataType === "search-item") { 85 const nodeId = target.getAttribute("data-node-id"); 86 if (nodeId) { 87 initSearchMenu(nodeId).popup({x: event.clientX, y: event.clientY}); 88 } 89 event.stopPropagation(); 90 break; 91 } else if (dataType && target.classList.contains("dock__item")) { 92 hideTooltip(); 93 initDockMenu(target).popup({x: event.clientX, y: event.clientY}); 94 event.stopPropagation(); 95 break; 96 } else if (dataType === "textMenu") { 97 /// #if !BROWSER 98 textMenu(target).open({x: event.clientX, y: event.clientY}); 99 event.stopPropagation(); 100 event.preventDefault(); 101 break; 102 /// #endif 103 } 104 105 target = target.parentElement; 106 } 107 }, false); 108 /// #endif 109 } 110 111 private getDir(target: HTMLElement) { 112 const rootElement = hasTopClosestByTag(target, "UL"); 113 if (rootElement) { 114 return rootElement.getAttribute("data-url"); 115 } 116 } 117 118 private unselect() { 119 if (getSelection().rangeCount > 0) { 120 getSelection().getRangeAt(0).collapse(true); 121 } 122 } 123}