diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index ed79df10d..33938508e 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1,4 +1,15 @@ { + "goToTab1": "Go to tab #1", + "goToTab2": "Go to tab #2", + "goToTab3": "Go to tab #3", + "goToTab4": "Go to tab #4", + "goToTab5": "Go to tab #5", + "goToTab6": "Go to tab #6", + "goToTab7": "Go to tab #7", + "goToTab8": "Go to tab #8", + "goToTab9": "Go to last tab", + "goToTabNext": "Go to next tab", + "goToTabPrev": "Go to previous tab", "createdTime": "Created time", "updatedTime": "Updated time", "removeBookmark": "Remove bookmark from ${x}?", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 7f42a4832..88601fd50 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1,4 +1,15 @@ { + "goToTab1": "Ir a la pestaña #1", + "goToTab2": "Ir a la pestaña #2", + "goToTab3": "Ir a la pestaña #3", + "goToTab4": "Ir a la pestaña #4", + "goToTab5": "Ir a la pestaña #5", + "goToTab6": "Ir a la pestaña #6", + "goToTab7": "Ir a la pestaña #7", + "goToTab8": "Ir a la pestaña #8", + "goToTab9": "Ir a la última pestaña", + "goToTabNext": "Ir a la siguiente pestaña", + "goToTabPrev": "Ir a la pestaña anterior", "createdTime": "Hora de creación", "updatedTime": "Hora actualizada", "removeBookmark": "¿Eliminar marcador de ${x}?", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 0339c9a48..80e8d3783 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1,4 +1,15 @@ { + "goToTab1": "Aller à l'onglet #1", + "goToTab2": "Aller à l'onglet #2", + "goToTab3": "Aller à l'onglet #3", + "goToTab4": "Aller à l'onglet #4", + "goToTab5": "Aller à l'onglet #5", + "goToTab6": "Aller à l'onglet #6", + "goToTab7": "Aller à l'onglet #7", + "goToTab8": "Aller à l'onglet #8", + "goToTab9": "Aller au dernier onglet", + "goToTabNext": "Aller à l'onglet suivant", + "goToTabPrev": "Aller à l'onglet précédent", "createdTime": "Heure de création", "updatedTime": "Heure mise à jour", "removeBookmark": "Supprimer le signet de ${x} ?", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index 97efab286..1e071c535 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1,4 +1,15 @@ { + "goToTab1": "跳到第一個頁籤", + "goToTab2": "跳到第二個頁籤", + "goToTab3": "跳到第三個頁籤", + "goToTab4": "跳到第四個頁籤", + "goToTab5": "跳到第五個頁籤", + "goToTab6": "跳到第六個頁籤", + "goToTab7": "跳到第七個頁籤", + "goToTab8": "跳到第八個頁籤", + "goToTab9": "跳到最後一個頁籤", + "goToTabNext": "跳到下一個頁籤", + "goToTabPrev": "跳到上一個頁籤", "createdTime": "建立時間", "updatedTime": "更新時間", "removeBookmark": "移除 ${x} 中的書籤?", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 0cd787a4b..8037e746f 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1,4 +1,15 @@ { + "goToTab1": "跳转到第一个页签", + "goToTab2": "跳转到第二个页签", + "goToTab3": "跳转到第三个页签", + "goToTab4": "跳转到第四个页签", + "goToTab5": "跳转到第五个页签", + "goToTab6": "跳转到第六个页签", + "goToTab7": "跳转到第七个页签", + "goToTab8": "跳转到第八个页签", + "goToTab9": "跳转到最后一个页签", + "goToTabNext": "跳转到下一个页签", + "goToTabPrev": "跳转到上一个页签", "createdTime": "创建时间", "updatedTime": "更新时间", "removeBookmark": "移除 ${x} 中的书签?", diff --git a/app/src/boot/globalEvent/keydown.ts b/app/src/boot/globalEvent/keydown.ts index e9a5f8ba5..5785a9a79 100644 --- a/app/src/boot/globalEvent/keydown.ts +++ b/app/src/boot/globalEvent/keydown.ts @@ -10,7 +10,9 @@ import { import {newFile} from "../../util/newFile"; import {Constants} from "../../constants"; import {openSetting} from "../../config"; -import {copyTab, getDockByType, getInstanceById, resizeTabs} from "../../layout/util"; +import {getInstanceById} from "../../layout/util"; +import {closeTabByType, copyTab, getDockByType, resizeTabs, switchTabByIndex} from "../../layout/tabUtil"; +import {getActiveTab} from "../../layout/tabUtil"; import {Tab} from "../../layout/Tab"; import {Editor} from "../../editor"; import {setEditMode} from "../../protyle/util/setEditMode"; @@ -156,7 +158,6 @@ const dialogArrow = (app: App, element: HTMLElement, event: KeyboardEvent) => { }; const editKeydown = (app: App, event: KeyboardEvent) => { - const activeTabElement = document.querySelector(".layout__wnd--active .item--focus"); let protyle: IProtyle; let range: Range; if (getSelection().rangeCount > 0) { @@ -177,14 +178,14 @@ const editKeydown = (app: App, event: KeyboardEvent) => { } }); } - if (!protyle && activeTabElement) { - const tab = getInstanceById(activeTabElement.getAttribute("data-id")) as Tab; - if (tab.model instanceof Editor) { - protyle = tab.model.editor.protyle; - } else if (tab.model instanceof Search) { - protyle = tab.model.edit.protyle; - } else if (tab.model instanceof Custom && tab.model.data?.editor instanceof Protyle) { - protyle = tab.model.data.editor.protyle; + const activeTab = getActiveTab() + if (!protyle && activeTab) { + if (activeTab.model instanceof Editor) { + protyle = activeTab.model.editor.protyle; + } else if (activeTab.model instanceof Search) { + protyle = activeTab.model.edit.protyle; + } else if (activeTab.model instanceof Custom && activeTab.model.data?.editor instanceof Protyle) { + protyle = activeTab.model.data.editor.protyle; } else { return false; } @@ -1338,7 +1339,7 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { // close tab if (matchHotKey(window.siyuan.config.keymap.general.closeTab.custom, event) && !event.repeat) { event.preventDefault(); - let activeTabElement = document.querySelector(".layout__tab--active"); + const activeTabElement = document.querySelector(".layout__tab--active"); if (activeTabElement && activeTabElement.getBoundingClientRect().width > 0) { let type = ""; Array.from(activeTabElement.classList).find(item => { @@ -1352,18 +1353,131 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { } return; } - activeTabElement = document.querySelector(".layout__wnd--active .item--focus"); - if (activeTabElement) { - const tab = getInstanceById(activeTabElement.getAttribute("data-id")) as Tab; + const tab = getActiveTab(false); + if (tab) { tab.parent.removeTab(tab.id); - return; } - getAllTabs().find(item => { - if (item.headElement?.classList.contains("item--focus")) { - item.parent.removeTab(item.id); - return true; + return; + } + + if (matchHotKey(window.siyuan.config.keymap.general.goToTab1.custom, event) && !event.repeat) { + switchTabByIndex(0); + event.preventDefault(); + return; + } + + if (matchHotKey(window.siyuan.config.keymap.general.goToTab2.custom, event) && !event.repeat) { + switchTabByIndex(1); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab3.custom, event) && !event.repeat) { + switchTabByIndex(2); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab4.custom, event) && !event.repeat) { + switchTabByIndex(3); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab5.custom, event) && !event.repeat) { + switchTabByIndex(4); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab6.custom, event) && !event.repeat) { + switchTabByIndex(5); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab7.custom, event) && !event.repeat) { + switchTabByIndex(6); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab8.custom, event) && !event.repeat) { + switchTabByIndex(7); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTab9.custom, event) && !event.repeat) { + switchTabByIndex(-1); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTabNext.custom, event) && !event.repeat) { + switchTabByIndex(-3); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.goToTabPrev.custom, event) && !event.repeat) { + switchTabByIndex(-2); + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.closeOthers.custom, event) && !event.repeat) { + const tab = getActiveTab(); + if (tab) { + closeTabByType(tab, "closeOthers"); + } + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.closeAll.custom, event) && !event.repeat) { + const tab = getActiveTab(); + if (tab) { + closeTabByType(tab, "closeAll"); + } + event.preventDefault(); + return; + } + if (matchHotKey(window.siyuan.config.keymap.general.closeUnmodified.custom, event) && !event.repeat) { + const tab = getActiveTab(); + if (tab) { + const unmodifiedTabs: Tab[] = [] + tab.parent.children.forEach((item: Tab) => { + const editor = item.model as Editor; + if (!editor || (editor.editor?.protyle && !editor.editor?.protyle.updated)) { + unmodifiedTabs.push(item); + } + }); + if (unmodifiedTabs.length > 0) { + closeTabByType(tab, "other", unmodifiedTabs); } - }); + } + event.preventDefault(); + return; + } + if ((matchHotKey(window.siyuan.config.keymap.general.closeLeft.custom, event) || matchHotKey(window.siyuan.config.keymap.general.closeRight.custom, event)) && + !event.repeat) { + const tab = getActiveTab(); + if (tab) { + const leftTabs: Tab[] = []; + const rightTabs: Tab[] = []; + let midIndex = -1; + tab.parent.children.forEach((item: Tab, index: number) => { + const editor = item.model as Editor; + if (item.id === tab.id) { + midIndex = index; + } + if (midIndex === -1) { + leftTabs.push(item); + } else if (index > midIndex) { + rightTabs.push(item); + } + }); + if (matchHotKey(window.siyuan.config.keymap.general.closeLeft.custom, event)) { + if (leftTabs.length > 0) { + closeTabByType(tab, "other", leftTabs); + } + } else { + if (rightTabs.length > 0) { + closeTabByType(tab, "other", rightTabs); + } + } + } + event.preventDefault(); return; } @@ -1372,21 +1486,18 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { matchHotKey(window.siyuan.config.keymap.general.splitTB.custom, event) || matchHotKey(window.siyuan.config.keymap.general.splitMoveB.custom, event)) && !event.repeat) { event.preventDefault(); - const activeTabElement = document.querySelector(".layout__wnd--active .item--focus"); - if (activeTabElement) { - const tab = getInstanceById(activeTabElement.getAttribute("data-id")) as Tab; - if (tab) { - if (matchHotKey(window.siyuan.config.keymap.general.splitLR.custom, event)) { - tab.parent.split("lr").addTab(copyTab(app, tab)); - } else if (matchHotKey(window.siyuan.config.keymap.general.splitTB.custom, event)) { - tab.parent.split("tb").addTab(copyTab(app, tab)); - } else if (tab.parent.children.length > 1) { - const newWnd = tab.parent.split(matchHotKey(window.siyuan.config.keymap.general.splitMoveB.custom, event) ? "tb" : "lr"); - newWnd.headersElement.append(tab.headElement); - newWnd.headersElement.parentElement.classList.remove("fn__none"); - newWnd.moveTab(tab); - resizeTabs(); - } + const tab = getActiveTab(false); + if (tab) { + if (matchHotKey(window.siyuan.config.keymap.general.splitLR.custom, event)) { + tab.parent.split("lr").addTab(copyTab(app, tab)); + } else if (matchHotKey(window.siyuan.config.keymap.general.splitTB.custom, event)) { + tab.parent.split("tb").addTab(copyTab(app, tab)); + } else if (tab.parent.children.length > 1) { + const newWnd = tab.parent.split(matchHotKey(window.siyuan.config.keymap.general.splitMoveB.custom, event) ? "tb" : "lr"); + newWnd.headersElement.append(tab.headElement); + newWnd.headersElement.parentElement.classList.remove("fn__none"); + newWnd.moveTab(tab); + resizeTabs(); } } return; diff --git a/app/src/boot/globalEvent/keyup.ts b/app/src/boot/globalEvent/keyup.ts index ad51fe448..3bf74b198 100644 --- a/app/src/boot/globalEvent/keyup.ts +++ b/app/src/boot/globalEvent/keyup.ts @@ -1,7 +1,7 @@ import {fetchPost} from "../../util/fetch"; import {escapeHtml} from "../../util/escape"; import {openCard} from "../../card/openCard"; -import {getDockByType} from "../../layout/util"; +import {getDockByType} from "../../layout/tabUtil"; import {getAllTabs} from "../../layout/getAll"; import {App} from "../../index"; diff --git a/app/src/boot/onGetConfig.ts b/app/src/boot/onGetConfig.ts index e96405980..aa00aea6b 100644 --- a/app/src/boot/onGetConfig.ts +++ b/app/src/boot/onGetConfig.ts @@ -1,4 +1,5 @@ -import {exportLayout, JSONToLayout, resetLayout, resizeTopbar, resizeTabs} from "../layout/util"; +import {exportLayout, JSONToLayout, resetLayout, resizeTopBar} from "../layout/util"; +import {resizeTabs} from "../layout/tabUtil"; import {setStorageVal} from "../protyle/util/compatibility"; /// #if !BROWSER import {ipcRenderer, webFrame} from "electron"; @@ -146,7 +147,7 @@ export const onGetConfig = (isStart: boolean, app: App) => { window.clearTimeout(resizeTimeout); resizeTimeout = window.setTimeout(() => { resizeTabs(); - resizeTopbar(); + resizeTopBar(); }, 200); }); addGA(); diff --git a/app/src/config/keymap.ts b/app/src/config/keymap.ts index 91334dfd6..65ea63be4 100644 --- a/app/src/config/keymap.ts +++ b/app/src/config/keymap.ts @@ -382,7 +382,7 @@ export const keymap = { } let hasConflict = false; if (["⌘", "⇧", "⌥", "⌃"].includes(keymapStr.substr(keymapStr.length - 1, 1)) || - ["⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⇧⌘⇥", "⌃⇥", "⌘⇥", "⌃⌘⇥", "⇧⌘→", "⇧⌘←", "⌘Home", "⌘End", "⇧↩", "↩", "PageUp", "PageDown", "⌫", "⌦"].includes(keymapStr)) { + ["⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⌃⇧⇥", "⌃⇥", "⌘⇥", "⇧⌘⇥", "⇧⌘→", "⇧⌘←", "⌘Home", "⌘End", "⇧↩", "↩", "PageUp", "PageDown", "⌫", "⌦"].includes(keymapStr)) { showMessage(`${window.siyuan.languages.invalid} [${adoptKeymapStr}]`); hasConflict = true; } diff --git a/app/src/constants.ts b/app/src/constants.ts index eb53abb91..a1da7042a 100644 --- a/app/src/constants.ts +++ b/app/src/constants.ts @@ -221,7 +221,7 @@ export abstract class Constants { }; // 冲突不使用 "⌘S/Q" // "⌘", "⇧", "⌥", "⌃" - // "⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⇧⌘⇥", "⌃⇥", "⌘⇥", "⌃⌘⇥", "⇧⌘→", "⇧⌘←", + // "⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⌃⇧⇥", "⌃⇥", "⌘⇥", "⇧⌘⇥", "⇧⌘→", "⇧⌘←", // "⌘Home", "⌘End", "⇧↩", "↩", "PageUp", "PageDown", "⌫", "⌦" 不可自定义 public static readonly SIYUAN_KEYMAP: IKeymap = { general: { @@ -254,6 +254,17 @@ export abstract class Constants { toggleWin: {default: "⌥M", custom: "⌥M"}, lockScreen: {default: "⌥N", custom: "⌥N"}, recentDocs: {default: "⌘E", custom: "⌘E"}, + goToTab1: {default: "⌘1", custom: "⌘1"}, + goToTab2: {default: "⌘2", custom: "⌘2"}, + goToTab3: {default: "⌘3", custom: "⌘3"}, + goToTab4: {default: "⌘4", custom: "⌘4"}, + goToTab5: {default: "⌘5", custom: "⌘5"}, + goToTab6: {default: "⌘6", custom: "⌘6"}, + goToTab7: {default: "⌘7", custom: "⌘7"}, + goToTab8: {default: "⌘8", custom: "⌘8"}, + goToTab9: {default: "⌘9", custom: "⌘9"}, + goToTabNext: {default: "⇧⌘]", custom: "⇧⌘]"}, + goToTabPrev: {default: "⇧⌘[", custom: "⇧⌘["}, move: {default: "", custom: ""}, selectOpen1: {default: "", custom: ""}, toggleDock: {default: "", custom: ""}, @@ -261,6 +272,11 @@ export abstract class Constants { splitMoveR: {default: "", custom: ""}, splitTB: {default: "", custom: ""}, splitMoveB: {default: "", custom: ""}, + closeOthers: {default: "", custom: ""}, + closeAll: {default: "", custom: ""}, + closeUnmodified: {default: "", custom: ""}, + closeLeft: {default: "", custom: ""}, + closeRight: {default: "", custom: ""}, }, editor: { general: { diff --git a/app/src/editor/util.ts b/app/src/editor/util.ts index 9ff8c385c..b706c7b00 100644 --- a/app/src/editor/util.ts +++ b/app/src/editor/util.ts @@ -1,7 +1,8 @@ import {Tab} from "../layout/Tab"; import {Editor} from "./index"; import {Wnd} from "../layout/Wnd"; -import {getDockByType, getInstanceById, getWndByLayout, pdfIsLoading, setPanelFocus} from "../layout/util"; +import {getInstanceById, getWndByLayout, pdfIsLoading, setPanelFocus} from "../layout/util"; +import {getDockByType} from "../layout/tabUtil"; import {getAllModels, getAllTabs} from "../layout/getAll"; import {highlightById, scrollCenter} from "../util/highlightById"; import {getDisplayName, pathPosix, showFileInFolder} from "../util/pathName"; diff --git a/app/src/emoji/index.ts b/app/src/emoji/index.ts index 607ad237f..711d21fdb 100644 --- a/app/src/emoji/index.ts +++ b/app/src/emoji/index.ts @@ -4,7 +4,7 @@ import {hasClosestByClassName} from "../protyle/util/hasClosest"; import {Constants} from "../constants"; import {Files} from "../layout/dock/Files"; /// #if !MOBILE -import {getDockByType} from "../layout/util"; +import {getDockByType} from "../layout/tabUtil"; import {getAllModels} from "../layout/getAll"; /// #endif import {setNoteBook} from "../util/pathName"; diff --git a/app/src/layout/Wnd.ts b/app/src/layout/Wnd.ts index a90379439..62f34cb57 100644 --- a/app/src/layout/Wnd.ts +++ b/app/src/layout/Wnd.ts @@ -3,8 +3,7 @@ import {genUUID} from "../util/genID"; import { getInstanceById, getWndByLayout, JSONToCenter, - newCenterEmptyTab, newModelByInitData, pdfIsLoading, - resizeTabs, + newModelByInitData, pdfIsLoading, setPanelFocus, switchWnd } from "./util"; @@ -37,6 +36,7 @@ import {App} from "../index"; import {unicode2Emoji} from "../emoji"; import {closeWindow} from "../window/closeWin"; import {setTitle} from "../dialog/processSystem"; +import {newCenterEmptyTab, resizeTabs} from "./tabUtil"; export class Wnd { private app: App; @@ -745,6 +745,7 @@ export class Wnd { }); if (latestHeadElement && !closeAll) { this.switchTab(latestHeadElement, true, true, false); + this.showHeading(); } } if (animate) { diff --git a/app/src/layout/dock/Backlink.ts b/app/src/layout/dock/Backlink.ts index 5a9d6bf44..93dfd0703 100644 --- a/app/src/layout/dock/Backlink.ts +++ b/app/src/layout/dock/Backlink.ts @@ -1,7 +1,8 @@ import {Tab} from "../Tab"; import {Model} from "../Model"; import {Tree} from "../../util/Tree"; -import {getDockByType, setPanelFocus} from "../util"; +import {setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; import {fetchPost} from "../../util/fetch"; import {Constants} from "../../constants"; import {updateHotkeyTip} from "../../protyle/util/compatibility"; diff --git a/app/src/layout/dock/Bookmark.ts b/app/src/layout/dock/Bookmark.ts index 1fdb8e311..df7e2d48f 100644 --- a/app/src/layout/dock/Bookmark.ts +++ b/app/src/layout/dock/Bookmark.ts @@ -1,7 +1,8 @@ import {Tab} from "../Tab"; import {Model} from "../Model"; import {Tree} from "../../util/Tree"; -import {getDockByType, setPanelFocus} from "../util"; +import {setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; import {fetchPost} from "../../util/fetch"; import {updateHotkeyTip} from "../../protyle/util/compatibility"; import {openFileById} from "../../editor/util"; diff --git a/app/src/layout/dock/Files.ts b/app/src/layout/dock/Files.ts index 437ce2b1d..b6684ba43 100644 --- a/app/src/layout/dock/Files.ts +++ b/app/src/layout/dock/Files.ts @@ -1,7 +1,8 @@ import {escapeHtml} from "../../util/escape"; import {Tab} from "../Tab"; import {Model} from "../Model"; -import {getDockByType, getInstanceById, setPanelFocus} from "../util"; +import {getInstanceById, setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; import {Constants} from "../../constants"; import {getDisplayName, pathPosix, setNoteBook} from "../../util/pathName"; import {newFile} from "../../util/newFile"; diff --git a/app/src/layout/dock/Graph.ts b/app/src/layout/dock/Graph.ts index 708ee3ce3..9d483e328 100644 --- a/app/src/layout/dock/Graph.ts +++ b/app/src/layout/dock/Graph.ts @@ -1,5 +1,6 @@ import {Tab} from "../Tab"; -import {getDockByType, setPanelFocus} from "../util"; +import {setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; import {Model} from "../Model"; import {Constants} from "../../constants"; import {addScript} from "../../protyle/util/addScript"; diff --git a/app/src/layout/dock/Inbox.ts b/app/src/layout/dock/Inbox.ts index 4780b1538..a70c28b93 100644 --- a/app/src/layout/dock/Inbox.ts +++ b/app/src/layout/dock/Inbox.ts @@ -1,6 +1,7 @@ /// #if !MOBILE import {Tab} from "../Tab"; -import {getDockByType, setPanelFocus} from "../util"; +import {setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; /// #endif import {fetchPost} from "../../util/fetch"; import {updateHotkeyTip} from "../../protyle/util/compatibility"; diff --git a/app/src/layout/dock/Outline.ts b/app/src/layout/dock/Outline.ts index 73ad67e5a..f508d9c69 100644 --- a/app/src/layout/dock/Outline.ts +++ b/app/src/layout/dock/Outline.ts @@ -1,7 +1,8 @@ import {Tab} from "../Tab"; import {Model} from "../Model"; import {Tree} from "../../util/Tree"; -import {getDockByType, getInstanceById, setPanelFocus} from "../util"; +import {getInstanceById, setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; import {fetchPost} from "../../util/fetch"; import {getAllModels} from "../getAll"; import {hasClosestBlock, hasClosestByClassName, hasTopClosestByClassName} from "../../protyle/util/hasClosest"; diff --git a/app/src/layout/dock/Tag.ts b/app/src/layout/dock/Tag.ts index 2c276d856..2595e13fe 100644 --- a/app/src/layout/dock/Tag.ts +++ b/app/src/layout/dock/Tag.ts @@ -1,7 +1,8 @@ import {Tab} from "../Tab"; import {Model} from "../Model"; import {Tree} from "../../util/Tree"; -import {getDockByType, setPanelFocus} from "../util"; +import {setPanelFocus} from "../util"; +import {getDockByType} from "../tabUtil"; import {fetchPost} from "../../util/fetch"; import {updateHotkeyTip} from "../../protyle/util/compatibility"; import {openGlobalSearch} from "../../search/util"; diff --git a/app/src/layout/dock/index.ts b/app/src/layout/dock/index.ts index ee095ac75..a9e728ae1 100644 --- a/app/src/layout/dock/index.ts +++ b/app/src/layout/dock/index.ts @@ -9,7 +9,8 @@ import {Bookmark} from "./Bookmark"; import {Tag} from "./Tag"; import {Graph} from "./Graph"; import {Model} from "../Model"; -import {getDockByType, resizeTabs, setPanelFocus} from "../util"; +import {setPanelFocus} from "../util"; +import {getDockByType, resizeTabs} from "../tabUtil"; import {Inbox} from "./Inbox"; import {Protyle} from "../../protyle"; import {Backlink} from "./Backlink"; diff --git a/app/src/layout/dock/util.ts b/app/src/layout/dock/util.ts index 4acdb7bd2..f0a5cceee 100644 --- a/app/src/layout/dock/util.ts +++ b/app/src/layout/dock/util.ts @@ -2,7 +2,8 @@ import {getAllModels} from "../getAll"; import {Tab} from "../Tab"; import {Graph} from "./Graph"; import {Outline} from "./Outline"; -import {getInstanceById, getWndByLayout, resizeTabs, switchWnd} from "../util"; +import {getInstanceById, getWndByLayout, switchWnd} from "../util"; +import {resizeTabs} from "../tabUtil"; import {Backlink} from "./Backlink"; import {App} from "../../index"; import {Wnd} from "../Wnd"; diff --git a/app/src/layout/index.ts b/app/src/layout/index.ts index 46013d64e..62f69764c 100644 --- a/app/src/layout/index.ts +++ b/app/src/layout/index.ts @@ -1,6 +1,7 @@ import {Wnd} from "./Wnd"; import {genUUID} from "../util/genID"; -import {addResize, resizeTabs} from "./util"; +import {addResize} from "./util"; +import {resizeTabs} from "./tabUtil"; /// #if MOBILE // 检测移动端是否引入了桌面端的代码 console.error("Need remove unused code"); diff --git a/app/src/layout/status.ts b/app/src/layout/status.ts index 951016fe0..b224c2ffe 100644 --- a/app/src/layout/status.ts +++ b/app/src/layout/status.ts @@ -1,5 +1,5 @@ /// #if !MOBILE -import {getDockByType} from "./util"; +import {getDockByType} from "./tabUtil"; import {hasClosestByClassName} from "../protyle/util/hasClosest"; import {fetchPost} from "../util/fetch"; import {mountHelp} from "../util/mount"; diff --git a/app/src/layout/tabUtil.ts b/app/src/layout/tabUtil.ts new file mode 100644 index 000000000..7ad9104da --- /dev/null +++ b/app/src/layout/tabUtil.ts @@ -0,0 +1,364 @@ +import {Tab} from "./Tab"; +import {getInstanceById, newModelByInitData} from "./util"; +import {getAllModels, getAllTabs} from "./getAll"; +import {hideAllElements, hideElements} from "../protyle/ui/hideElements"; +import {pdfResize} from "../asset/renderAssets"; +import {App} from "../index"; +import {Model} from "./Model"; +import {Editor} from "../editor"; +import {saveScroll} from "../protyle/scroll/saveScroll"; +import {Asset} from "../asset"; +import {Graph} from "./dock/Graph"; +import {Files} from "./dock/Files"; +import {Outline} from "./dock/Outline"; +import {Backlink} from "./dock/Backlink"; +import {Bookmark} from "./dock/Bookmark"; +import {Tag} from "./dock/Tag"; +import {Search} from "../search"; +import {Custom} from "./dock/Custom"; +import {newCardModel} from "../card/newCardTab"; +import {updateHotkeyTip} from "../protyle/util/compatibility"; +import {openSearch} from "../search/spread"; +import {openRecentDocs} from "../business/openRecentDocs"; +import {openHistory} from "../history/history"; +import {newFile} from "../util/newFile"; +import {mountHelp, newNotebook} from "../util/mount"; + +export const getActiveTab = (wndActive = true) => { + const activeTabElement = document.querySelector(".layout__wnd--active .item--focus"); + let tab; + if (activeTabElement) { + tab = getInstanceById(activeTabElement.getAttribute("data-id")) as Tab; + } + if (!tab && !wndActive) { + getAllTabs().find(item => { + if (item.headElement?.classList.contains("item--focus")) { + tab = item; + } + }); + } + return tab; +}; + +export const switchTabByIndex = (index: number) => { + const activeDockIcoElement = document.querySelector(".dock .dock__item--activefocus"); + if (activeDockIcoElement) { + let indexElement = activeDockIcoElement.parentElement.children[index] + if (index === -1) { + // 最后一个 + indexElement = activeDockIcoElement.parentElement.lastElementChild + if (!indexElement.getAttribute("data-type")) { + indexElement = indexElement.previousElementSibling + } + } else if (index === -2) { + // 上一个 + indexElement = activeDockIcoElement.previousElementSibling + } else if (index === -3) { + // 下一个 + indexElement = activeDockIcoElement.nextElementSibling + } + const type = indexElement?.getAttribute("data-type") + if (type) { + getDockByType(type)?.toggleModel(type, true, false); + } + return; + } + const tab = getActiveTab(false); + if (tab) { + let indexElement = tab.parent.headersElement.children[index] + if (index === -1) { + // 最后一个 + indexElement = tab.parent.headersElement.lastElementChild + } else if (index === -2) { + // 上一个 + indexElement = tab.headElement.previousElementSibling + } else if (index === -3) { + // 下一个 + indexElement = tab.headElement.nextElementSibling + } + if (indexElement) { + tab.parent.switchTab(indexElement as HTMLElement, true); + tab.parent.showHeading(); + } + } +} + +let resizeTimeout: number; +export const resizeTabs = () => { + clearTimeout(resizeTimeout); + // .layout .fn__flex-shrink {width .15s cubic-bezier(0, 0, .2, 1) 0ms} 时需要再次计算 padding + // PDF 避免分屏多次调用后,页码跳转到1 https://github.com/siyuan-note/siyuan/issues/5646 + resizeTimeout = window.setTimeout(() => { + const models = getAllModels(); + models.editor.forEach((item) => { + if (item.editor && item.editor.protyle && + item.element.parentElement && !item.element.classList.contains("fn__none")) { + item.editor.resize(); + } + }); + // https://github.com/siyuan-note/siyuan/issues/6250 + models.backlink.forEach(item => { + const mTreeElement = item.element.querySelector(".backlinkMList") as HTMLElement; + if (mTreeElement.style.height && mTreeElement.style.height !== "0px" && item.element.clientHeight !== 0) { + mTreeElement.style.height = (item.element.clientHeight - mTreeElement.previousElementSibling.clientHeight * 2) + "px"; + } + item.editors.forEach(editorItem => { + hideElements(["gutter"], editorItem.protyle); + editorItem.resize(); + }); + }); + models.search.forEach(item => { + item.edit.resize(); + }); + models.custom.forEach(item => { + if (item.resize) { + item.resize(); + } + }); + pdfResize(); + hideAllElements(["gutter"]); + }, 200); +}; + +export const getDockByType = (type: string) => { + if (!window.siyuan.layout.leftDock) { + return undefined; + } + if (window.siyuan.layout.leftDock.data[type]) { + return window.siyuan.layout.leftDock; + } + if (window.siyuan.layout.rightDock.data[type]) { + return window.siyuan.layout.rightDock; + } + if (window.siyuan.layout.bottomDock.data[type]) { + return window.siyuan.layout.bottomDock; + } +}; + +export const newCenterEmptyTab = (app: App) => { + return new Tab({ + panel: `
+
+ +
${window.siyuan.languages.slogan}
+
+
+
+ + ${window.siyuan.languages.search} + ${updateHotkeyTip(window.siyuan.config.keymap.general.globalSearch.custom)} +
+
+ + ${window.siyuan.languages.recentDocs} + ${updateHotkeyTip(window.siyuan.config.keymap.general.recentDocs.custom)} +
+
+ + ${window.siyuan.languages.dataHistory} + ${updateHotkeyTip(window.siyuan.config.keymap.general.dataHistory.custom)} +
+
+ + ${window.siyuan.languages.newFile} + ${updateHotkeyTip(window.siyuan.config.keymap.general.newFile.custom)} +
+
+ + ${window.siyuan.languages.newNotebook} +
+
+ + ${window.siyuan.languages.help} +
+
`, + callback(tab: Tab) { + tab.panelElement.addEventListener("click", (event) => { + let target = event.target as HTMLElement; + while (target && !target.isEqualNode(tab.panelElement)) { + if (target.id === "editorEmptySearch") { + openSearch({ + app, + hotkey: window.siyuan.config.keymap.general.globalSearch.custom, + }); + event.stopPropagation(); + event.preventDefault(); + break; + } else if (target.id === "editorEmptyRecent") { + const openRecentDocsDialog = window.siyuan.dialogs.find(item => { + if (item.element.getAttribute("data-key") === window.siyuan.config.keymap.general.recentDocs.custom) { + return true; + } + }); + if (openRecentDocsDialog) { + hideElements(["dialog"]); + return; + } + openRecentDocs(); + event.stopPropagation(); + event.preventDefault(); + break; + } else if (target.id === "editorEmptyHistory") { + openHistory(app); + event.stopPropagation(); + event.preventDefault(); + break; + } else if (target.id === "editorEmptyFile") { + newFile({ + app, + useSavePath: true + }); + event.stopPropagation(); + event.preventDefault(); + break; + } else if (target.id === "editorEmptyNewNotebook") { + newNotebook(); + event.stopPropagation(); + event.preventDefault(); + break; + } else if (target.id === "editorEmptyHelp") { + mountHelp(); + event.stopPropagation(); + event.preventDefault(); + break; + } + target = target.parentElement; + } + }); + } + }); +}; + +export const copyTab = (app: App, tab: Tab) => { + return new Tab({ + icon: tab.icon, + docIcon: tab.docIcon, + title: tab.title, + callback(newTab: Tab) { + let model: Model; + if (tab.model instanceof Editor) { + model = new Editor({ + app, + tab: newTab, + blockId: tab.model.editor.protyle.block.id, + scrollAttr: saveScroll(tab.model.editor.protyle, true) + }); + } else if (tab.model instanceof Asset) { + model = new Asset({ + app, + tab: newTab, + path: tab.model.path + }); + } else if (tab.model instanceof Graph) { + model = new Graph({ + app, + tab: newTab, + blockId: tab.model.blockId, + rootId: tab.model.rootId, + type: tab.model.type, + }); + } else if (tab.model instanceof Files) { + model = new Files({ + app, + tab: newTab + }); + } else if (tab.model instanceof Outline) { + model = new Outline({ + app, + tab: newTab, + blockId: tab.model.blockId, + type: tab.model.type, + isPreview: tab.model.isPreview + }); + } else if (tab.model instanceof Backlink) { + model = new Backlink({ + app, + tab: newTab, + blockId: tab.model.blockId, + rootId: tab.model.rootId, + type: tab.model.type + }); + } else if (tab.model instanceof Bookmark) { + model = new Bookmark(app, newTab); + } else if (tab.model instanceof Tag) { + model = new Tag(app, newTab); + } else if (tab.model instanceof Search) { + model = new Search({ + app, + tab: newTab, + config: tab.model.config + }); + } else if (tab.model instanceof Custom) { + const custom = tab.model as Custom; + if (custom.type === "siyuan-card") { + model = newCardModel({ + app, + tab: newTab, + data: custom.data + }); + } else { + app.plugins.find(item => { + if (item.models[custom.type]) { + model = item.models[custom.type]({ + tab: newTab, + data: custom.data + }); + return true; + } + }); + } + } else if (!tab.model && tab.headElement) { + const initData = JSON.parse(tab.headElement.getAttribute("data-initdata") || "{}"); + if (initData) { + // 历史数据兼容 2023-05-24 + if (initData.scrollAttr) { + initData.scrollAttr.rootId = initData.rootId; + } + model = newModelByInitData(app, newTab, initData); + } + } + newTab.addModel(model); + } + }); +}; + +export const closeTabByType = async (tab: Tab, type: "closeOthers" | "closeAll" | "other", tabs?: Tab[]) => { + if (type === "closeOthers") { + for (let index = 0; index < tab.parent.children.length; index++) { + if (tab.parent.children[index].id !== tab.id && !tab.parent.children[index].headElement.classList.contains("item--pin")) { + tab.parent.children[index].parent.removeTab(tab.parent.children[index].id, true, true, false); + } + } + if (!tab.headElement.parentElement.querySelector(".item--focus")) { + tab.parent.switchTab(tab.headElement, true); + } + return + } + if (type === "closeAll") { + for (let index = 0; index < tab.parent.children.length; index++) { + if (!tab.parent.children[index].headElement.classList.contains("item--pin")) { + await tab.parent.children[index].parent.removeTab(tab.parent.children[index].id, true); + } + } + if (tab.parent.children[0].headElement.parentElement) { + tab.parent.children[0].parent.switchTab(tab.parent.children[0].headElement, true); + } + return; + } + if (tabs.length > 0) { + for (let index = 0; index < tabs.length; index++) { + if (!tabs[index].headElement.classList.contains("item--pin")) { + await tabs[index].parent.removeTab(tabs[index].id); + } + } + if (tab.headElement.parentElement && !tab.headElement.parentElement.querySelector(".item--focus")) { + tab.parent.switchTab(tab.headElement, true); + } else if (tab.parent.children[0].headElement.parentElement) { + tab.parent.children[0].parent.switchTab(tab.parent.children[0].headElement, true); + } + return; + } +} diff --git a/app/src/layout/util.ts b/app/src/layout/util.ts index e10d9e384..3059fb1f7 100644 --- a/app/src/layout/util.ts +++ b/app/src/layout/util.ts @@ -1,29 +1,24 @@ import {Layout} from "./index"; import {Wnd} from "./Wnd"; -import {mountHelp, newNotebook} from "../util/mount"; import {Tab} from "./Tab"; import {Model} from "./Model"; import {Graph} from "./dock/Graph"; import {Editor} from "../editor"; import {Files} from "./dock/Files"; -import {newFile} from "../util/newFile"; import {Outline} from "./dock/Outline"; import {Bookmark} from "./dock/Bookmark"; -import {updateHotkeyTip} from "../protyle/util/compatibility"; import {Tag} from "./dock/Tag"; import {getAllModels, getAllTabs} from "./getAll"; import {Asset} from "../asset"; import {Search} from "../search"; import {Dock} from "./dock"; import {focusByOffset, focusByRange, getSelectionOffset} from "../protyle/util/selection"; -import {hideAllElements, hideElements} from "../protyle/ui/hideElements"; +import {hideElements} from "../protyle/ui/hideElements"; import {fetchPost} from "../util/fetch"; import {hasClosestBlock, hasClosestByClassName} from "../protyle/util/hasClosest"; import {getContenteditableElement} from "../protyle/wysiwyg/getBlock"; import {Constants} from "../constants"; -import {openSearch} from "../search/spread"; import {saveScroll} from "../protyle/scroll/saveScroll"; -import {pdfResize} from "../asset/renderAssets"; import {Backlink} from "./dock/Backlink"; import {openFileById} from "../editor/util"; import {isWindow} from "../util/functions"; @@ -32,13 +27,12 @@ import {setTabPosition} from "../window/setHeader"; /// #endif import {showMessage} from "../dialog/message"; import {getIdZoomInByPath} from "../util/pathName"; -import {openHistory} from "../history/history"; import {Custom} from "./dock/Custom"; import {newCardModel} from "../card/newCardTab"; -import {openRecentDocs} from "../business/openRecentDocs"; import {App} from "../index"; import {afterLoadPlugin} from "../plugin/loader"; import {setTitle} from "../dialog/processSystem"; +import {newCenterEmptyTab, resizeTabs} from "./tabUtil"; export const setPanelFocus = (element: Element) => { if (element.getAttribute("data-type") === "wnd") { @@ -76,21 +70,6 @@ export const setPanelFocus = (element: Element) => { } }; -export const getDockByType = (type: string) => { - if (!window.siyuan.layout.leftDock) { - return undefined; - } - if (window.siyuan.layout.leftDock.data[type]) { - return window.siyuan.layout.leftDock; - } - if (window.siyuan.layout.rightDock.data[type]) { - return window.siyuan.layout.rightDock; - } - if (window.siyuan.layout.bottomDock.data[type]) { - return window.siyuan.layout.bottomDock; - } -}; - export const switchWnd = (newWnd: Wnd, targetWnd: Wnd) => { // DOM 移动后 range 会变化 const rangeDatas: { @@ -449,7 +428,7 @@ export const JSONToLayout = (app: App, isStart: boolean) => { tab.parent.switchTab(item, false, false); }); } - resizeTopbar(); + resizeTopBar(); }; export const layoutToJSON = (layout: Layout | Wnd | Tab | Model, json: any, dropEditScroll = false) => { @@ -587,7 +566,7 @@ export const layoutToJSON = (layout: Layout | Wnd | Tab | Model, json: any, drop } }; -export const resizeTopbar = () => { +export const resizeTopBar = () => { const toolbarElement = document.querySelector("#toolbar"); if (!toolbarElement) { return; @@ -647,136 +626,6 @@ export const resizeTopbar = () => { }); }; -let resizeTimeout: number; -export const resizeTabs = () => { - clearTimeout(resizeTimeout); - // .layout .fn__flex-shrink {width .15s cubic-bezier(0, 0, .2, 1) 0ms} 时需要再次计算 padding - // PDF 避免分屏多次调用后,页码跳转到1 https://github.com/siyuan-note/siyuan/issues/5646 - resizeTimeout = window.setTimeout(() => { - const models = getAllModels(); - models.editor.forEach((item) => { - if (item.editor && item.editor.protyle && - item.element.parentElement && !item.element.classList.contains("fn__none")) { - item.editor.resize(); - } - }); - // https://github.com/siyuan-note/siyuan/issues/6250 - models.backlink.forEach(item => { - const mTreeElement = item.element.querySelector(".backlinkMList") as HTMLElement; - if (mTreeElement.style.height && mTreeElement.style.height !== "0px" && item.element.clientHeight !== 0) { - mTreeElement.style.height = (item.element.clientHeight - mTreeElement.previousElementSibling.clientHeight * 2) + "px"; - } - item.editors.forEach(editorItem => { - hideElements(["gutter"], editorItem.protyle); - editorItem.resize(); - }); - }); - models.search.forEach(item => { - item.edit.resize(); - }); - models.custom.forEach(item => { - if (item.resize) { - item.resize(); - } - }); - pdfResize(); - hideAllElements(["gutter"]); - }, 200); -}; - -export const copyTab = (app: App, tab: Tab) => { - return new Tab({ - icon: tab.icon, - docIcon: tab.docIcon, - title: tab.title, - callback(newTab: Tab) { - let model: Model; - if (tab.model instanceof Editor) { - model = new Editor({ - app, - tab: newTab, - blockId: tab.model.editor.protyle.block.id, - scrollAttr: saveScroll(tab.model.editor.protyle, true) - }); - } else if (tab.model instanceof Asset) { - model = new Asset({ - app, - tab: newTab, - path: tab.model.path - }); - } else if (tab.model instanceof Graph) { - model = new Graph({ - app, - tab: newTab, - blockId: tab.model.blockId, - rootId: tab.model.rootId, - type: tab.model.type, - }); - } else if (tab.model instanceof Files) { - model = new Files({ - app, - tab: newTab - }); - } else if (tab.model instanceof Outline) { - model = new Outline({ - app, - tab: newTab, - blockId: tab.model.blockId, - type: tab.model.type, - isPreview: tab.model.isPreview - }); - } else if (tab.model instanceof Backlink) { - model = new Backlink({ - app, - tab: newTab, - blockId: tab.model.blockId, - rootId: tab.model.rootId, - type: tab.model.type - }); - } else if (tab.model instanceof Bookmark) { - model = new Bookmark(app, newTab); - } else if (tab.model instanceof Tag) { - model = new Tag(app, newTab); - } else if (tab.model instanceof Search) { - model = new Search({ - app, - tab: newTab, - config: tab.model.config - }); - } else if (tab.model instanceof Custom) { - const custom = tab.model as Custom; - if (custom.type === "siyuan-card") { - model = newCardModel({ - app, - tab: newTab, - data: custom.data - }); - } else { - app.plugins.find(item => { - if (item.models[custom.type]) { - model = item.models[custom.type]({ - tab: newTab, - data: custom.data - }); - return true; - } - }); - } - } else if (!tab.model && tab.headElement) { - const initData = JSON.parse(tab.headElement.getAttribute("data-initdata") || "{}"); - if (initData) { - // 历史数据兼容 2023-05-24 - if (initData.scrollAttr) { - initData.scrollAttr.rootId = initData.rootId; - } - model = newModelByInitData(app, newTab, initData); - } - } - newTab.addModel(model); - } - }); -}; - export const newModelByInitData = (app: App, tab: Tab, json: any) => { let model: Model; if (json.instance === "Custom") { @@ -959,100 +808,3 @@ export const addResize = (obj: Layout | Wnd) => { obj.element.insertAdjacentElement("beforebegin", resizeElement); resizeWnd(resizeElement, obj.resize); }; - -export const newCenterEmptyTab = (app: App) => { - return new Tab({ - panel: `
-
- -
${window.siyuan.languages.slogan}
-
-
-
- - ${window.siyuan.languages.search} - ${updateHotkeyTip(window.siyuan.config.keymap.general.globalSearch.custom)} -
-
- - ${window.siyuan.languages.recentDocs} - ${updateHotkeyTip(window.siyuan.config.keymap.general.recentDocs.custom)} -
-
- - ${window.siyuan.languages.dataHistory} - ${updateHotkeyTip(window.siyuan.config.keymap.general.dataHistory.custom)} -
-
- - ${window.siyuan.languages.newFile} - ${updateHotkeyTip(window.siyuan.config.keymap.general.newFile.custom)} -
-
- - ${window.siyuan.languages.newNotebook} -
-
- - ${window.siyuan.languages.help} -
-
`, - callback(tab: Tab) { - tab.panelElement.addEventListener("click", (event) => { - let target = event.target as HTMLElement; - while (target && !target.isEqualNode(tab.panelElement)) { - if (target.id === "editorEmptySearch") { - openSearch({ - app, - hotkey: window.siyuan.config.keymap.general.globalSearch.custom, - }); - event.stopPropagation(); - event.preventDefault(); - break; - } else if (target.id === "editorEmptyRecent") { - const openRecentDocsDialog = window.siyuan.dialogs.find(item => { - if (item.element.getAttribute("data-key") === window.siyuan.config.keymap.general.recentDocs.custom) { - return true; - } - }); - if (openRecentDocsDialog) { - hideElements(["dialog"]); - return; - } - openRecentDocs(); - event.stopPropagation(); - event.preventDefault(); - break; - } else if (target.id === "editorEmptyHistory") { - openHistory(app); - event.stopPropagation(); - event.preventDefault(); - break; - } else if (target.id === "editorEmptyFile") { - newFile({ - app, - useSavePath: true - }); - event.stopPropagation(); - event.preventDefault(); - break; - } else if (target.id === "editorEmptyNewNotebook") { - newNotebook(); - event.stopPropagation(); - event.preventDefault(); - break; - } else if (target.id === "editorEmptyHelp") { - mountHelp(); - event.stopPropagation(); - event.preventDefault(); - break; - } - target = target.parentElement; - } - }); - } - }); -}; diff --git a/app/src/menus/navigation.ts b/app/src/menus/navigation.ts index 157f46964..97068f838 100644 --- a/app/src/menus/navigation.ts +++ b/app/src/menus/navigation.ts @@ -18,7 +18,7 @@ import {Constants} from "../constants"; import {newFile} from "../util/newFile"; import {hasClosestByTag} from "../protyle/util/hasClosest"; import {deleteFiles} from "../editor/deleteFile"; -import {getDockByType} from "../layout/util"; +import {getDockByType} from "../layout/tabUtil"; import {Files} from "../layout/dock/Files"; import {openCardByData} from "../card/openCard"; import {viewCards} from "../card/viewCards"; diff --git a/app/src/menus/tab.ts b/app/src/menus/tab.ts index 35b35d62a..bee2f2d0b 100644 --- a/app/src/menus/tab.ts +++ b/app/src/menus/tab.ts @@ -1,7 +1,7 @@ import {Tab} from "../layout/Tab"; import {MenuItem} from "./Menu"; import {Editor} from "../editor"; -import {copyTab, resizeTabs} from "../layout/util"; +import {closeTabByType, copyTab, resizeTabs} from "../layout/tabUtil"; /// #if !BROWSER import {openNewWindow} from "../window/openNewWindow"; /// #endif @@ -9,7 +9,6 @@ import {copySubMenu} from "./commonMenuItem"; import {App} from "../index"; const closeMenu = (tab: Tab) => { - const allTabs: Tab[] = []; const unmodifiedTabs: Tab[] = []; const leftTabs: Tab[] = []; const rightTabs: Tab[] = []; @@ -27,7 +26,6 @@ const closeMenu = (tab: Tab) => { } else if (index > midIndex) { rightTabs.push(item); } - allTabs.push(item); }); window.siyuan.menus.menu.append(new MenuItem({ @@ -38,77 +36,45 @@ const closeMenu = (tab: Tab) => { tab.parent.removeTab(tab.id); } }).element); - if (allTabs.length > 1) { + if (tab.parent.children.length > 1) { window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.closeOthers, + accelerator: window.siyuan.config.keymap.general.closeOthers.custom, click() { - for (let index = 0; index < allTabs.length; index++) { - if (allTabs[index].id !== tab.id && !allTabs[index].headElement.classList.contains("item--pin")) { - allTabs[index].parent.removeTab(allTabs[index].id, true, true, false); - } - } - if (!tab.headElement.parentElement.querySelector(".item--focus")) { - tab.parent.switchTab(tab.headElement, true); - } + closeTabByType(tab, "closeOthers"); } }).element); window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.closeAll, - click: async () => { - for (let index = 0; index < allTabs.length; index++) { - if (!allTabs[index].headElement.classList.contains("item--pin")) { - await allTabs[index].parent.removeTab(allTabs[index].id, true); - } - } - if (allTabs[0].headElement.parentElement) { - allTabs[0].parent.switchTab(allTabs[0].headElement, true); - } + accelerator: window.siyuan.config.keymap.general.closeAll.custom, + click() { + closeTabByType(tab, "closeAll"); } }).element); if (unmodifiedTabs.length > 0) { window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.closeUnmodified, - click: async () => { - for (let index = 0; index < unmodifiedTabs.length; index++) { - if (!unmodifiedTabs[index].headElement.classList.contains("item--pin")) { - await unmodifiedTabs[index].parent.removeTab(unmodifiedTabs[index].id); - } - } - if (tab.headElement.parentElement && !tab.headElement.parentElement.querySelector(".item--focus")) { - tab.parent.switchTab(tab.headElement, true); - } else if (allTabs[0].headElement.parentElement) { - allTabs[0].parent.switchTab(allTabs[0].headElement, true); - } + accelerator: window.siyuan.config.keymap.general.closeUnmodified.custom, + click() { + closeTabByType(tab, "other", unmodifiedTabs); } }).element); } if (leftTabs.length > 0) { window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.closeLeft, + accelerator: window.siyuan.config.keymap.general.closeLeft.custom, click: async () => { - for (let index = 0; index < leftTabs.length; index++) { - if (!leftTabs[index].headElement.classList.contains("item--pin")) { - await leftTabs[index].parent.removeTab(leftTabs[index].id); - } - } - if (!tab.headElement.parentElement.querySelector(".item--focus")) { - tab.parent.switchTab(tab.headElement, true); - } + closeTabByType(tab, "other", leftTabs); } }).element); } if (rightTabs.length > 0) { window.siyuan.menus.menu.append(new MenuItem({ label: window.siyuan.languages.closeRight, - click: async () => { - for (let index = 0; index < rightTabs.length; index++) { - if (!rightTabs[index].headElement.classList.contains("item--pin")) { - await rightTabs[index].parent.removeTab(rightTabs[index].id); - } - } - if (!tab.headElement.parentElement.querySelector(".item--focus")) { - tab.parent.switchTab(tab.headElement, true); - } + accelerator: window.siyuan.config.keymap.general.closeRight.custom, + click () { + closeTabByType(tab, "other", rightTabs); } }).element); } diff --git a/app/src/menus/workspace.ts b/app/src/menus/workspace.ts index 669b9dd5d..12dc0842c 100644 --- a/app/src/menus/workspace.ts +++ b/app/src/menus/workspace.ts @@ -11,7 +11,8 @@ import {isInAndroid, isInIOS, setStorageVal, writeText} from "../protyle/util/co import {openCard} from "../card/openCard"; import {openSetting} from "../config"; import {getAllDocks} from "../layout/getAll"; -import {exportLayout, getDockByType} from "../layout/util"; +import {exportLayout} from "../layout/util"; +import {getDockByType} from "../layout/tabUtil"; import {exitSiYuan, lockScreen} from "../dialog/processSystem"; import {showMessage} from "../dialog/message"; import {unicode2Emoji} from "../emoji"; diff --git a/app/src/plugin/index.ts b/app/src/plugin/index.ts index 80bdb4167..3a61a20ae 100644 --- a/app/src/plugin/index.ts +++ b/app/src/plugin/index.ts @@ -7,7 +7,8 @@ import {Custom} from "../layout/dock/Custom"; import {getAllModels} from "../layout/getAll"; /// #endif import {Tab} from "../layout/Tab"; -import {getDockByType, setPanelFocus} from "../layout/util"; +import {setPanelFocus} from "../layout/util"; +import {getDockByType} from "../layout/tabUtil"; import {hasClosestByAttribute} from "../protyle/util/hasClosest"; import {BlockPanel} from "../block/Panel"; import {Setting} from "./Setting"; diff --git a/app/src/plugin/loader.ts b/app/src/plugin/loader.ts index 05fe8ceaf..769090c63 100644 --- a/app/src/plugin/loader.ts +++ b/app/src/plugin/loader.ts @@ -2,7 +2,7 @@ import {fetchSyncPost} from "../util/fetch"; import {App} from "../index"; import {Plugin} from "./index"; /// #if !MOBILE -import {exportLayout, resizeTopbar} from "../layout/util"; +import {exportLayout, resizeTopBar} from "../layout/util"; /// #endif import {API} from "./API"; import {getFrontend, isMobile, isWindow} from "../util/functions"; @@ -187,7 +187,7 @@ export const afterLoadPlugin = (plugin: Plugin) => { } } /// #if !MOBILE - resizeTopbar(); + resizeTopBar(); mergePluginHotkey(plugin); plugin.statusBarIcons.forEach(element => { const statusElement = document.getElementById("status"); diff --git a/app/src/plugin/uninstall.ts b/app/src/plugin/uninstall.ts index f745d2bb6..e52a9fbd9 100644 --- a/app/src/plugin/uninstall.ts +++ b/app/src/plugin/uninstall.ts @@ -1,7 +1,7 @@ import {App} from "../index"; import {Plugin} from "../plugin"; import {getAllModels} from "../layout/getAll"; -import {exportLayout, resizeTopbar} from "../layout/util"; +import {exportLayout, resizeTopBar} from "../layout/util"; import {Constants} from "../constants"; export const uninstall = (app: App, name: string) => { @@ -24,7 +24,7 @@ export const uninstall = (app: App, name: string) => { plugin.topBarIcons.forEach(item => { item.remove(); }); - resizeTopbar(); + resizeTopBar(); // rm statusBar /// #if !MOBILE plugin.statusBarIcons.forEach(item => { diff --git a/app/src/util/newFile.ts b/app/src/util/newFile.ts index 32c0018d8..72c4a43da 100644 --- a/app/src/util/newFile.ts +++ b/app/src/util/newFile.ts @@ -1,7 +1,7 @@ import {showMessage} from "../dialog/message"; import {getAllModels} from "../layout/getAll"; import {hasClosestByClassName, hasTopClosestByTag} from "../protyle/util/hasClosest"; -import {getDockByType} from "../layout/util"; +import {getDockByType} from "../layout/tabUtil"; /// #if !MOBILE import {Files} from "../layout/dock/Files"; import {openFileById} from "../editor/util"; diff --git a/app/src/window/init.ts b/app/src/window/init.ts index 45a7e379a..36b12431c 100644 --- a/app/src/window/init.ts +++ b/app/src/window/init.ts @@ -1,7 +1,8 @@ import {Constants} from "../constants"; import {webFrame} from "electron"; import {fetchPost} from "../util/fetch"; -import {getInstanceById, JSONToCenter, resizeTabs} from "../layout/util"; +import {getInstanceById, JSONToCenter} from "../layout/util"; +import {resizeTabs} from "../layout/tabUtil"; import {initStatus} from "../layout/status"; import {appearance} from "../config/appearance"; import {initAssets, setInlineStyle} from "../util/assets";