2022-05-26 15:18:53 +08:00
|
|
|
|
import {Layout} from "./index";
|
|
|
|
|
|
import {genUUID} from "../util/genID";
|
|
|
|
|
|
import {
|
|
|
|
|
|
getInstanceById,
|
2023-01-27 18:09:34 +08:00
|
|
|
|
getWndByLayout, JSONToCenter,
|
2022-05-26 15:18:53 +08:00
|
|
|
|
newCenterEmptyTab,
|
|
|
|
|
|
resizeTabs,
|
|
|
|
|
|
setPanelFocus,
|
|
|
|
|
|
switchWnd
|
|
|
|
|
|
} from "./util";
|
|
|
|
|
|
import {Tab} from "./Tab";
|
|
|
|
|
|
import {Model} from "./Model";
|
|
|
|
|
|
import {Editor} from "../editor";
|
|
|
|
|
|
import {Graph} from "./dock/Graph";
|
|
|
|
|
|
import {hasClosestByAttribute, hasClosestByClassName, hasClosestByTag} from "../protyle/util/hasClosest";
|
|
|
|
|
|
import {Constants} from "../constants";
|
|
|
|
|
|
/// #if !BROWSER
|
2023-01-27 22:37:22 +08:00
|
|
|
|
import {webFrame, ipcRenderer} from "electron";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
import {getCurrentWindow} from "@electron/remote";
|
2023-01-27 10:27:14 +08:00
|
|
|
|
import {setTabPosition} from "../window/setHeader";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
/// #endif
|
|
|
|
|
|
import {Search} from "../search";
|
|
|
|
|
|
import {showMessage} from "../dialog/message";
|
|
|
|
|
|
import {openFileById, updatePanelByEditor} from "../editor/util";
|
|
|
|
|
|
import {scrollCenter} from "../util/highlightById";
|
2022-06-19 16:47:27 +08:00
|
|
|
|
import {getAllModels} from "./getAll";
|
2022-10-05 10:12:21 +08:00
|
|
|
|
import {clearCounter} from "./status";
|
2022-08-07 00:14:50 +08:00
|
|
|
|
import {saveScroll} from "../protyle/scroll/saveScroll";
|
2022-08-18 12:12:51 +08:00
|
|
|
|
import {Asset} from "../asset";
|
2022-09-04 21:51:18 +08:00
|
|
|
|
import {newFile} from "../util/newFile";
|
|
|
|
|
|
import {MenuItem} from "../menus/Menu";
|
2022-09-20 22:30:41 +08:00
|
|
|
|
import {escapeHtml} from "../util/escape";
|
2023-01-26 18:53:57 +08:00
|
|
|
|
import {isWindow} from "../util/functions";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
|
|
|
|
|
export class Wnd {
|
|
|
|
|
|
public id: string;
|
|
|
|
|
|
public parent?: Layout;
|
|
|
|
|
|
public element: HTMLElement;
|
|
|
|
|
|
public headersElement: HTMLElement;
|
|
|
|
|
|
public children: Tab[] = [];
|
|
|
|
|
|
public resize?: TDirection;
|
|
|
|
|
|
|
|
|
|
|
|
constructor(resize?: TDirection, parentType?: TLayout) {
|
|
|
|
|
|
this.id = genUUID();
|
|
|
|
|
|
this.resize = resize;
|
|
|
|
|
|
this.element = document.createElement("div");
|
|
|
|
|
|
this.element.classList.add("fn__flex-1", "fn__flex");
|
|
|
|
|
|
let dragHTML = '<div class="layout-tab-container__drag fn__none"></div>';
|
|
|
|
|
|
if (parentType === "left" || parentType === "right" || parentType === "top" || parentType === "bottom") {
|
|
|
|
|
|
dragHTML = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
this.element.innerHTML = `<div data-type="wnd" data-id="${this.id}" class="fn__flex-column fn__flex fn__flex-1">
|
2022-09-04 21:51:18 +08:00
|
|
|
|
<div class="fn__flex fn__none">
|
2022-10-19 17:49:56 +08:00
|
|
|
|
<ul class="fn__flex layout-tab-bar"></ul>
|
|
|
|
|
|
<ul class="layout-tab-bar layout-tab-bar--readonly fn__flex-1">
|
2022-09-04 21:51:18 +08:00
|
|
|
|
<li class="item item--readonly">
|
|
|
|
|
|
<span data-type="new" class="item__close" title="${window.siyuan.languages.newFile}"><svg style="height: 10px;width: 10px;padding: 3px"><use xlink:href="#iconAdd"></use></svg></span>
|
2022-10-19 17:49:56 +08:00
|
|
|
|
<span class="fn__flex-1"></span>
|
2022-09-04 21:51:18 +08:00
|
|
|
|
<span data-type="more" data-menu="true" class="item__close" title="${window.siyuan.languages.more}"><svg><use xlink:href="#iconDown"></use></svg></span>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</div>
|
2022-05-26 15:18:53 +08:00
|
|
|
|
<div class="layout-tab-container fn__flex-1">${dragHTML}</div>
|
|
|
|
|
|
</div>`;
|
|
|
|
|
|
this.headersElement = this.element.querySelector(".layout-tab-bar");
|
2023-01-28 16:19:27 +08:00
|
|
|
|
const dragElement = this.element.querySelector(".layout-tab-container__drag") as HTMLElement;
|
|
|
|
|
|
if (!dragElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
this.headersElement.addEventListener("mousedown", (event) => {
|
|
|
|
|
|
// 点击鼠标滚轮关闭
|
|
|
|
|
|
if (event.button !== 1) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let target = event.target as HTMLElement;
|
|
|
|
|
|
while (target && !target.isEqualNode(this.headersElement)) {
|
|
|
|
|
|
if (target.tagName === "LI") {
|
|
|
|
|
|
this.removeTab(target.getAttribute("data-id"));
|
|
|
|
|
|
window.siyuan.menus.menu.remove();
|
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
target = target.parentElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
this.headersElement.addEventListener("mousewheel", (event: WheelEvent) => {
|
|
|
|
|
|
this.headersElement.scrollLeft = this.headersElement.scrollLeft + event.deltaY;
|
|
|
|
|
|
}, {passive: true});
|
2023-01-28 16:19:27 +08:00
|
|
|
|
|
2022-09-04 21:51:18 +08:00
|
|
|
|
this.headersElement.parentElement.addEventListener("click", (event) => {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let target = event.target as HTMLElement;
|
|
|
|
|
|
while (target && !target.isEqualNode(this.headersElement)) {
|
2022-09-04 21:51:18 +08:00
|
|
|
|
if (target.classList.contains("item__close") && target.getAttribute("data-type") === "new") {
|
2022-09-06 20:22:04 +08:00
|
|
|
|
setPanelFocus(this.headersElement.parentElement.parentElement);
|
2023-02-03 22:29:34 +08:00
|
|
|
|
newFile(undefined, undefined, undefined, true);
|
2022-09-04 21:51:18 +08:00
|
|
|
|
break;
|
|
|
|
|
|
} else if (target.classList.contains("item__close") && target.getAttribute("data-type") === "more") {
|
|
|
|
|
|
this.renderTabList(event);
|
|
|
|
|
|
break;
|
|
|
|
|
|
} else if (target.tagName === "LI" && target.getAttribute("data-id")) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
this.switchTab(target, true);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
target = target.parentElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-01-26 19:50:14 +08:00
|
|
|
|
this.headersElement.parentElement.addEventListener("dblclick", (event) => {
|
|
|
|
|
|
let target = event.target as HTMLElement;
|
|
|
|
|
|
while (target && !target.isEqualNode(this.headersElement)) {
|
|
|
|
|
|
if (window.siyuan.config.fileTree.openFilesUseCurrentTab && target.getAttribute("data-type") === "tab-header") {
|
|
|
|
|
|
target.classList.remove("item--unupdate");
|
|
|
|
|
|
break;
|
|
|
|
|
|
} else if (target.tagName === "SPAN" && target.className === "fn__flex-1" &&
|
|
|
|
|
|
isWindow() && this.headersElement.getBoundingClientRect().top <= 0) {
|
2023-01-27 10:27:14 +08:00
|
|
|
|
/// #if !BROWSER
|
2023-01-26 19:50:14 +08:00
|
|
|
|
const currentWindow = getCurrentWindow();
|
|
|
|
|
|
if (currentWindow.isMaximized()) {
|
|
|
|
|
|
currentWindow.unmaximize();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
currentWindow.maximize();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2023-01-27 10:27:14 +08:00
|
|
|
|
/// #endif
|
2023-01-26 19:50:14 +08:00
|
|
|
|
break;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2023-01-26 19:50:14 +08:00
|
|
|
|
target = target.parentElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-02-16 18:29:39 +08:00
|
|
|
|
this.headersElement.parentElement.addEventListener("dragover", function (event: DragEvent & {
|
|
|
|
|
|
target: HTMLElement
|
|
|
|
|
|
}) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const it = this as HTMLElement;
|
2022-10-13 11:33:55 +08:00
|
|
|
|
if (event.dataTransfer.types.includes(Constants.SIYUAN_DROP_FILE)) {
|
2022-11-04 19:49:07 +08:00
|
|
|
|
event.preventDefault();
|
2023-01-28 16:19:27 +08:00
|
|
|
|
it.classList.add("layout-tab-bars--drag");
|
2022-10-13 11:33:55 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-01-28 00:06:47 +08:00
|
|
|
|
// 不能使用 !window.siyuan.dragElement,因为移动页签到新窗口后,再把主窗口页签拖拽新窗口页签上时,该值为空
|
|
|
|
|
|
if (!event.dataTransfer.types.includes(Constants.SIYUAN_DROP_TAB)) {
|
2022-11-04 19:49:07 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let oldTabHeaderElement = window.siyuan.dragElement;
|
|
|
|
|
|
let exitDrag = false;
|
2023-01-28 16:19:27 +08:00
|
|
|
|
Array.from(it.firstElementChild.childNodes).find((item: HTMLElement) => {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (item.style.opacity === "0.1") {
|
|
|
|
|
|
oldTabHeaderElement = item;
|
|
|
|
|
|
exitDrag = true;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-01-28 00:06:47 +08:00
|
|
|
|
if (!exitDrag && oldTabHeaderElement) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (oldTabHeaderElement.classList.contains("item--pin")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
oldTabHeaderElement = oldTabHeaderElement.cloneNode(true) as HTMLElement;
|
|
|
|
|
|
oldTabHeaderElement.setAttribute("data-clone", "true");
|
2023-01-28 16:19:27 +08:00
|
|
|
|
it.firstElementChild.append(oldTabHeaderElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
2023-01-28 00:06:47 +08:00
|
|
|
|
} else if (!exitDrag && !oldTabHeaderElement) { // 拖拽到新窗口
|
2023-01-28 00:45:18 +08:00
|
|
|
|
oldTabHeaderElement = document.createElement("li");
|
|
|
|
|
|
oldTabHeaderElement.style.opacity = "0.1";
|
|
|
|
|
|
oldTabHeaderElement.innerHTML = '<svg class="svg"><use xlink:href="#iconFile"></use></svg>';
|
2023-01-28 00:06:47 +08:00
|
|
|
|
oldTabHeaderElement.setAttribute("data-clone", "true");
|
2023-01-28 16:19:27 +08:00
|
|
|
|
it.firstElementChild.append(oldTabHeaderElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2023-01-28 16:19:27 +08:00
|
|
|
|
const newTabHeaderElement = hasClosestByAttribute(event.target, "data-type", "tab-header");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (!newTabHeaderElement) {
|
2023-01-28 16:19:27 +08:00
|
|
|
|
if (!oldTabHeaderElement.classList.contains("item--pin")) {
|
|
|
|
|
|
it.classList.add("layout-tab-bars--drag");
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!newTabHeaderElement.isSameNode(oldTabHeaderElement) &&
|
|
|
|
|
|
((oldTabHeaderElement.classList.contains("item--pin") && newTabHeaderElement.classList.contains("item--pin")) ||
|
|
|
|
|
|
(!oldTabHeaderElement.classList.contains("item--pin") && !newTabHeaderElement.classList.contains("item--pin")))) {
|
|
|
|
|
|
const rect = newTabHeaderElement.getClientRects()[0];
|
|
|
|
|
|
if (event.clientX > rect.left + rect.width / 2) {
|
|
|
|
|
|
newTabHeaderElement.after(oldTabHeaderElement);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
newTabHeaderElement.before(oldTabHeaderElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-01-28 14:52:58 +08:00
|
|
|
|
let dragleaveTimeout: number;
|
2023-01-28 16:19:27 +08:00
|
|
|
|
this.headersElement.parentElement.addEventListener("dragleave", function () {
|
2023-01-28 14:52:58 +08:00
|
|
|
|
clearTimeout(dragleaveTimeout);
|
2023-01-28 12:09:13 +08:00
|
|
|
|
// 窗口拖拽到新窗口时,不 drop 无法移除 clone 的元素
|
|
|
|
|
|
dragleaveTimeout = window.setTimeout(() => {
|
|
|
|
|
|
document.querySelectorAll(".layout-tab-bar li[data-clone='true']").forEach(item => {
|
|
|
|
|
|
item.remove();
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 1000);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const it = this as HTMLElement;
|
2023-01-28 16:19:27 +08:00
|
|
|
|
it.classList.remove("layout-tab-bars--drag");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
});
|
2023-02-16 18:29:39 +08:00
|
|
|
|
this.headersElement.parentElement.addEventListener("drop", function (event: DragEvent & {
|
|
|
|
|
|
target: HTMLElement
|
|
|
|
|
|
}) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const it = this as HTMLElement;
|
2022-10-13 11:33:55 +08:00
|
|
|
|
if (event.dataTransfer.types.includes(Constants.SIYUAN_DROP_FILE)) {
|
|
|
|
|
|
// 文档树拖拽
|
2023-01-28 16:19:27 +08:00
|
|
|
|
setPanelFocus(it.parentElement);
|
2022-11-04 19:49:07 +08:00
|
|
|
|
event.dataTransfer.getData(Constants.SIYUAN_DROP_FILE).split(",").forEach(item => {
|
|
|
|
|
|
if (item) {
|
|
|
|
|
|
openFileById({
|
|
|
|
|
|
id: item,
|
|
|
|
|
|
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_SCROLL]
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2022-10-13 11:33:55 +08:00
|
|
|
|
});
|
|
|
|
|
|
window.siyuan.dragElement = undefined;
|
2023-01-28 16:19:27 +08:00
|
|
|
|
it.classList.remove("layout-tab-bars--drag");
|
2022-10-13 11:33:55 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-02-17 15:46:46 +08:00
|
|
|
|
const tabData = JSON.parse(event.dataTransfer.getData(Constants.SIYUAN_DROP_TAB));
|
2023-02-16 18:29:39 +08:00
|
|
|
|
let oldTab = getInstanceById(tabData.id) as Tab;
|
2023-01-28 16:19:27 +08:00
|
|
|
|
const wnd = getInstanceById(it.parentElement.getAttribute("data-id")) as Wnd;
|
2023-01-28 00:06:47 +08:00
|
|
|
|
/// #if !BROWSER
|
|
|
|
|
|
if (!oldTab) { // 从主窗口拖拽到页签新窗口
|
2023-01-28 11:32:55 +08:00
|
|
|
|
if (wnd instanceof Wnd) {
|
2023-02-16 18:29:39 +08:00
|
|
|
|
JSONToCenter(tabData, wnd);
|
2023-01-28 11:32:55 +08:00
|
|
|
|
oldTab = wnd.children[wnd.children.length - 1];
|
2023-02-16 18:29:39 +08:00
|
|
|
|
ipcRenderer.send(Constants.SIYUAN_CLOSETAB, tabData.id);
|
2023-01-28 11:32:55 +08:00
|
|
|
|
it.querySelector("li[data-clone='true']").remove();
|
|
|
|
|
|
wnd.switchTab(oldTab.headElement);
|
|
|
|
|
|
}
|
2023-01-28 00:06:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
/// #endif
|
2023-01-28 16:19:27 +08:00
|
|
|
|
it.classList.remove("layout-tab-bars--drag");
|
2023-01-28 00:06:47 +08:00
|
|
|
|
if (!oldTab) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
2023-01-28 16:19:27 +08:00
|
|
|
|
const nextTabHeaderElement = (Array.from(it.firstElementChild.childNodes).find((item: HTMLElement) => {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (item.style.opacity === "0.1") {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}) as HTMLElement)?.nextElementSibling;
|
|
|
|
|
|
|
|
|
|
|
|
if (!it.contains(oldTab.headElement)) {
|
|
|
|
|
|
// 从其他 Wnd 拖动过来
|
|
|
|
|
|
const cloneTabElement = it.querySelector("[data-clone='true']");
|
|
|
|
|
|
if (!cloneTabElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
cloneTabElement.before(oldTab.headElement);
|
|
|
|
|
|
cloneTabElement.remove();
|
2023-01-06 11:37:48 +08:00
|
|
|
|
if (oldTab.model instanceof Asset) {
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/6890
|
|
|
|
|
|
const pdfViewerElement = oldTab.model.element.querySelector("#viewerContainer");
|
|
|
|
|
|
if (pdfViewerElement) {
|
|
|
|
|
|
pdfViewerElement.setAttribute("data-scrolltop", pdfViewerElement.scrollTop.toString());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// 对象顺序
|
2023-01-28 16:19:27 +08:00
|
|
|
|
wnd.moveTab(oldTab, nextTabHeaderElement ? nextTabHeaderElement.getAttribute("data-id") : undefined);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
resizeTabs();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let tempTab: Tab;
|
|
|
|
|
|
oldTab.parent.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === oldTab.id) {
|
|
|
|
|
|
tempTab = oldTab.parent.children.splice(index, 1)[0];
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (nextTabHeaderElement) {
|
|
|
|
|
|
oldTab.parent.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === nextTabHeaderElement.getAttribute("data-id")) {
|
|
|
|
|
|
oldTab.parent.children.splice(index, 0, tempTab);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
oldTab.parent.children.push(tempTab);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-01-28 16:19:27 +08:00
|
|
|
|
|
|
|
|
|
|
this.element.addEventListener("dragenter", (event: DragEvent & { target: HTMLElement }) => {
|
|
|
|
|
|
if (event.dataTransfer.types.includes(Constants.SIYUAN_DROP_TAB)) {
|
|
|
|
|
|
const tabHeadersElement = hasClosestByClassName(event.target, "layout-tab-bar");
|
|
|
|
|
|
if (tabHeadersElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const tabPanelsElement = hasClosestByClassName(event.target, "layout-tab-container", true);
|
|
|
|
|
|
if (tabPanelsElement) {
|
|
|
|
|
|
dragElement.classList.remove("fn__none");
|
|
|
|
|
|
dragElement.setAttribute("style", "height:100%;width:100%;right:auto;bottom:auto");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
dragElement.addEventListener("dragover", (event: DragEvent & { layerX: number, layerY: number }) => {
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
if (!dragElement.nextElementSibling) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const rect = dragElement.parentElement.getBoundingClientRect();
|
|
|
|
|
|
const height = rect.height;
|
|
|
|
|
|
const width = rect.width;
|
|
|
|
|
|
const x = event.clientX - rect.left;
|
|
|
|
|
|
const y = event.clientY - rect.top;
|
|
|
|
|
|
if ((x <= width / 3 && (y <= height / 8 || y >= height * 7 / 8)) ||
|
|
|
|
|
|
(x <= width / 8 && (y > height / 8 || y < height * 7 / 8))) {
|
|
|
|
|
|
dragElement.setAttribute("style", "height:100%;width:50%;right:50%;bottom:0;left:0;top:0");
|
|
|
|
|
|
} else if ((x > width * 2 / 3 && (y <= height / 8 || y >= height * 7 / 8)) ||
|
|
|
|
|
|
(x >= width * 7 / 8 && (y > height / 8 || y < height * 7 / 8))) {
|
|
|
|
|
|
dragElement.setAttribute("style", "height:100%;width:50%;right:0;bottom:0;left:50%;top:0");
|
|
|
|
|
|
} else if (x > width / 3 && x < width * 2 / 3 && y <= height / 8) {
|
|
|
|
|
|
dragElement.setAttribute("style", "height:50%;width:100%;right:0;bottom:50%;left:0;top:0");
|
|
|
|
|
|
} else if (x > width / 3 && x < width * 2 / 3 && y >= height * 7 / 8) {
|
|
|
|
|
|
dragElement.setAttribute("style", "height:50%;width:100%;right:0;bottom:0;left:0;top:50%");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dragElement.setAttribute("style", "height:100%;width:100%;right:0;bottom:0;top:0;left:0");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
dragElement.addEventListener("dragleave", () => {
|
|
|
|
|
|
dragElement.classList.add("fn__none");
|
|
|
|
|
|
});
|
|
|
|
|
|
dragElement.addEventListener("drop", (event: DragEvent & { target: HTMLElement }) => {
|
|
|
|
|
|
dragElement.classList.add("fn__none");
|
|
|
|
|
|
const targetWndElement = event.target.parentElement.parentElement;
|
|
|
|
|
|
const targetWnd = getInstanceById(targetWndElement.getAttribute("data-id")) as Wnd;
|
2023-02-17 15:46:46 +08:00
|
|
|
|
const tabData = JSON.parse(event.dataTransfer.getData(Constants.SIYUAN_DROP_TAB));
|
2023-02-16 18:29:39 +08:00
|
|
|
|
let oldTab = getInstanceById(tabData.id) as Tab;
|
2023-01-27 22:37:22 +08:00
|
|
|
|
/// #if !BROWSER
|
|
|
|
|
|
if (!oldTab) { // 从主窗口拖拽到页签新窗口
|
2023-02-16 18:29:39 +08:00
|
|
|
|
JSONToCenter(tabData, this);
|
2023-01-27 18:09:34 +08:00
|
|
|
|
oldTab = this.children[this.children.length - 1];
|
2023-02-16 18:29:39 +08:00
|
|
|
|
ipcRenderer.send(Constants.SIYUAN_CLOSETAB, tabData.id);
|
2023-01-27 22:37:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
/// #endif
|
|
|
|
|
|
if (!oldTab) {
|
|
|
|
|
|
return;
|
2023-01-27 18:09:34 +08:00
|
|
|
|
}
|
2023-01-26 19:50:14 +08:00
|
|
|
|
if (oldTab.model instanceof Asset) {
|
2022-12-21 14:35:05 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/6890
|
2022-12-22 22:19:04 +08:00
|
|
|
|
const pdfViewerElement = oldTab.model.element.querySelector("#viewerContainer");
|
2022-12-21 14:35:05 +08:00
|
|
|
|
if (pdfViewerElement) {
|
2022-12-22 22:19:04 +08:00
|
|
|
|
pdfViewerElement.setAttribute("data-scrolltop", pdfViewerElement.scrollTop.toString());
|
2022-12-21 14:35:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (dragElement.style.height === "50%" || dragElement.style.width === "50%") {
|
|
|
|
|
|
// split
|
|
|
|
|
|
if (dragElement.style.height === "50%") {
|
|
|
|
|
|
// split to bottom
|
|
|
|
|
|
const newWnd = targetWnd.split("tb");
|
|
|
|
|
|
newWnd.headersElement.append(oldTab.headElement);
|
2022-09-05 12:01:46 +08:00
|
|
|
|
newWnd.headersElement.parentElement.classList.remove("fn__none");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
newWnd.moveTab(oldTab);
|
|
|
|
|
|
|
2022-07-02 21:54:22 +08:00
|
|
|
|
if (dragElement.style.bottom === "50%" && newWnd.element.previousElementSibling && targetWnd.element.parentElement) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// 交换位置
|
|
|
|
|
|
switchWnd(newWnd, targetWnd);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (dragElement.style.width === "50%") {
|
|
|
|
|
|
// split to right
|
|
|
|
|
|
const newWnd = targetWnd.split("lr");
|
|
|
|
|
|
newWnd.headersElement.append(oldTab.headElement);
|
2022-09-05 12:01:46 +08:00
|
|
|
|
newWnd.headersElement.parentElement.classList.remove("fn__none");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
newWnd.moveTab(oldTab);
|
|
|
|
|
|
|
2022-07-02 21:54:22 +08:00
|
|
|
|
if (dragElement.style.right === "50%" && newWnd.element.previousElementSibling && targetWnd.element.parentElement) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// 交换位置
|
|
|
|
|
|
switchWnd(newWnd, targetWnd);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-01-27 10:27:14 +08:00
|
|
|
|
/// #if !BROWSER
|
2023-01-26 18:53:57 +08:00
|
|
|
|
setTabPosition();
|
2023-01-27 10:27:14 +08:00
|
|
|
|
/// #endif
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-16 18:29:39 +08:00
|
|
|
|
if (targetWndElement.contains(document.querySelector(`[data-id="${tabData.id}"]`))) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (targetWnd) {
|
|
|
|
|
|
targetWnd.headersElement.append(oldTab.headElement);
|
2022-09-05 12:01:46 +08:00
|
|
|
|
targetWnd.headersElement.parentElement.classList.remove("fn__none");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
targetWnd.moveTab(oldTab);
|
|
|
|
|
|
resizeTabs();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public showHeading() {
|
|
|
|
|
|
const currentElement = this.headersElement.querySelector(".item--focus") as HTMLElement;
|
2022-10-20 01:49:19 +08:00
|
|
|
|
if (!currentElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (currentElement.offsetLeft + currentElement.clientWidth > this.headersElement.scrollLeft + this.headersElement.clientWidth) {
|
|
|
|
|
|
this.headersElement.scrollLeft = currentElement.offsetLeft + currentElement.clientWidth - this.headersElement.clientWidth;
|
|
|
|
|
|
} else if (currentElement.offsetLeft < this.headersElement.scrollLeft) {
|
|
|
|
|
|
this.headersElement.scrollLeft = currentElement.offsetLeft;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public switchTab(target: HTMLElement, pushBack = false, update = true) {
|
2022-09-05 12:01:46 +08:00
|
|
|
|
setPanelFocus(this.headersElement.parentElement.parentElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let currentTab: Tab;
|
|
|
|
|
|
this.children.forEach((item) => {
|
|
|
|
|
|
if (target === item.headElement) {
|
|
|
|
|
|
if (item.headElement && item.headElement.classList.contains("fn__none")) {
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/267
|
|
|
|
|
|
} else {
|
2022-06-29 09:09:18 +08:00
|
|
|
|
if (item.headElement) {
|
|
|
|
|
|
item.headElement.classList.add("item--focus");
|
|
|
|
|
|
item.headElement.setAttribute("data-activetime", (new Date()).getTime().toString());
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
item.panelElement.classList.remove("fn__none");
|
|
|
|
|
|
}
|
|
|
|
|
|
currentTab = item;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
item.headElement?.classList.remove("item--focus");
|
|
|
|
|
|
if (!item.panelElement.classList.contains("fn__none")) {
|
|
|
|
|
|
// 必须现判断,否则会触发 observer.observe(this.element, {attributeFilter: ["class"]}); 导致 https://ld246.com/article/1641198819303
|
|
|
|
|
|
item.panelElement.classList.add("fn__none");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-01-26 18:53:57 +08:00
|
|
|
|
if (currentTab && currentTab.headElement) {
|
2023-01-04 11:10:57 +08:00
|
|
|
|
const initData = currentTab.headElement.getAttribute("data-initdata");
|
|
|
|
|
|
if (initData) {
|
|
|
|
|
|
const json = JSON.parse(initData);
|
|
|
|
|
|
currentTab.addModel(new Editor({
|
|
|
|
|
|
tab: currentTab,
|
|
|
|
|
|
blockId: json.blockId,
|
|
|
|
|
|
mode: json.mode,
|
|
|
|
|
|
action: typeof json.action === "string" ? [json.action] : json.action,
|
|
|
|
|
|
scrollAttr: json.scrollAttr,
|
|
|
|
|
|
}));
|
|
|
|
|
|
currentTab.headElement.removeAttribute("data-initdata");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-08-08 10:42:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-18 12:12:51 +08:00
|
|
|
|
if (currentTab && target === currentTab.headElement) {
|
|
|
|
|
|
if (currentTab.model instanceof Graph) {
|
|
|
|
|
|
currentTab.model.onGraph(false);
|
|
|
|
|
|
} else if (currentTab.model instanceof Asset && currentTab.model.pdfObject) {
|
2022-08-18 12:13:31 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/5655
|
2022-08-18 12:12:51 +08:00
|
|
|
|
currentTab.model.pdfObject.pdfViewer.container.focus();
|
|
|
|
|
|
}
|
2022-08-08 10:42:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (currentTab && currentTab.model instanceof Editor) {
|
|
|
|
|
|
const keepCursorId = currentTab.headElement.getAttribute("keep-cursor");
|
|
|
|
|
|
if (keepCursorId) {
|
2022-06-29 09:09:18 +08:00
|
|
|
|
// 在新页签中打开,但不跳转到新页签,但切换到新页签时需调整滚动
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let nodeElement: HTMLElement;
|
|
|
|
|
|
Array.from(currentTab.model.editor.protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${keepCursorId}"]`)).find((item: HTMLElement) => {
|
|
|
|
|
|
if (!hasClosestByAttribute(item, "data-type", "NodeBlockQueryEmbed", true)) {
|
|
|
|
|
|
nodeElement = item;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (nodeElement) {
|
|
|
|
|
|
if (!currentTab.model.editor.protyle.toolbar.range) {
|
|
|
|
|
|
const range = document.createRange();
|
|
|
|
|
|
range.selectNodeContents(nodeElement);
|
|
|
|
|
|
range.collapse();
|
|
|
|
|
|
currentTab.model.editor.protyle.toolbar.range = range;
|
|
|
|
|
|
}
|
|
|
|
|
|
scrollCenter(currentTab.model.editor.protyle, nodeElement, true);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
openFileById({
|
|
|
|
|
|
id: keepCursorId,
|
2022-08-07 09:26:08 +08:00
|
|
|
|
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT]
|
2022-05-26 15:18:53 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
currentTab.headElement.removeAttribute("keep-cursor");
|
|
|
|
|
|
}
|
|
|
|
|
|
// focusin 触发前,layout__wnd--active 和 tab 已设置,需在调用里面更新
|
|
|
|
|
|
if (update) {
|
|
|
|
|
|
updatePanelByEditor(currentTab.model.editor.protyle, true, pushBack);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
updatePanelByEditor(undefined, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public addTab(tab: Tab, keepCursor = false) {
|
|
|
|
|
|
if (keepCursor) {
|
|
|
|
|
|
tab.headElement?.classList.remove("item--focus");
|
|
|
|
|
|
tab.panelElement.classList.add("fn__none");
|
|
|
|
|
|
}
|
|
|
|
|
|
let oldFocusIndex = 0;
|
|
|
|
|
|
this.children.forEach((item, index) => {
|
2022-05-30 10:20:44 +08:00
|
|
|
|
if (item.headElement && item.headElement.classList.contains("item--focus")) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
oldFocusIndex = index;
|
2022-05-30 10:20:44 +08:00
|
|
|
|
let nextElement = item.headElement.nextElementSibling;
|
|
|
|
|
|
while (nextElement && nextElement.classList.contains("item--pin")) {
|
|
|
|
|
|
oldFocusIndex++;
|
|
|
|
|
|
nextElement = nextElement.nextElementSibling;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (!keepCursor) {
|
|
|
|
|
|
item.headElement?.classList.remove("item--focus");
|
|
|
|
|
|
item.panelElement.classList.add("fn__none");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.children.splice(oldFocusIndex + 1, 0, tab);
|
|
|
|
|
|
|
|
|
|
|
|
if (tab.headElement) {
|
2022-09-04 21:51:18 +08:00
|
|
|
|
this.headersElement.parentElement.classList.remove("fn__none");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (this.headersElement.childElementCount === 0) {
|
|
|
|
|
|
this.headersElement.append(tab.headElement);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.headersElement.children[oldFocusIndex].after(tab.headElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
tab.headElement.querySelector(".item__close").addEventListener("click", (event) => {
|
|
|
|
|
|
if (tab.headElement.classList.contains("item--pin")) {
|
|
|
|
|
|
tab.unpin();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tab.parent.removeTab(tab.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
window.siyuan.menus.menu.remove();
|
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
});
|
2022-06-23 00:28:27 +08:00
|
|
|
|
|
2022-06-29 09:09:18 +08:00
|
|
|
|
tab.headElement.setAttribute("data-activetime", (new Date()).getTime().toString());
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2022-05-29 10:06:02 +08:00
|
|
|
|
const containerElement = this.element.querySelector(".layout-tab-container");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (!containerElement.querySelector(".fn__flex-1")) {
|
|
|
|
|
|
// empty center
|
|
|
|
|
|
containerElement.append(tab.panelElement);
|
|
|
|
|
|
} else if (!containerElement.querySelector(".layout-tab-container__drag")) {
|
|
|
|
|
|
// Dock
|
|
|
|
|
|
containerElement.children[oldFocusIndex].after(tab.panelElement);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
containerElement.children[oldFocusIndex + 1].after(tab.panelElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tab.parent = this;
|
|
|
|
|
|
if (tab.callback) {
|
|
|
|
|
|
tab.callback(tab);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 移除 centerLayout 中的 empty
|
|
|
|
|
|
if (this.parent.type === "center" && this.children.length === 2 && !this.children[0].headElement) {
|
|
|
|
|
|
this.removeTab(this.children[0].id);
|
2022-06-23 11:43:46 +08:00
|
|
|
|
} else if (this.children.length > window.siyuan.config.fileTree.maxOpenTabCount) {
|
2022-07-25 16:13:28 +08:00
|
|
|
|
this.removeOverCounter(oldFocusIndex);
|
|
|
|
|
|
}
|
2023-01-27 10:27:14 +08:00
|
|
|
|
/// #if !BROWSER
|
2023-01-26 18:53:57 +08:00
|
|
|
|
setTabPosition();
|
2023-01-27 10:27:14 +08:00
|
|
|
|
/// #endif
|
2022-07-25 16:13:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-04 21:51:18 +08:00
|
|
|
|
private renderTabList(event: MouseEvent) {
|
2022-09-07 17:56:13 +08:00
|
|
|
|
window.siyuan.menus.menu.remove();
|
2022-11-04 21:50:03 +08:00
|
|
|
|
window.siyuan.menus.menu.element.classList.add("b3-menu--list");
|
2022-09-04 21:51:18 +08:00
|
|
|
|
Array.from(this.headersElement.children).forEach((item: HTMLElement) => {
|
2022-09-07 17:56:13 +08:00
|
|
|
|
const iconElement = item.querySelector(".item__icon");
|
|
|
|
|
|
const graphicElement = item.querySelector(".item__graphic");
|
2022-09-04 21:51:18 +08:00
|
|
|
|
window.siyuan.menus.menu.append(new MenuItem({
|
2022-09-20 22:30:41 +08:00
|
|
|
|
label: escapeHtml(item.querySelector(".item__text").textContent),
|
|
|
|
|
|
action: "iconClose",
|
2022-09-04 22:17:08 +08:00
|
|
|
|
iconHTML: iconElement ? `<span class="b3-menu__icon">${iconElement.innerHTML}</span>` : "",
|
|
|
|
|
|
icon: graphicElement ? graphicElement.firstElementChild.getAttribute("xlink:href").substring(1) : "",
|
2022-09-20 22:30:41 +08:00
|
|
|
|
bind: (element) => {
|
|
|
|
|
|
element.addEventListener("click", (event) => {
|
|
|
|
|
|
if (hasClosestByTag(event.target as Element, "svg")) {
|
|
|
|
|
|
this.removeTab(item.getAttribute("data-id"));
|
|
|
|
|
|
if (element.previousElementSibling || element.nextElementSibling) {
|
|
|
|
|
|
element.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
window.siyuan.menus.menu.remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.switchTab(item, true);
|
2022-10-19 18:37:33 +08:00
|
|
|
|
this.showHeading();
|
2022-09-20 22:30:41 +08:00
|
|
|
|
window.siyuan.menus.menu.remove();
|
|
|
|
|
|
}
|
2022-09-23 23:30:01 +08:00
|
|
|
|
event.preventDefault();
|
2022-09-20 22:30:41 +08:00
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
});
|
2022-09-04 21:51:18 +08:00
|
|
|
|
},
|
|
|
|
|
|
current: item.classList.contains("item--focus")
|
|
|
|
|
|
}).element);
|
2022-09-07 17:56:13 +08:00
|
|
|
|
});
|
2022-09-04 21:51:18 +08:00
|
|
|
|
window.siyuan.menus.menu.popup({
|
2022-11-02 15:41:47 +08:00
|
|
|
|
x: event.clientX,
|
2022-09-04 21:51:18 +08:00
|
|
|
|
y: event.clientY,
|
2022-11-02 15:41:47 +08:00
|
|
|
|
w: 16
|
2022-09-04 21:51:18 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-25 16:13:28 +08:00
|
|
|
|
private removeOverCounter(oldFocusIndex?: number) {
|
|
|
|
|
|
if (typeof oldFocusIndex === "undefined") {
|
2022-06-23 00:28:27 +08:00
|
|
|
|
this.children.forEach((item, index) => {
|
2022-07-25 16:13:28 +08:00
|
|
|
|
if (item.headElement && item.headElement.classList.contains("item--focus")) {
|
|
|
|
|
|
oldFocusIndex = index;
|
2022-06-23 00:28:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2022-07-25 16:13:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
let removeId: string;
|
|
|
|
|
|
let openTime: string;
|
|
|
|
|
|
this.children.forEach((item, index) => {
|
|
|
|
|
|
if (item.headElement.classList.contains("item--pin") ||
|
|
|
|
|
|
item.headElement.classList.contains("item--focus") ||
|
|
|
|
|
|
index === oldFocusIndex) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!openTime) {
|
|
|
|
|
|
openTime = item.headElement.getAttribute("data-activetime");
|
|
|
|
|
|
removeId = this.children[index].id;
|
|
|
|
|
|
} else if (item.headElement.getAttribute("data-activetime") < openTime) {
|
|
|
|
|
|
openTime = item.headElement.getAttribute("data-activetime");
|
|
|
|
|
|
removeId = this.children[index].id;
|
2022-06-23 00:28:27 +08:00
|
|
|
|
}
|
2022-07-25 16:13:28 +08:00
|
|
|
|
});
|
|
|
|
|
|
if (removeId) {
|
|
|
|
|
|
this.removeTab(removeId);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private destroyModel(model: Model) {
|
|
|
|
|
|
if (!model) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (model instanceof Editor && model.editor) {
|
|
|
|
|
|
window.siyuan.blockPanels.forEach((item) => {
|
|
|
|
|
|
if (item.element && model.editor.protyle.wysiwyg.element.contains(item.element)) {
|
|
|
|
|
|
item.destroy();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
model.editor.destroy();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (model instanceof Search) {
|
2022-11-27 00:50:53 +08:00
|
|
|
|
if (model.edit) {
|
|
|
|
|
|
model.edit.destroy();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-09-04 23:19:11 +08:00
|
|
|
|
if (model instanceof Asset) {
|
2022-10-01 17:17:46 +08:00
|
|
|
|
if (model.pdfObject && model.pdfObject.pdfLoadingTask) {
|
2022-09-04 23:19:11 +08:00
|
|
|
|
model.pdfObject.pdfLoadingTask.destroy();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
model.send("closews", {});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-07 21:38:14 +08:00
|
|
|
|
private removeTabAction = (id: string, closeAll = false, hasSaveScroll = true, animate = true) => {
|
2022-10-05 10:12:21 +08:00
|
|
|
|
clearCounter();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
this.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === id) {
|
2022-08-10 11:24:12 +08:00
|
|
|
|
if (item.model instanceof Editor && hasSaveScroll) {
|
2022-08-07 00:14:50 +08:00
|
|
|
|
saveScroll(item.model.editor.protyle);
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (this.children.length === 1) {
|
|
|
|
|
|
this.destroyModel(this.children[0].model);
|
|
|
|
|
|
this.children = [];
|
|
|
|
|
|
if (["top", "bottom", "left", "right"].includes(this.parent.type)) {
|
|
|
|
|
|
item.panelElement.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.remove();
|
|
|
|
|
|
}
|
2022-06-23 15:45:55 +08:00
|
|
|
|
// 关闭分屏页签后光标消失
|
|
|
|
|
|
const editors = getAllModels().editor;
|
|
|
|
|
|
if (editors.length === 0) {
|
|
|
|
|
|
updatePanelByEditor();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
editors.forEach(item => {
|
|
|
|
|
|
if (!item.element.classList.contains("fn__none")) {
|
2022-09-05 12:01:46 +08:00
|
|
|
|
setPanelFocus(item.parent.parent.headersElement.parentElement.parentElement);
|
2022-06-23 15:45:55 +08:00
|
|
|
|
updatePanelByEditor(item.editor.protyle, true, true);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2023-01-27 18:09:34 +08:00
|
|
|
|
/// #if !BROWSER
|
|
|
|
|
|
setTabPosition();
|
|
|
|
|
|
/// #endif
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.headElement) {
|
|
|
|
|
|
if (item.headElement.classList.contains("item--focus")) {
|
2023-02-21 13:22:31 +08:00
|
|
|
|
let latestHeadElement: HTMLElement
|
|
|
|
|
|
Array.from(item.headElement.parentElement.children).forEach((headItem: HTMLElement) => {
|
|
|
|
|
|
if (!headItem.isSameNode(item.headElement)) {
|
|
|
|
|
|
if (!latestHeadElement) {
|
|
|
|
|
|
latestHeadElement = headItem;
|
|
|
|
|
|
} else if (headItem.getAttribute("data-activetime") > latestHeadElement.getAttribute("data-activetime")) {
|
|
|
|
|
|
latestHeadElement = headItem;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
if (latestHeadElement && !closeAll) {
|
|
|
|
|
|
this.switchTab(latestHeadElement, true);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-11-07 21:38:14 +08:00
|
|
|
|
if (animate) {
|
|
|
|
|
|
item.headElement.setAttribute("style", "max-width: 0px;");
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
item.headElement.remove();
|
|
|
|
|
|
}, Constants.TIMEOUT_TRANSITION);
|
|
|
|
|
|
} else {
|
2022-10-14 11:12:35 +08:00
|
|
|
|
item.headElement.remove();
|
2022-11-07 21:38:14 +08:00
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
item.panelElement.remove();
|
|
|
|
|
|
this.destroyModel(item.model);
|
|
|
|
|
|
this.children.splice(index, 1);
|
|
|
|
|
|
resizeTabs();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2022-07-25 16:13:28 +08:00
|
|
|
|
// 初始化移除窗口,但 centerLayout 还没有赋值 https://ld246.com/article/1658718634416
|
|
|
|
|
|
if (window.siyuan.layout.centerLayout) {
|
|
|
|
|
|
const wnd = getWndByLayout(window.siyuan.layout.centerLayout);
|
|
|
|
|
|
if (!wnd) {
|
2023-01-26 18:53:57 +08:00
|
|
|
|
/// #if !BROWSER
|
|
|
|
|
|
if (isWindow()) {
|
|
|
|
|
|
getCurrentWindow().destroy();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
/// #endif
|
2022-07-25 16:13:28 +08:00
|
|
|
|
const wnd = new Wnd();
|
|
|
|
|
|
window.siyuan.layout.centerLayout.addWnd(wnd);
|
|
|
|
|
|
wnd.addTab(newCenterEmptyTab());
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
/// #if !BROWSER
|
|
|
|
|
|
webFrame.clearCache();
|
|
|
|
|
|
getCurrentWindow().webContents.session.clearCache();
|
|
|
|
|
|
/// #endif
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-11-07 21:38:14 +08:00
|
|
|
|
public removeTab(id: string, closeAll = false, needSaveScroll = true, animate = true) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
for (let index = 0; index < this.children.length; index++) {
|
|
|
|
|
|
const item = this.children[index];
|
|
|
|
|
|
if (item.id === id) {
|
|
|
|
|
|
if ((item.model instanceof Editor) && item.model.editor?.protyle) {
|
|
|
|
|
|
if (item.model.editor.protyle.upload.isUploading) {
|
|
|
|
|
|
showMessage(window.siyuan.languages.uploading);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-11-07 21:38:14 +08:00
|
|
|
|
this.removeTabAction(id, closeAll, needSaveScroll, animate);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
2022-11-07 21:38:14 +08:00
|
|
|
|
this.removeTabAction(id, closeAll, needSaveScroll, animate);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public moveTab(tab: Tab, nextId?: string) {
|
|
|
|
|
|
this.element.querySelector(".layout-tab-container").append(tab.panelElement);
|
2022-06-29 18:47:02 +08:00
|
|
|
|
if (tab.model instanceof Editor) {
|
|
|
|
|
|
// DOM 移动后 range 会变化,因此置空
|
|
|
|
|
|
tab.model.editor.protyle.toolbar.range = null;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (nextId) {
|
|
|
|
|
|
// 只能用 find https://github.com/siyuan-note/siyuan/issues/3455
|
|
|
|
|
|
this.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === nextId) {
|
|
|
|
|
|
this.children.splice(index, 0, tab);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.children.push(tab);
|
|
|
|
|
|
}
|
2022-07-25 16:13:28 +08:00
|
|
|
|
if (this.children.length > window.siyuan.config.fileTree.maxOpenTabCount) {
|
|
|
|
|
|
this.removeOverCounter();
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
this.switchTab(tab.headElement);
|
|
|
|
|
|
|
|
|
|
|
|
const oldWnd = tab.parent;
|
|
|
|
|
|
if (oldWnd.children.length === 1) {
|
|
|
|
|
|
oldWnd.children = [];
|
|
|
|
|
|
oldWnd.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
oldWnd.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === tab.id) {
|
|
|
|
|
|
oldWnd.children.splice(index, 1);
|
|
|
|
|
|
resizeTabs();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
oldWnd.switchTab(oldWnd.children[oldWnd.children.length - 1].headElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
tab.parent = this;
|
|
|
|
|
|
resizeTabs();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public split(direction: TDirection) {
|
|
|
|
|
|
if (this.children.length === 1 && !this.children[0].headElement) {
|
|
|
|
|
|
// 场景:没有打开的文档,点击标签面板打开
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
const wnd = new Wnd(direction);
|
|
|
|
|
|
if (direction === this.parent.direction) {
|
|
|
|
|
|
this.parent.addWnd(wnd, this.id);
|
|
|
|
|
|
} else if (this.parent.children.length === 1) {
|
|
|
|
|
|
// layout 仅含一个时,只需更新 direction
|
|
|
|
|
|
this.parent.direction = direction;
|
|
|
|
|
|
if (direction === "tb") {
|
|
|
|
|
|
this.parent.element.classList.add("fn__flex-column");
|
|
|
|
|
|
this.parent.element.classList.remove("fn__flex");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.parent.element.classList.remove("fn__flex-column");
|
|
|
|
|
|
this.parent.element.classList.add("fn__flex");
|
|
|
|
|
|
}
|
|
|
|
|
|
this.parent.addWnd(wnd, this.id);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.parent.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === this.id) {
|
|
|
|
|
|
const layout = new Layout({
|
|
|
|
|
|
resize: item.resize,
|
|
|
|
|
|
direction,
|
|
|
|
|
|
});
|
|
|
|
|
|
this.parent.addLayout(layout, item.id);
|
|
|
|
|
|
const movedWnd = this.parent.children.splice(index, 1)[0];
|
|
|
|
|
|
if (movedWnd.resize) {
|
|
|
|
|
|
movedWnd.element.previousElementSibling.remove();
|
|
|
|
|
|
movedWnd.resize = undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
layout.addWnd.call(layout, movedWnd);
|
|
|
|
|
|
layout.addWnd.call(layout, wnd);
|
|
|
|
|
|
|
|
|
|
|
|
if (direction === "tb" && movedWnd.element.style.width) {
|
|
|
|
|
|
layout.element.style.width = movedWnd.element.style.width;
|
|
|
|
|
|
layout.element.classList.remove("fn__flex-1");
|
|
|
|
|
|
movedWnd.element.style.width = "";
|
|
|
|
|
|
movedWnd.element.classList.add("fn__flex-1");
|
|
|
|
|
|
} else if (direction === "lr" && movedWnd.element.style.height) {
|
|
|
|
|
|
layout.element.style.height = movedWnd.element.style.height;
|
|
|
|
|
|
layout.element.classList.remove("fn__flex-1");
|
|
|
|
|
|
movedWnd.element.style.height = "";
|
|
|
|
|
|
movedWnd.element.classList.add("fn__flex-1");
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return wnd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private remove() {
|
|
|
|
|
|
let layout = this.parent;
|
|
|
|
|
|
let element = this.element;
|
|
|
|
|
|
let id = this.id;
|
|
|
|
|
|
while (layout && layout.children.length === 1 && "center" !== layout.type) {
|
|
|
|
|
|
id = layout.id;
|
|
|
|
|
|
element = layout.element;
|
|
|
|
|
|
layout = layout.parent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
layout.children.find((item, index) => {
|
|
|
|
|
|
if (item.id === id) {
|
|
|
|
|
|
if (layout.children.length > 1) {
|
|
|
|
|
|
let previous = layout.children[index - 1];
|
|
|
|
|
|
if (index === 0) {
|
|
|
|
|
|
previous = layout.children[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
if (layout.children.length === 2) {
|
|
|
|
|
|
if (layout.direction === "lr") {
|
|
|
|
|
|
previous.element.style.width = "";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
previous.element.style.height = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
previous.resize = undefined;
|
|
|
|
|
|
previous.element.classList.add("fn__flex-1");
|
2022-08-17 17:22:27 +08:00
|
|
|
|
} else if (!previous.element.classList.contains("fn__flex-1")) {
|
|
|
|
|
|
// 分屏后要均分 https://github.com/siyuan-note/siyuan/issues/5657
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (layout.direction === "lr") {
|
|
|
|
|
|
previous.element.style.width = (previous.element.clientWidth + element.clientWidth) + "px";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
previous.element.style.height = (previous.element.clientHeight + element.clientHeight) + "px";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-09-08 22:04:57 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/5844
|
|
|
|
|
|
if (layout.children.length > 2 && index === 0) {
|
|
|
|
|
|
layout.children[1].resize = undefined;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
layout.children.splice(index, 1);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (element.previousElementSibling && element.previousElementSibling.classList.contains("layout__resize")) {
|
|
|
|
|
|
element.previousElementSibling.remove();
|
|
|
|
|
|
} else if (element.nextElementSibling && element.nextElementSibling.classList.contains("layout__resize")) {
|
|
|
|
|
|
element.nextElementSibling.remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
element.remove();
|
|
|
|
|
|
resizeTabs();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|