From f8315fb0ba6316a43390a52caf4fb9d96929f4a7 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Thu, 26 Oct 2023 23:17:27 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/9502 --- app/src/assets/scss/protyle/_wysiwyg.scss | 10 +++ app/src/protyle/util/editorCommonEvent.ts | 101 +++++++++++++++------- 2 files changed, 80 insertions(+), 31 deletions(-) diff --git a/app/src/assets/scss/protyle/_wysiwyg.scss b/app/src/assets/scss/protyle/_wysiwyg.scss index dac7c8689..14339beac 100644 --- a/app/src/assets/scss/protyle/_wysiwyg.scss +++ b/app/src/assets/scss/protyle/_wysiwyg.scss @@ -51,6 +51,16 @@ &.list { padding-left: 0; + + .dragover { + &__top:not(.av__row) { + box-shadow: 0 -3px 0 var(--b3-theme-primary-lighter), inset 0px 1px 0 var(--b3-theme-primary-lighter) !important; + } + + &__bottom:not(.av__row) { + box-shadow: 0 3px 0 var(--b3-theme-primary-lighter), inset 0px -1px 0 var(--b3-theme-primary-lighter) !important; + } + } } &.li { diff --git a/app/src/protyle/util/editorCommonEvent.ts b/app/src/protyle/util/editorCommonEvent.ts index 1eaa8f73a..24356a871 100644 --- a/app/src/protyle/util/editorCommonEvent.ts +++ b/app/src/protyle/util/editorCommonEvent.ts @@ -1,5 +1,11 @@ import {focusBlock, focusByRange, getRangeByPoint} from "./selection"; -import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName, hasClosestByTag} from "./hasClosest"; +import { + hasClosestBlock, + hasClosestByAttribute, + hasClosestByClassName, + hasClosestByTag, + hasTopClosestByAttribute +} from "./hasClosest"; import {Constants} from "../../constants"; import {paste} from "./paste"; import {cancelSB, genEmptyElement, genSBElement} from "../../block/util"; @@ -761,8 +767,12 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { gutterType = item.type; } } - const targetElement = (gutterType.startsWith(`application/siyuan-gutternodeattributeview${Constants.ZWSP}col`) ? hasClosestByClassName(event.target, "av__cell") : hasClosestByClassName(event.target, "av__row")) || - hasClosestBlock(event.target); + const targetElement = editorElement.querySelector(".dragover__left, .dragover__right, .dragover__bottom, .dragover__top"); + if (targetElement) { + targetElement.classList.remove("protyle-wysiwyg--select"); + targetElement.removeAttribute("select-start"); + targetElement.removeAttribute("select-end"); + } if (gutterType) { // gutter 或反链面板拖拽 const sourceElements: Element[] = []; @@ -822,7 +832,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { hideElements(["gutter"], protyle); const targetClass = targetElement.className.split(" "); - targetElement.classList.remove("dragover__bottom", "dragover__top", "dragover__left", "dragover__right", "protyle-wysiwyg--select"); + targetElement.classList.remove("dragover__bottom", "dragover__top", "dragover__left", "dragover__right"); if (targetElement.classList.contains("av__cell")) { const blockElement = hasClosestBlock(targetElement); @@ -975,7 +985,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { }, Constants.TIMEOUT_LOAD); }); } - targetElement.classList.remove("dragover__bottom", "dragover__top", "dragover__left", "dragover__right", "protyle-wysiwyg--select"); + targetElement.classList.remove("dragover__bottom", "dragover__top", "dragover__left", "dragover__right"); } else if (!window.siyuan.dragElement && (event.dataTransfer.types[0] === "Files" || event.dataTransfer.types.includes("text/html"))) { // 外部文件拖入编辑器中或者编辑器内选中文字拖拽 focusByRange(getRangeByPoint(event.clientX, event.clientY)); @@ -1018,6 +1028,8 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { const targetElement = hasClosestBlock(event.target); if (targetElement) { targetElement.classList.remove("dragover__top", "protyle-wysiwyg--select", "dragover__bottom", "dragover__left", "dragover__right"); + targetElement.removeAttribute("select-start"); + targetElement.removeAttribute("select-end"); } event.preventDefault(); return; @@ -1037,17 +1049,65 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { targetElement = false; } } - if (!targetElement || targetElement?.classList.contains("av")) { + const point = {x: event.clientX, y: event.clientY, className: ""}; + if (!targetElement) { + const editorRect = editorElement.getBoundingClientRect(); + const editorPosition = { + left: editorRect.left + parseInt(editorElement.style.paddingLeft), + right: editorRect.right - parseInt(editorElement.style.paddingRight), + top: editorRect.top - 16, + }; + if (event.clientY > editorElement.lastElementChild.getBoundingClientRect().bottom) { + // 命中底部 + targetElement = editorElement.lastElementChild as HTMLElement; + point.className = "dragover__bottom" + } else if (event.clientY < editorElement.firstElementChild.getBoundingClientRect().top) { + // 命中顶部 + targetElement = editorElement.firstElementChild as HTMLElement + point.className = "dragover__top" + } else { + if (event.clientX < editorPosition.left) { + // 左侧 + point.x = editorPosition.left; + point.className = "dragover__left"; + } else if (event.clientX > editorPosition.right) { + // 右侧 + point.x = editorPosition.right - 6; + point.className = "dragover__right"; + } + targetElement = document.elementFromPoint(point.x, point.y) as HTMLElement; + if (targetElement.classList.contains("protyle-wysiwyg")) { + // 命中间隙 + targetElement = document.elementFromPoint(point.x, point.y - 6) as HTMLElement; + } + targetElement = hasTopClosestByAttribute(targetElement, "data-node-id", null); + } + } else if (targetElement && targetElement.classList.contains("list")) { + if (gutterType && gutterType.replace(Constants.SIYUAN_DROP_GUTTER, "").split(Constants.ZWSP)[0] !== "nodelistitem") { + targetElement = hasClosestBlock(document.elementFromPoint(event.clientX, event.clientY - 6)); + } else { + targetElement = hasClosestByClassName(document.elementFromPoint(event.clientX, event.clientY - 6), "li"); + } + } + if (!targetElement || targetElement.classList.contains("av")) { return; } const fileTreeIds = (event.dataTransfer.types.includes(Constants.SIYUAN_DROP_FILE) && window.siyuan.dragElement) ? window.siyuan.dragElement.innerText : ""; if (targetElement && dragoverElement && targetElement.isSameNode(dragoverElement)) { // 性能优化,目标为同一个元素不再进行校验 const nodeRect = targetElement.getBoundingClientRect(); - targetElement.classList.remove("protyle-wysiwyg--select", "dragover__top", "dragover__bottom", "dragover__left", "dragover__right"); + editorElement.querySelectorAll(".dragover__left, .dragover__right, .dragover__bottom, .dragover__top").forEach((item: HTMLElement) => { + item.classList.remove("dragover__top", "dragover__bottom", "dragover__left", "dragover__right", "protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); + }); if (targetElement.getAttribute("data-type") === "NodeAttributeView" && hasClosestByTag(event.target, "TD")) { return; } + if (point.className) { + targetElement.classList.add(point.className) + return; + } if (targetElement.getAttribute("data-type") === "NodeListItem" || fileTreeIds.indexOf("-") > -1) { if (event.clientY > nodeRect.top + nodeRect.height / 2) { targetElement.classList.add("dragover__bottom"); @@ -1138,29 +1198,8 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { } }); editorElement.addEventListener("dragleave", (event: DragEvent & { target: HTMLElement }) => { - let nodeElement = hasClosestByClassName(event.target, "av__row") || hasClosestBlock(event.target); - if (nodeElement && !nodeElement.classList.contains("av")) { - let gutterType = ""; - for (const item of event.dataTransfer.items) { - if (item.type.startsWith(Constants.SIYUAN_DROP_GUTTER)) { - gutterType = item.type; - } - } - nodeElement.classList.remove("dragover__top", "dragover__bottom", "dragover__left", "dragover__right"); - if (nodeElement.classList.contains("av__row")) { - nodeElement.classList.remove("protyle-wysiwyg--select"); - if (nodeElement.classList.contains("av__row--header")) { - nodeElement = hasClosestByClassName(event.target, "av__cell"); - if (nodeElement) { - nodeElement.classList.remove("protyle-wysiwyg--select", "dragover__left", "dragover__right"); - } - } - } else if (gutterType.indexOf(nodeElement.getAttribute("data-node-id")) === -1) { - // 选中的元素不应移除,否则拖拽 gutter 经过选中的元素,该元素就会被取消选中 - nodeElement.classList.remove("protyle-wysiwyg--select"); - nodeElement.removeAttribute("select-start"); - nodeElement.removeAttribute("select-end"); - } - } + editorElement.querySelectorAll(".dragover__left, .dragover__right, .dragover__bottom, .dragover__top").forEach((item: HTMLElement) => { + item.classList.remove("dragover__top", "dragover__bottom", "dragover__left", "dragover__right"); + }); }); };