diff --git a/app/src/layout/Wnd.ts b/app/src/layout/Wnd.ts index 64ec6de52..fc77baafc 100644 --- a/app/src/layout/Wnd.ts +++ b/app/src/layout/Wnd.ts @@ -12,7 +12,7 @@ import {Tab} from "./Tab"; import {Model} from "./Model"; import {Editor} from "../editor"; import {Graph} from "./dock/Graph"; -import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasClosest"; +import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasClosest"; import {Constants} from "../constants"; /// #if !BROWSER import {webFrame, ipcRenderer} from "electron"; @@ -32,6 +32,7 @@ import {MenuItem} from "../menus/Menu"; import {escapeHtml} from "../util/escape"; import {isWindow} from "../util/functions"; import {hideAllElements} from "../protyle/ui/hideElements"; +import {focusByOffset, getSelectionOffset, getSelectionPosition} from "../protyle/util/selection"; export class Wnd { public id: string; @@ -369,6 +370,7 @@ export class Wnd { switchWnd(newWnd, targetWnd); } } + resizeTabs(); /// #if !BROWSER setTabPosition(); /// #endif @@ -754,10 +756,29 @@ export class Wnd { } public moveTab(tab: Tab, nextId?: string) { + let rangeData: { + id: string, + start: number, + end: number + } + if (tab.model instanceof Editor && tab.model.editor.protyle.toolbar.range) { + const blockElement = hasClosestBlock(tab.model.editor.protyle.toolbar.range.startContainer); + if (blockElement) { + const startEnd = getSelectionOffset(blockElement, undefined, tab.model.editor.protyle.toolbar.range); + rangeData = { + id: blockElement.getAttribute("data-node-id"), + start: startEnd.start, + end: startEnd.end + } + } + } this.element.querySelector(".layout-tab-container").append(tab.panelElement); - if (tab.model instanceof Editor) { - // DOM 移动后 range 会变化,因此置空 - tab.model.editor.protyle.toolbar.range = null; + if (rangeData && tab.model instanceof Editor) { + // DOM 移动后 range 会变化 + const range = focusByOffset(tab.model.editor.protyle.wysiwyg.element.querySelector(`[data-node-id="${rangeData.id}"]`), rangeData.start, rangeData.end); + if (range) { + tab.model.editor.protyle.toolbar.range = range; + } } if (nextId) { // 只能用 find https://github.com/siyuan-note/siyuan/issues/3455 @@ -802,7 +823,6 @@ export class Wnd { } } tab.parent = this; - resizeTabs(); hideAllElements(["toolbar"]); } diff --git a/app/src/layout/util.ts b/app/src/layout/util.ts index c7b2d132d..3bbc5594c 100644 --- a/app/src/layout/util.ts +++ b/app/src/layout/util.ts @@ -16,7 +16,7 @@ import {getAllModels, getAllTabs} from "./getAll"; import {Asset} from "../asset"; import {Search} from "../search"; import {Dock} from "./dock"; -import {focusByRange} from "../protyle/util/selection"; +import {focusByOffset, focusByRange, getSelectionOffset} from "../protyle/util/selection"; import {hideAllElements, hideElements} from "../protyle/ui/hideElements"; import {fetchPost} from "../util/fetch"; import {hasClosestBlock, hasClosestByClassName} from "../protyle/util/hasClosest"; @@ -79,7 +79,35 @@ export const getDockByType = (type: TDockType) => { }; export const switchWnd = (newWnd: Wnd, targetWnd: Wnd) => { + // DOM 移动后 range 会变化 + const rangeDatas: { + id: string, + start: number, + end: number + }[] = []; + targetWnd.children.forEach((item) => { + if (item.model instanceof Editor && item.model.editor.protyle.toolbar.range) { + const blockElement = hasClosestBlock(item.model.editor.protyle.toolbar.range.startContainer); + if (blockElement) { + const startEnd = getSelectionOffset(blockElement, undefined, item.model.editor.protyle.toolbar.range); + rangeDatas.push({ + id: blockElement.getAttribute("data-node-id"), + start: startEnd.start, + end: startEnd.end + }) + } + } + }) newWnd.element.after(targetWnd.element); + targetWnd.children.forEach((item) => { + if (item.model instanceof Editor) { + const rangeData = rangeDatas.splice(0, 1)[0]; + const range = focusByOffset(item.model.editor.protyle.wysiwyg.element.querySelector(`[data-node-id="${rangeData.id}"]`), rangeData.start, rangeData.end); + if (range) { + item.model.editor.protyle.toolbar.range = range; + } + } + }) // 分割线 newWnd.element.after(newWnd.element.previousElementSibling); newWnd.parent.children.find((item, index) => { @@ -160,7 +188,7 @@ export const exportLayout = (reload: boolean, cb?: () => void, onlyData = false, } else if (cb) { cb(); } - return ; + return; } const useElement = document.querySelector("#barDock use"); if (!useElement) { diff --git a/app/src/menus/tab.ts b/app/src/menus/tab.ts index de11ccd9b..0e6fa6542 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} from "../layout/util"; +import {copyTab, resizeTabs} from "../layout/util"; /// #if !BROWSER import {openNewWindow} from "../window/openNewWindow"; /// #endif @@ -132,6 +132,7 @@ const splitSubMenu = (tab: Tab) => { newWnd.headersElement.append(tab.headElement); newWnd.headersElement.parentElement.classList.remove("fn__none"); newWnd.moveTab(tab); + resizeTabs(); } }); } @@ -152,6 +153,7 @@ const splitSubMenu = (tab: Tab) => { newWnd.headersElement.append(tab.headElement); newWnd.headersElement.parentElement.classList.remove("fn__none"); newWnd.moveTab(tab); + resizeTabs(); } }); }