diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss index 5a43bb7e5..88b5fc7c0 100644 --- a/app/src/assets/scss/business/_av.scss +++ b/app/src/assets/scss/business/_av.scss @@ -68,22 +68,6 @@ font-size: 87.5%; } - &__gutters { - @extend .protyle-gutters; - top: 0; - left: -44px; - opacity: 0; - display: flex; - - &--min .av__gutter { - padding: 4px 0; - } - - svg { - height: 25px; - } - } - &__mask { position: fixed; top: 0; @@ -114,14 +98,8 @@ box-shadow: 0 -3px 0 var(--b3-theme-primary-lighter), inset 0 2px 0 var(--b3-theme-primary-lighter) !important; } - &:hover { - [data-type="block-more"] { - display: block; - } - - .av__gutters { - opacity: 1; - } + &:hover [data-type="block-more"] { + display: block; } &--select { diff --git a/app/src/boot/globalEvent/mousemove.ts b/app/src/boot/globalEvent/mousemove.ts index 2523d1bc4..edf267f37 100644 --- a/app/src/boot/globalEvent/mousemove.ts +++ b/app/src/boot/globalEvent/mousemove.ts @@ -89,11 +89,15 @@ export const windowMouseMove = (event: MouseEvent & { target: HTMLElement }, mou if (!targetBlockElement) { return; } + let rowElement: Element; + if (targetBlockElement.classList.contains("av")) { + rowElement = hasClosestByClassName(mouseElement, "av__row") as HTMLElement; + } const allModels = getAllModels(); let findNode = false; allModels.editor.find(item => { if (item.editor.protyle.wysiwyg.element.isSameNode(eventPath0)) { - item.editor.protyle.gutter.render(item.editor.protyle, targetBlockElement, item.editor.protyle.wysiwyg.element); + item.editor.protyle.gutter.render(item.editor.protyle, targetBlockElement, item.editor.protyle.wysiwyg.element, rowElement); findNode = true; return true; } @@ -102,7 +106,7 @@ export const windowMouseMove = (event: MouseEvent & { target: HTMLElement }, mou window.siyuan.blockPanels.find(item => { item.editors.find(eItem => { if (eItem.protyle.wysiwyg.element.contains(eventPath0)) { - eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element); + eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element, rowElement); findNode = true; return true; } @@ -116,7 +120,7 @@ export const windowMouseMove = (event: MouseEvent & { target: HTMLElement }, mou allModels.backlink.find(item => { item.editors.find(eItem => { if (eItem.protyle.wysiwyg.element.isSameNode(eventPath0)) { - eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element); + eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element, rowElement); findNode = true; return true; } diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index abb6ea970..8bd64a581 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -44,6 +44,8 @@ import {appearanceMenu} from "../toolbar/Font"; import {setPosition} from "../../util/setPosition"; import {avRender} from "../render/av/render"; import {emitOpenMenu} from "../../plugin/EventBus"; +import {insertAttrViewBlockAnimation} from "../render/av/row"; +import {avContextmenu} from "../render/av/action"; export class Gutter { public element: HTMLElement; @@ -183,6 +185,43 @@ export class Gutter { window.siyuan.menus.menu.remove(); return; } + if (buttonElement.dataset.type === "NodeAttributeViewRowMenu" || buttonElement.dataset.type === "NodeAttributeViewRow") { + const rowElement = protyle.wysiwyg.element.querySelector(`.av__row[data-id="${buttonElement.dataset.nodeId}"]`) as HTMLElement; + if (!rowElement) { + return; + } + const blockElement = hasClosestBlock(rowElement) + if (!blockElement) { + return; + } + blockElement.querySelector(".av__cell--select")?.classList.remove("av__cell--select"); + if (buttonElement.dataset.type === "NodeAttributeViewRow") { + const avID = blockElement.getAttribute("data-av-id"); + const srcIDs = [Lute.NewNodeID()]; + const previousID = event.altKey ? (rowElement.previousElementSibling.getAttribute("data-id") || "") : buttonElement.dataset.nodeId; + transaction(protyle, [{ + action: "insertAttrViewBlock", + avID, + previousID, + srcIDs, + isDetached: true, + }], [{ + action: "removeAttrViewBlock", + srcIDs, + avID, + }]); + insertAttrViewBlockAnimation(blockElement, srcIDs, previousID, avID); + } else { + const gutterRect = buttonElement.getBoundingClientRect(); + avContextmenu(protyle, rowElement, { + x: gutterRect.left, + y: gutterRect.bottom, + w: gutterRect.width, + h: gutterRect.height + }); + } + return; + } if (isOnlyMeta(event)) { zoomOut({protyle, id}); } else if (event.altKey) { @@ -1805,7 +1844,7 @@ export class Gutter { }; } - public render(protyle: IProtyle, element: Element, wysiwyg: HTMLElement) { + public render(protyle: IProtyle, element: Element, wysiwyg: HTMLElement, target?: Element) { // https://github.com/siyuan-note/siyuan/issues/4659 const titleElement = wysiwyg.parentElement.querySelector(".protyle-title__input"); if (titleElement && titleElement.getAttribute("data-render") !== "true") { @@ -1830,6 +1869,15 @@ export class Gutter { if (isShow) { type = nodeElement.getAttribute("data-type"); } + if (type === "NodeAttributeView" && target) { + const rowElement = hasClosestByClassName(target, "av__row"); + if (rowElement && !rowElement.classList.contains("av__row--header")) { + element = rowElement; + html = ` +` + break; + } + } if (index === 0) { // 不单独显示,要不然在块的间隔中,gutter 会跳来跳去的 if (["NodeBlockquote", "NodeList", "NodeSuperBlock"].includes(type)) { @@ -1924,8 +1972,9 @@ data-type="fold"> Math.floor(window.siyuan.config.editor.fontSize * 1.625) + 8 && rect.height < Math.floor(window.siyuan.config.editor.fontSize * 1.625) * 2 + 8)) { marginHeight = (rect.height - this.element.clientHeight) / 2; - } else if ((nodeElement.getAttribute("data-type") === "NodeAttributeView" || - element.getAttribute("data-type") === "NodeAttributeView") && contentTop < rect.top) { + } else if (!element.classList.contains("av__row") && + (nodeElement.getAttribute("data-type") === "NodeAttributeView" || element.getAttribute("data-type") === "NodeAttributeView") && + contentTop < rect.top) { marginHeight = 8; } this.element.style.top = `${Math.max(rect.top, contentTop) + marginHeight}px`; diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index 5070d92f7..6a2dc929c 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -159,39 +159,6 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle event.preventDefault(); event.stopPropagation(); return true; - } else if (target.classList.contains("av__gutter")) { - const rowElement = hasClosestByClassName(target, "av__row"); - if (!rowElement) { - return; - } - if (target.dataset.action === "add") { - const avID = blockElement.getAttribute("data-av-id"); - const srcIDs = [Lute.NewNodeID()]; - const previousID = event.altKey ? (rowElement.previousElementSibling.getAttribute("data-id") || "") : rowElement.getAttribute("data-id"); - transaction(protyle, [{ - action: "insertAttrViewBlock", - avID, - previousID, - srcIDs, - isDetached: true, - }], [{ - action: "removeAttrViewBlock", - srcIDs, - avID, - }]); - insertAttrViewBlockAnimation(blockElement, srcIDs, previousID, avID); - } else { - const gutterRect = target.getBoundingClientRect(); - avContextmenu(protyle, rowElement, { - x: gutterRect.left, - y: gutterRect.bottom, - w: gutterRect.width, - h: gutterRect.height - }); - } - event.preventDefault(); - event.stopPropagation(); - return true; } else if (target.classList.contains("av__firstcol")) { window.siyuan.menus.menu.remove(); selectRow(target, "toggle"); diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts index 079d08147..4464cb943 100644 --- a/app/src/protyle/render/av/render.ts +++ b/app/src/protyle/render/av/render.ts @@ -120,11 +120,7 @@ style="width: ${column.width || "200px"}">${getCalcValue(column) || '`; // body data.rows.forEach((row: IAVRow) => { - tableHTML += `
-
- - -
`; + tableHTML += `
`; if (pinIndex > -1) { tableHTML += '
'; } else { diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index d9beba869..76f20d87b 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -379,7 +379,6 @@ export class WYSIWYG { } const target = event.target as HTMLElement; if (hasClosestByClassName(target, "protyle-action") || - hasClosestByClassName(target, "av__gutters") || hasClosestByClassName(target, "av__cellheader")) { return; } @@ -1511,22 +1510,7 @@ export class WYSIWYG { if (embedElement) { protyle.gutter.render(protyle, embedElement, this.element); } else { - // database 行块标 - const rowElement = hasClosestByClassName(event.target, "av__row"); - if (rowElement && rowElement.dataset.id) { - const guttersElement = rowElement.querySelector(".av__gutters"); - if (guttersElement) { - guttersElement.classList.remove("av__gutters--min"); - let guttersLeft = rowElement.parentElement.parentElement.getBoundingClientRect().left - guttersElement.clientWidth; - const contentLeft = protyle.contentElement.getBoundingClientRect().left; - if (guttersLeft < contentLeft) { - guttersLeft = contentLeft; - guttersElement.classList.add("av__gutters--min"); - } - guttersElement.setAttribute("style", `left:${guttersLeft}px;top:${rowElement.getBoundingClientRect().top}px`); - } - } - protyle.gutter.render(protyle, nodeElement, this.element); + protyle.gutter.render(protyle, nodeElement, this.element, event.target); } } });