A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 304 lines 14 kB view raw
1import {fetchPost, fetchSyncPost} from "../../util/fetch"; 2import {MenuItem} from "../../menus/Menu"; 3import {copySubMenu, exportMd, movePathToMenu, openFileAttr, openFileWechatNotify,} from "../../menus/commonMenuItem"; 4import {deleteFile} from "../../editor/deleteFile"; 5import {updateHotkeyTip} from "../util/compatibility"; 6/// #if !MOBILE 7import {openBacklink, openGraph, openOutline} from "../../layout/dock/util"; 8import * as path from "path"; 9/// #else 10import {openMobileFileById} from "../../mobile/editor"; 11/// #endif 12import {Constants} from "../../constants"; 13import {openCardByData} from "../../card/openCard"; 14import {viewCards} from "../../card/viewCards"; 15import {getDisplayName, getNotebookName, pathPosix, useShell} from "../../util/pathName"; 16import {makeCard, quickMakeCard} from "../../card/makeCard"; 17import {emitOpenMenu} from "../../plugin/EventBus"; 18import * as dayjs from "dayjs"; 19import {hideTooltip} from "../../dialog/tooltip"; 20import {popSearch} from "../../mobile/menu/search"; 21import {openSearch} from "../../search/spread"; 22import {openDocHistory} from "../../history/doc"; 23import {openNewWindowById} from "../../window/openNewWindow"; 24import {transferBlockRef} from "../../menus/block"; 25import {addEditorToDatabase} from "../render/av/addToDatabase"; 26import {openFileById} from "../../editor/util"; 27import {hasTopClosestByClassName} from "../util/hasClosest"; 28 29export const openTitleMenu = (protyle: IProtyle, position: IPosition, from: string) => { 30 hideTooltip(); 31 if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && 32 window.siyuan.menus.menu.element.getAttribute("data-name") === Constants.MENU_TITLE) { 33 window.siyuan.menus.menu.remove(); 34 return; 35 } 36 fetchPost("/api/block/getDocInfo", { 37 id: protyle.block.rootID 38 }, (response) => { 39 window.siyuan.menus.menu.remove(); 40 window.siyuan.menus.menu.element.setAttribute("data-name", Constants.MENU_TITLE); 41 const popoverElement = hasTopClosestByClassName(protyle.element, "block__popover", true); 42 window.siyuan.menus.menu.element.setAttribute("data-from", popoverElement ? popoverElement.dataset.level + "popover-" + from : "app-" + from); 43 window.siyuan.menus.menu.append(new MenuItem({ 44 id: "copy", 45 label: window.siyuan.languages.copy, 46 icon: "iconCopy", 47 type: "submenu", 48 submenu: copySubMenu([protyle.block.rootID], true, undefined, protyle.block.showAll ? protyle.block.id : protyle.block.rootID) 49 }).element); 50 if (!protyle.disabled) { 51 window.siyuan.menus.menu.append(movePathToMenu([protyle.path])); 52 const range = getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : undefined; 53 window.siyuan.menus.menu.append(new MenuItem({ 54 id: "addToDatabase", 55 label: window.siyuan.languages.addToDatabase, 56 accelerator: window.siyuan.config.keymap.general.addToDatabase.custom, 57 icon: "iconDatabase", 58 click: () => { 59 addEditorToDatabase(protyle, range, "title"); 60 } 61 }).element); 62 window.siyuan.menus.menu.append(new MenuItem({ 63 id: "delete", 64 icon: "iconTrashcan", 65 label: window.siyuan.languages.delete, 66 click: () => { 67 deleteFile(protyle.notebookId, protyle.path); 68 } 69 }).element); 70 } 71 /// #if !MOBILE 72 window.siyuan.menus.menu.append(new MenuItem({id: "separator_1", type: "separator"}).element); 73 window.siyuan.menus.menu.append(new MenuItem({ 74 id: "outline", 75 icon: "iconAlignCenter", 76 label: window.siyuan.languages.outline, 77 accelerator: window.siyuan.config.keymap.editor.general.outline.custom, 78 click: () => { 79 openOutline({ 80 app: protyle.app, 81 rootId: protyle.block.rootID, 82 title: protyle.options.render.title ? (protyle.title.editElement.textContent || window.siyuan.languages.untitled) : "", 83 isPreview: !protyle.preview.element.classList.contains("fn__none") 84 }); 85 } 86 }).element); 87 window.siyuan.menus.menu.append(new MenuItem({ 88 id: "backlinks", 89 icon: "iconLink", 90 label: window.siyuan.languages.backlinks, 91 accelerator: window.siyuan.config.keymap.editor.general.backlinks.custom, 92 click: () => { 93 openBacklink({ 94 app: protyle.app, 95 blockId: protyle.block.id, 96 rootId: protyle.block.rootID, 97 useBlockId: protyle.block.showAll, 98 title: protyle.title ? (protyle.title.editElement.textContent || window.siyuan.languages.untitled) : null 99 }); 100 } 101 }).element); 102 window.siyuan.menus.menu.append(new MenuItem({ 103 id: "graphView", 104 icon: "iconGraph", 105 label: window.siyuan.languages.graphView, 106 accelerator: window.siyuan.config.keymap.editor.general.graphView.custom, 107 click: () => { 108 openGraph({ 109 app: protyle.app, 110 blockId: protyle.block.id, 111 rootId: protyle.block.rootID, 112 useBlockId: protyle.block.showAll, 113 title: protyle.title ? (protyle.title.editElement.textContent || window.siyuan.languages.untitled) : null 114 }); 115 } 116 }).element); 117 /// #endif 118 window.siyuan.menus.menu.append(new MenuItem({id: "separator_2", type: "separator"}).element); 119 window.siyuan.menus.menu.append(new MenuItem({ 120 id: "attr", 121 label: window.siyuan.languages.attr, 122 icon: "iconAttr", 123 accelerator: window.siyuan.config.keymap.editor.general.attr.custom + "/" + updateHotkeyTip("⇧" + window.siyuan.languages.click), 124 click() { 125 openFileAttr(response.data.ial, "bookmark", protyle); 126 } 127 }).element); 128 if (!window.siyuan.config.readonly) { 129 if (window.siyuan.config.cloudRegion === 0) { 130 window.siyuan.menus.menu.append(new MenuItem({ 131 id: "wechatReminder", 132 label: window.siyuan.languages.wechatReminder, 133 icon: "iconMp", 134 click() { 135 openFileWechatNotify(protyle); 136 } 137 }).element); 138 } 139 const isCardMade = !!response.data.ial[Constants.CUSTOM_RIFF_DECKS]; 140 const riffCardMenu: IMenu[] = [{ 141 id: "spaceRepetition", 142 iconHTML: "", 143 label: window.siyuan.languages.spaceRepetition, 144 accelerator: window.siyuan.config.keymap.editor.general.spaceRepetition.custom, 145 click: () => { 146 fetchPost("/api/riff/getTreeRiffDueCards", {rootID: protyle.block.rootID}, (response) => { 147 openCardByData(protyle.app, response.data, "doc", protyle.block.rootID, response.data.name); 148 }); 149 } 150 }, { 151 id: "manage", 152 iconHTML: "", 153 label: window.siyuan.languages.manage, 154 click: () => { 155 fetchPost("/api/filetree/getHPathByID", { 156 id: protyle.block.rootID 157 }, (response) => { 158 viewCards(protyle.app, protyle.block.rootID, pathPosix().join(getNotebookName(protyle.notebookId), (response.data)), "Tree"); 159 }); 160 } 161 }, { 162 id: isCardMade ? "removeCard" : "quickMakeCard", 163 iconHTML: "", 164 label: isCardMade ? window.siyuan.languages.removeCard : window.siyuan.languages.quickMakeCard, 165 accelerator: window.siyuan.config.keymap.editor.general.quickMakeCard.custom, 166 click: () => { 167 let titleElement = protyle.title?.element; 168 if (!titleElement) { 169 titleElement = document.createElement("div"); 170 titleElement.setAttribute("data-node-id", protyle.block.rootID); 171 titleElement.setAttribute(Constants.CUSTOM_RIFF_DECKS, response.data.ial[Constants.CUSTOM_RIFF_DECKS]); 172 } 173 quickMakeCard(protyle, [titleElement]); 174 } 175 }]; 176 if (window.siyuan.config.flashcard.deck) { 177 riffCardMenu.push({ 178 id: "addToDeck", 179 iconHTML: "", 180 label: window.siyuan.languages.addToDeck, 181 click: () => { 182 makeCard(protyle.app, [protyle.block.rootID]); 183 } 184 }); 185 } 186 window.siyuan.menus.menu.append(new MenuItem({ 187 id: "riffCard", 188 label: window.siyuan.languages.riffCard, 189 type: "submenu", 190 icon: "iconRiffCard", 191 submenu: riffCardMenu, 192 }).element); 193 } 194 window.siyuan.menus.menu.append(new MenuItem({ 195 id: "search", 196 label: window.siyuan.languages.search, 197 icon: "iconSearch", 198 accelerator: window.siyuan.config.keymap.general.search.custom, 199 async click() { 200 const searchPath = getDisplayName(protyle.path, false, true); 201 /// #if MOBILE 202 const pathResponse = await fetchSyncPost("/api/filetree/getHPathByPath", { 203 notebook: protyle.notebookId, 204 path: searchPath + ".sy" 205 }); 206 popSearch(protyle.app, { 207 hasReplace: false, 208 hPath: pathPosix().join(getNotebookName(protyle.notebookId), pathResponse.data), 209 idPath: [pathPosix().join(protyle.notebookId, searchPath)], 210 page: 1, 211 }); 212 /// #else 213 openSearch({ 214 app: protyle.app, 215 hotkey: Constants.DIALOG_SEARCH, 216 notebookId: protyle.notebookId, 217 searchPath 218 }); 219 /// #endif 220 } 221 }).element); 222 if (!protyle.disabled) { 223 transferBlockRef(protyle.block.rootID); 224 } 225 window.siyuan.menus.menu.append(new MenuItem({id: "separator_3", type: "separator"}).element); 226 if (!protyle.model) { 227 window.siyuan.menus.menu.append(new MenuItem({ 228 id: "openBy", 229 label: window.siyuan.languages.openBy, 230 icon: "iconOpen", 231 click() { 232 /// #if !MOBILE 233 openFileById({ 234 app: protyle.app, 235 id: protyle.block.id, 236 action: protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_CONTEXT], 237 }); 238 /// #else 239 openMobileFileById(protyle.app, protyle.block.id, protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL] : [Constants.CB_GET_CONTEXT]); 240 /// #endif 241 } 242 }).element); 243 } 244 /// #if !BROWSER 245 window.siyuan.menus.menu.append(new MenuItem({ 246 id: "openByNewWindow", 247 label: window.siyuan.languages.openByNewWindow, 248 icon: "iconOpenWindow", 249 click() { 250 openNewWindowById(protyle.block.rootID); 251 } 252 }).element); 253 window.siyuan.menus.menu.append(new MenuItem({ 254 id: "showInFolder", 255 icon: "iconFolder", 256 label: window.siyuan.languages.showInFolder, 257 click: () => { 258 useShell("showItemInFolder", path.join(window.siyuan.config.system.dataDir, protyle.notebookId, protyle.path)); 259 } 260 }).element); 261 /// #endif 262 if (!protyle.disabled) { 263 window.siyuan.menus.menu.append(new MenuItem({ 264 id: "fileHistory", 265 label: window.siyuan.languages.fileHistory, 266 icon: "iconHistory", 267 click() { 268 openDocHistory({ 269 app: protyle.app, 270 id: protyle.block.rootID, 271 notebookId: protyle.notebookId, 272 pathString: response.data.name 273 }); 274 } 275 }).element); 276 } 277 window.siyuan.menus.menu.append(exportMd(protyle.block.showAll ? protyle.block.id : protyle.block.rootID)); 278 279 window.siyuan.menus.menu.append(new MenuItem({id: "separator_4", type: "separator"}).element); 280 if (protyle?.app?.plugins) { 281 emitOpenMenu({ 282 plugins: protyle.app.plugins, 283 type: "click-editortitleicon", 284 detail: { 285 protyle, 286 data: response.data, 287 }, 288 separatorPosition: "bottom", 289 }); 290 } 291 window.siyuan.menus.menu.append(new MenuItem({ 292 id: "updateAndCreatedAt", 293 iconHTML: "", 294 type: "readonly", 295 // 不能换行,否则移动端间距过大 296 label: `${window.siyuan.languages.modifiedAt} ${dayjs(response.data.ial.updated).format("YYYY-MM-DD HH:mm:ss")}<br>${window.siyuan.languages.createdAt} ${dayjs(response.data.ial.id.substr(0, 14)).format("YYYY-MM-DD HH:mm:ss")}` 297 }).element); 298 /// #if MOBILE 299 window.siyuan.menus.menu.fullscreen(); 300 /// #else 301 window.siyuan.menus.menu.popup(position); 302 /// #endif 303 }); 304};