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: `