From dd5a90fdc0690b0d1ec611af2c8fe40e7036d3b2 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sat, 1 Jun 2024 00:08:35 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/10247 --- app/src/assets/scss/business/_layout.scss | 5 + app/src/boot/globalEvent/click.ts | 41 ++++++-- app/src/layout/dock/index.ts | 119 ++++++++++++++++++++-- app/src/menus/dock.ts | 1 - 4 files changed, 151 insertions(+), 15 deletions(-) diff --git a/app/src/assets/scss/business/_layout.scss b/app/src/assets/scss/business/_layout.scss index 488ffac60..b266e352c 100644 --- a/app/src/assets/scss/business/_layout.scss +++ b/app/src/assets/scss/business/_layout.scss @@ -368,6 +368,11 @@ border-top: .5px solid var(--b3-border-color); } + &__items { + min-height: 26px; + min-width: 26px; + } + svg { height: 14px; width: 14px; diff --git a/app/src/boot/globalEvent/click.ts b/app/src/boot/globalEvent/click.ts index 4c68a9c27..061296f8b 100644 --- a/app/src/boot/globalEvent/click.ts +++ b/app/src/boot/globalEvent/click.ts @@ -12,12 +12,39 @@ import {showMessage} from "../../dialog/message"; export const globalClick = (event: MouseEvent & { target: HTMLElement }) => { const ghostElement = document.getElementById("dragGhost"); if (ghostElement) { - const startElement = ghostElement.parentElement.querySelector(`[data-node-id="${ghostElement.getAttribute("data-node-id")}"]`) as HTMLElement; - startElement ? startElement.style.opacity = "" : ""; - ghostElement.parentElement.querySelectorAll(".dragover__top, .dragover__bottom, .dragover").forEach((item: HTMLElement) => { - item.classList.remove("dragover__top", "dragover__bottom", "dragover"); - item.style.opacity = ""; - }); + if (ghostElement.dataset.ghostType === "dock") { + ghostElement.parentElement.querySelectorAll(".dock__item").forEach((item: HTMLElement) => { + item.style.opacity = ""; + item.classList.add("b3-tooltips"); + }); + const original = JSON.parse(ghostElement.getAttribute("data-original")); + let dock + if (original.position === "Left") { + dock = window.siyuan.layout.leftDock; + } else if (original.position === "Right") { + dock = window.siyuan.layout.rightDock; + } else if (original.position === "Bottom") { + dock = window.siyuan.layout.bottomDock; + } + const previousElement = dock.element.querySelector(`.dock__item[data-type="${original.previousType}"]`) + const dockElement = dock.element.querySelector(`.dock__item[data-type="${original.type}"]`) + if (previousElement) { + previousElement.after(dockElement) + } else { + if (original.index === "0") { + dock.element.firstElementChild.prepend(dockElement) + } else { + dock.element.lastElementChild.previousElementSibling.prepend(dockElement) + } + } + } else { + const startElement = ghostElement.parentElement.querySelector(`[data-node-id="${ghostElement.getAttribute("data-node-id")}"]`) as HTMLElement; + startElement ? startElement.style.opacity = "" : ""; + ghostElement.parentElement.querySelectorAll(".dragover__top, .dragover__bottom, .dragover").forEach((item: HTMLElement) => { + item.classList.remove("dragover__top", "dragover__bottom", "dragover"); + item.style.opacity = ""; + }); + } ghostElement.remove(); } if (!window.siyuan.menus.menu.element.contains(event.target) && !hasClosestByAttribute(event.target, "data-menu", "true")) { @@ -48,7 +75,7 @@ export const globalClick = (event: MouseEvent & { target: HTMLElement }) => { window.siyuan.layout.rightDock.hideDock(); } - const protyleElement = hasClosestByClassName(event.target, "protyle", true); + const protyleElement = hasClosestByClassName(event.target, "protyle", true); if (protyleElement) { const wysiwygElement = protyleElement.querySelector(".protyle-wysiwyg"); if (wysiwygElement.getAttribute("data-readonly") === "true" || !wysiwygElement.contains(event.target)) { diff --git a/app/src/layout/dock/index.ts b/app/src/layout/dock/index.ts index 92590871c..35b04d44b 100644 --- a/app/src/layout/dock/index.ts +++ b/app/src/layout/dock/index.ts @@ -9,7 +9,7 @@ import {Bookmark} from "./Bookmark"; import {Tag} from "./Tag"; import {Graph} from "./Graph"; import {Model} from "../Model"; -import {setPanelFocus} from "../util"; +import {saveLayout, setPanelFocus} from "../util"; import {getDockByType, resizeTabs} from "../tabUtil"; import {Inbox} from "./Inbox"; import {Protyle} from "../../protyle"; @@ -62,7 +62,7 @@ export class Dock { } this.app = options.app; this.element = document.getElementById("dock" + options.position); - const dockClass = options.position === "Bottom" ? ' class="fn__flex"' : ""; + const dockClass = options.position === "Bottom" ? ' class="fn__flex dock__items"' : ' class="dock__items"'; this.element.innerHTML = `
`; this.position = options.position; this.pin = options.data.pin; @@ -133,6 +133,106 @@ export class Dock { target = target.parentElement; } }); + + this.element.addEventListener("mousedown", (event: MouseEvent) => { + const item = hasClosestByClassName(event.target as HTMLElement, "dock__item"); + if (!item || !item.getAttribute("data-type")) { + return; + } + const documentSelf = document; + documentSelf.ondragstart = () => false; + let ghostElement: HTMLElement; + let selectItem: HTMLElement; + documentSelf.onmousemove = (moveEvent: MouseEvent) => { + if (window.siyuan.config.readonly || + Math.abs(moveEvent.clientY - event.clientY) < 3 && Math.abs(moveEvent.clientX - event.clientX) < 3) { + return; + } + console.log(moveEvent.clientY - event.clientY) + moveEvent.preventDefault(); + moveEvent.stopPropagation(); + if (!ghostElement) { + item.style.opacity = "0.38"; + item.classList.remove("b3-tooltips"); + ghostElement = item.cloneNode(true) as HTMLElement; + ghostElement.setAttribute("data-ghost-type", "dock"); + this.element.append(ghostElement); + ghostElement.setAttribute("data-original", JSON.stringify({ + position: this.position, + index: item.getAttribute("data-index"), + previousType: item.previousElementSibling?.getAttribute("data-type"), + type: item.getAttribute("data-type"), + })); + ghostElement.setAttribute("id", "dragGhost"); + ghostElement.setAttribute("style", `background-color:var(--b3-theme-background-light);position: fixed; top: ${event.clientY}px; left: ${event.clientX}px; z-index:999997;`); + } + if (this.position === "Bottom") { + ghostElement.style.top = (moveEvent.clientY - 40) + "px"; + ghostElement.style.left = (moveEvent.clientX - 20) + "px"; + } else { + ghostElement.style.top = (moveEvent.clientY - 20) + "px"; + if (this.position === "Left") { + ghostElement.style.left = (moveEvent.clientX) + "px"; + } else { + ghostElement.style.left = (moveEvent.clientX - 40) + "px"; + } + } + + const targetItem = hasClosestByClassName(moveEvent.target as HTMLElement, "dock__item") || + hasClosestByClassName(moveEvent.target as HTMLElement, "dock__items") as HTMLElement; + if (targetItem && selectItem && targetItem.isSameNode(selectItem)) { + if (selectItem.classList.contains("dock__item")) { + const selectRect = selectItem.getBoundingClientRect(); + if (selectItem.parentElement.parentElement.id === "dockBottom") { + if (selectRect.left + selectRect.width / 2 > moveEvent.clientX) { + selectItem.before(item); + } else { + selectItem.after(item); + } + } else { + if (selectRect.top + selectRect.height / 2 > moveEvent.clientY) { + selectItem.before(item); + } else { + selectItem.after(item); + } + } + } else if (selectItem.childElementCount === 0) { + selectItem.append(item) + } else if (selectItem.childElementCount === 1 && selectItem.firstElementChild.classList.contains("dock__item--pin")) { + selectItem.insertAdjacentElement("afterbegin", item); + } + return; + } + if (!targetItem || targetItem.classList.contains("dock__item--pin") || targetItem.style.position === "fixed" || targetItem.isSameNode(item)) { + return; + } + selectItem = targetItem; + }; + + documentSelf.onmouseup = () => { + documentSelf.onmousemove = null; + documentSelf.onmouseup = null; + documentSelf.ondragstart = null; + documentSelf.onselectstart = null; + documentSelf.onselect = null; + ghostElement?.remove(); + if (item.classList.contains("b3-tooltips")) { + return; + } + item.style.opacity = ""; + item.classList.add("b3-tooltips"); + let dock + if (item.parentElement.parentElement.id === "dockBottom") { + dock = window.siyuan.layout.bottomDock; + } else if (item.parentElement.parentElement.id === "dockLeft") { + dock = window.siyuan.layout.leftDock; + } else if (item.parentElement.parentElement.id === "dockRight") { + dock = window.siyuan.layout.rightDock; + } + dock.add(item.parentElement.isSameNode(dock.element.firstElementChild) ? 0 : 1, item, item.previousElementSibling?.getAttribute("data-type")); + }; + }); + this.layout.element.addEventListener("mouseleave", (event: MouseEvent & { toElement: HTMLElement }) => { if (event.buttons !== 0 || this.pin || event.toElement?.classList.contains("b3-menu")) { return; @@ -584,7 +684,7 @@ export class Dock { this.showDock(); } - public add(index: number, sourceElement: Element) { + public add(index: number, sourceElement: Element, previousType?:string) { sourceElement.setAttribute("data-height", ""); sourceElement.setAttribute("data-width", ""); const type = sourceElement.getAttribute("data-type"); @@ -608,17 +708,22 @@ export class Dock { sourceElement.classList.remove("b3-tooltips__n", "b3-tooltips__ne", "b3-tooltips__nw", "b3-tooltips__s", "b3-tooltips__se", "b3-tooltips__sw", "b3-tooltips__e", "b3-tooltips__w"); sourceElement.classList.add(`b3-tooltips__${this.getClassDirect(index)}`); sourceElement.setAttribute("data-index", index.toString()); - if (index === 0) { - this.element.firstElementChild.insertAdjacentElement("afterbegin", sourceElement); + if (previousType) { + this.element.querySelector(`[data-type="${previousType}"]`).after(sourceElement); } else { - this.element.lastElementChild.insertAdjacentElement("afterbegin", sourceElement); + if (index === 0) { + this.element.firstElementChild.insertAdjacentElement("afterbegin", sourceElement); + } else { + this.element.lastElementChild.insertAdjacentElement("afterbegin", sourceElement); + } } this.element.classList.remove("fn__none"); resetFloatDockSize(); this.data[type] = true; if (hasActive) { - this.toggleModel(type, true); + this.toggleModel(type, true, false, false, false); } + saveLayout(); } public remove(key: string) { diff --git a/app/src/menus/dock.ts b/app/src/menus/dock.ts index 844903966..9dd7fa37d 100644 --- a/app/src/menus/dock.ts +++ b/app/src/menus/dock.ts @@ -13,7 +13,6 @@ const moveMenuItem = (label: string, target: Element) => { } else if (label.indexOf("moveToBottom") > -1) { window.siyuan.layout.bottomDock.add(label.endsWith("Left") ? 0 : 1, target); } - saveLayout(); } }); };