A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 426 lines 15 kB view raw
1import {newDailyNote} from "../../../util/mount"; 2import {openHistory} from "../../../history/history"; 3import {Editor} from "../../../editor"; 4/// #if MOBILE 5import {openDock} from "../../../mobile/dock/util"; 6import {popMenu} from "../../../mobile/menu"; 7import {popSearch} from "../../../mobile/menu/search"; 8import {getRecentDocs} from "../../../mobile/menu/getRecentDocs"; 9/// #else 10import {openNewWindow} from "../../../window/openNewWindow"; 11import {openBacklink, openGraph, openOutline, selectOpenTab, toggleDockBar} from "../../../layout/dock/util"; 12import {openGlobalSearch} from "../../../search/util"; 13import {workspaceMenu} from "../../../menus/workspace"; 14import {isWindow} from "../../../util/functions"; 15import {openRecentDocs} from "../../../business/openRecentDocs"; 16import {openSearch} from "../../../search/spread"; 17import {goBack, goForward} from "../../../util/backForward"; 18import {getAllTabs, getAllWnds} from "../../../layout/getAll"; 19import {getInstanceById} from "../../../layout/util"; 20import { 21 closeTabByType, 22 copyTab, 23 getActiveTab, 24 getDockByType, 25 resizeTabs, 26 switchTabByIndex 27} from "../../../layout/tabUtil"; 28import {openSetting} from "../../../config"; 29import {Tab} from "../../../layout/Tab"; 30/// #endif 31/// #if !BROWSER 32import {ipcRenderer} from "electron"; 33/// #endif 34import {App} from "../../../index"; 35import {Constants} from "../../../constants"; 36import {setReadOnly} from "../../../config/util/setReadOnly"; 37import {lockScreen} from "../../../dialog/processSystem"; 38import {newFile} from "../../../util/newFile"; 39import {openCard} from "../../../card/openCard"; 40import {syncGuide} from "../../../sync/syncGuide"; 41import {Wnd} from "../../../layout/Wnd"; 42import {unsplitWnd} from "../../../menus/tab"; 43import {openFile} from "../../../editor/util"; 44 45export const globalCommand = (command: string, app: App) => { 46 /// #if MOBILE 47 switch (command) { 48 case "fileTree": 49 openDock("file"); 50 return true; 51 case "outline": 52 case "bookmark": 53 case "tag": 54 case "inbox": 55 openDock(command); 56 return true; 57 case "backlinks": 58 openDock("backlink"); 59 return true; 60 case "mainMenu": 61 popMenu(); 62 return true; 63 case "globalSearch": 64 popSearch(app); 65 return true; 66 case "recentDocs": 67 getRecentDocs(app); 68 return true; 69 } 70 /// #else 71 switch (command) { 72 case "fileTree": 73 getDockByType("file").toggleModel("file"); 74 return true; 75 case "outline": 76 getDockByType("outline").toggleModel("outline"); 77 return true; 78 case "bookmark": 79 case "tag": 80 case "inbox": 81 getDockByType(command).toggleModel(command); 82 return true; 83 case "backlinks": 84 getDockByType("backlink").toggleModel("backlink"); 85 return true; 86 case "graphView": 87 getDockByType("graph").toggleModel("graph"); 88 return true; 89 case "globalGraph": 90 getDockByType("globalGraph").toggleModel("globalGraph"); 91 return true; 92 case "config": 93 openSetting(app); 94 return true; 95 case "globalSearch": 96 openSearch({ 97 app, 98 hotkey: Constants.DIALOG_GLOBALSEARCH, 99 key: (getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : document.createRange()).toString() 100 }); 101 return true; 102 case "stickSearch": 103 openGlobalSearch(app, (getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : document.createRange()).toString(), true); 104 return true; 105 case "goBack": 106 goBack(app); 107 return true; 108 case "goForward": 109 goForward(app); 110 return true; 111 case "goToTab1": 112 switchTabByIndex(0); 113 return true; 114 case "goToTab2": 115 switchTabByIndex(1); 116 return true; 117 case "goToTab3": 118 switchTabByIndex(2); 119 return true; 120 case "goToTab4": 121 switchTabByIndex(3); 122 return true; 123 case "goToTab5": 124 switchTabByIndex(4); 125 return true; 126 case "goToTab6": 127 switchTabByIndex(5); 128 return true; 129 case "goToTab7": 130 switchTabByIndex(6); 131 return true; 132 case "goToTab8": 133 switchTabByIndex(7); 134 return true; 135 case "goToTab9": 136 switchTabByIndex(-1); 137 return true; 138 case "goToTabNext": 139 switchTabByIndex(-3); 140 return true; 141 case "goToTabPrev": 142 switchTabByIndex(-2); 143 return true; 144 case "mainMenu": 145 if (!isWindow()) { 146 workspaceMenu(app, document.querySelector("#barWorkspace").getBoundingClientRect()); 147 } 148 return true; 149 case "recentDocs": 150 openRecentDocs(); 151 return true; 152 case "recentClosed": 153 if (window.siyuan.closedTabs.length > 0) { 154 const closeData = window.siyuan.closedTabs.pop(); 155 const childData = closeData.children as ILayoutJSON; 156 if (childData.instance === "Editor") { 157 openFile({ 158 app, 159 fileName: closeData.title, 160 id: childData.blockId, 161 rootID: childData.rootId, 162 mode: childData.mode, 163 action: [childData.action] 164 }); 165 } else if (childData.instance === "Asset") { 166 openFile({ 167 app, 168 assetPath: childData.path, 169 page: childData.page, 170 }); 171 } else if (childData.instance === "Backlink") { 172 openBacklink({ 173 app, 174 blockId: childData.blockId, 175 rootId: childData.rootId, 176 title: closeData.title, 177 }); 178 } else if (childData.instance === "Graph") { 179 openGraph({ 180 app, 181 blockId: childData.blockId, 182 rootId: childData.rootId, 183 title: closeData.title 184 }); 185 } else if (childData.instance === "Outline") { 186 openOutline({ 187 app, 188 rootId: childData.blockId, 189 title: closeData.title, 190 isPreview: childData.isPreview 191 }); 192 } else if (childData.instance === "Search") { 193 openFile({ 194 app, 195 searchData: childData.config, 196 }); 197 } else if (childData.instance === "Custom") { 198 openFile({ 199 app, 200 custom: { 201 icon: closeData.icon, 202 title: closeData.title, 203 data: childData.customModelData, 204 id: childData.customModelType 205 }, 206 }); 207 } 208 } 209 return true; 210 case "toggleDock": 211 toggleDockBar(document.querySelector("#barDock use")); 212 return true; 213 case "toggleWin": 214 /// #if !BROWSER 215 ipcRenderer.send(Constants.SIYUAN_CMD, "hide"); 216 ipcRenderer.send(Constants.SIYUAN_CMD, "minimize"); 217 /// #endif 218 return true; 219 } 220 if (command === "goToEditTabNext" || command === "goToEditTabPrev") { 221 let currentTabElement = document.querySelector(".layout__wnd--active ul.layout-tab-bar > .item--focus"); 222 if (!currentTabElement) { 223 currentTabElement = document.querySelector("ul.layout-tab-bar > .item--focus"); 224 } 225 if (!currentTabElement) { 226 return true; 227 } 228 const tabs = getAllTabs().sort((itemA, itemB) => { 229 return itemA.headElement.getAttribute("data-activetime") > itemB.headElement.getAttribute("data-activetime") ? -1 : 1; 230 }); 231 const currentId = currentTabElement.getAttribute("data-id"); 232 tabs.find((item, index) => { 233 if (currentId === item.id) { 234 let newItem: Tab; 235 if (command === "goToEditTabPrev") { 236 if (index === 0) { 237 newItem = tabs[tabs.length - 1]; 238 } else { 239 newItem = tabs[index - 1]; 240 } 241 } else { 242 if (index === tabs.length - 1) { 243 newItem = tabs[0]; 244 } else { 245 newItem = tabs[index + 1]; 246 } 247 } 248 const tab = getInstanceById(newItem.id) as Tab; 249 tab.parent.switchTab(newItem.headElement); 250 tab.parent.showHeading(); 251 } 252 }); 253 return true; 254 } 255 if (command === "closeUnmodified") { 256 const tab = getActiveTab(false); 257 if (tab) { 258 const unmodifiedTabs: Tab[] = []; 259 tab.parent.children.forEach((item: Tab) => { 260 const editor = item.model as Editor; 261 if (!editor || (editor.editor?.protyle && !editor.editor?.protyle.updated)) { 262 unmodifiedTabs.push(item); 263 } 264 }); 265 if (unmodifiedTabs.length > 0) { 266 closeTabByType(tab, "other", unmodifiedTabs); 267 } 268 } 269 return true; 270 } 271 if (command === "unsplitAll") { 272 unsplitWnd(window.siyuan.layout.centerLayout, window.siyuan.layout.centerLayout, false); 273 return true; 274 } 275 if (command === "unsplit") { 276 const tab = getActiveTab(false); 277 if (tab) { 278 let wndsTemp: Wnd[] = []; 279 let layout = tab.parent.parent; 280 while (layout.id !== window.siyuan.layout.centerLayout.id) { 281 wndsTemp = []; 282 getAllWnds(layout, wndsTemp); 283 if (wndsTemp.length > 1) { 284 break; 285 } else { 286 layout = layout.parent; 287 } 288 } 289 unsplitWnd(tab.parent.parent.children[0], layout, true); 290 resizeTabs(); 291 } 292 return true; 293 } 294 if (command === "closeTab") { 295 const activeTabElement = document.querySelector(".layout__tab--active"); 296 if (activeTabElement && activeTabElement.getBoundingClientRect().width > 0) { 297 let type: TDock; 298 Array.from(activeTabElement.classList).find(item => { 299 if (item.startsWith("sy__")) { 300 type = item.replace("sy__", "") as TDock; 301 return true; 302 } 303 }); 304 if (type) { 305 getDockByType(type)?.toggleModel(type, false, true); 306 } 307 return true; 308 } 309 310 const tab = getActiveTab(); 311 if (tab) { 312 tab.parent.removeTab(tab.id); 313 return true; 314 } 315 // https://github.com/siyuan-note/siyuan/issues/14729 316 if (window.siyuan.blockPanels.length > 0) { 317 window.siyuan.blockPanels[window.siyuan.blockPanels.length - 1]?.destroy(); 318 return true; 319 } 320 const noFocusTab = getActiveTab(false); 321 if (noFocusTab) { 322 noFocusTab.parent.removeTab(noFocusTab.id); 323 return true; 324 } 325 } 326 if (command === "closeOthers" || command === "closeAll") { 327 const tab = getActiveTab(false); 328 if (tab) { 329 closeTabByType(tab, command); 330 } 331 return true; 332 } 333 if (command === "closeLeft" || command === "closeRight") { 334 const tab = getActiveTab(false); 335 if (tab) { 336 const leftTabs: Tab[] = []; 337 const rightTabs: Tab[] = []; 338 let midIndex = -1; 339 tab.parent.children.forEach((item: Tab, index: number) => { 340 if (item.id === tab.id) { 341 midIndex = index; 342 } 343 if (midIndex === -1) { 344 leftTabs.push(item); 345 } else if (index > midIndex) { 346 rightTabs.push(item); 347 } 348 }); 349 if (command === "closeLeft") { 350 if (leftTabs.length > 0) { 351 closeTabByType(tab, "other", leftTabs); 352 } 353 } else { 354 if (rightTabs.length > 0) { 355 closeTabByType(tab, "other", rightTabs); 356 } 357 } 358 } 359 return true; 360 } 361 if (command === "splitLR") { 362 const tab = getActiveTab(false); 363 if (tab) { 364 tab.parent.split("lr").addTab(copyTab(app, tab)); 365 } 366 return true; 367 } 368 if (command === "splitTB") { 369 const tab = getActiveTab(false); 370 if (tab) { 371 tab.parent.split("tb").addTab(copyTab(app, tab)); 372 } 373 return true; 374 } 375 if (command === "splitMoveB" || command === "splitMoveR") { 376 const tab = getActiveTab(false); 377 if (tab && tab.parent.children.length > 1) { 378 const newWnd = tab.parent.split(command === "splitMoveB" ? "tb" : "lr"); 379 newWnd.headersElement.append(tab.headElement); 380 newWnd.headersElement.parentElement.classList.remove("fn__none"); 381 newWnd.moveTab(tab); 382 resizeTabs(); 383 } 384 return true; 385 } 386 if (command === "tabToWindow") { 387 const tab = getActiveTab(false); 388 if (tab) { 389 openNewWindow(tab); 390 } 391 return true; 392 } 393 /// #endif 394 395 switch (command) { 396 case "dailyNote": 397 newDailyNote(app); 398 return true; 399 case "dataHistory": 400 openHistory(app); 401 return true; 402 case "editReadonly": 403 setReadOnly(!window.siyuan.config.editor.readOnly); 404 return true; 405 case "lockScreen": 406 lockScreen(app); 407 return true; 408 case "newFile": 409 newFile({ 410 app, 411 useSavePath: true 412 }); 413 return true; 414 case "riffCard": 415 openCard(app); 416 return true; 417 case "selectOpen1": 418 selectOpenTab(); 419 return true; 420 case "syncNow": 421 syncGuide(app); 422 return true; 423 } 424 425 return false; 426};