From e9c8cd0e0d3bd0ff72ddb4c416c811d1949b8a19 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Mon, 18 Nov 2024 11:55:18 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/11053 --- app/src/block/popover.ts | 7 +-- app/src/protyle/render/av/col.ts | 86 +++++++++++++++++++------- app/src/protyle/render/av/render.ts | 11 ++-- app/src/protyle/render/av/view.ts | 17 +++-- app/src/protyle/wysiwyg/transaction.ts | 2 +- app/src/types/index.d.ts | 2 + 6 files changed, 87 insertions(+), 38 deletions(-) diff --git a/app/src/block/popover.ts b/app/src/block/popover.ts index ba917e5e3..ec287d47f 100644 --- a/app/src/block/popover.ts +++ b/app/src/block/popover.ts @@ -28,12 +28,7 @@ export const initBlockPopover = (app: App) => { let tooltipClass = ""; let tip = aElement.getAttribute("aria-label"); if (aElement.classList.contains("av__cell")) { - if (aElement.classList.contains("av__cell--header")) { - const textElement = aElement.querySelector(".av__celltext"); - if (textElement.scrollWidth > textElement.clientWidth + 2) { - tip = getCellText(aElement); - } - } else { + if (!aElement.classList.contains("av__cell--header")) { if (aElement.firstElementChild?.getAttribute("data-type") === "url") { if (aElement.firstElementChild.textContent.indexOf("...") > -1) { tip = Lute.EscapeHTMLStr(aElement.firstElementChild.getAttribute("data-href")); diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts index 58d1db549..b653ac93d 100644 --- a/app/src/protyle/render/av/col.ts +++ b/app/src/protyle/render/av/col.ts @@ -15,6 +15,7 @@ import * as dayjs from "dayjs"; import {setPosition} from "../../../util/setPosition"; import {duplicateNameAddOne} from "../../../util/functions"; import {Dialog} from "../../../dialog"; +import {escapeAttr} from "../../../util/escape"; export const duplicateCol = (options: { protyle: IProtyle, @@ -575,35 +576,60 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen const avID = blockElement.getAttribute("data-av-id"); const blockID = blockElement.getAttribute("data-node-id"); const oldValue = cellElement.querySelector(".av__celltext").textContent.trim(); + const oldDesc = cellElement.dataset.desc; const menu = new Menu("av-header-cell", () => { const newValue = (menu.element.querySelector(".b3-text-field") as HTMLInputElement).value; - if (newValue === oldValue) { - return; + if (newValue !== oldValue) { + transaction(protyle, [{ + action: "updateAttrViewCol", + id: colId, + avID, + name: newValue, + type, + }], [{ + action: "updateAttrViewCol", + id: colId, + avID, + name: oldValue, + type, + }]); + updateAttrViewCellAnimation(blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {name: newValue}); + } + const newDesc = menu.element.querySelector("textarea").value; + if (newDesc !== oldDesc) { + transaction(protyle, [{ + action: "setAttrViewColDesc", + id: colId, + avID, + data: newDesc, + }], [{ + action: "setAttrViewColDesc", + id: colId, + avID, + data: oldDesc, + }]); } - transaction(protyle, [{ - action: "updateAttrViewCol", - id: colId, - avID, - name: newValue, - type, - }], [{ - action: "updateAttrViewCol", - id: colId, - avID, - name: oldValue, - type, - }]); - updateAttrViewCellAnimation(blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {name: newValue}); // https://github.com/siyuan-note/siyuan/issues/9862 focusBlock(blockElement); }); menu.addItem({ - iconHTML: `${cellElement.dataset.icon ? unicode2Emoji(cellElement.dataset.icon) : ``}`, + iconHTML: '', type: "readonly", - label: ``, + label: `
+
+ ${cellElement.dataset.icon ? unicode2Emoji(cellElement.dataset.icon) : ``} +
+ + +
+
+
+
+ +
+
`, bind(element) { const iconElement = element.querySelector(".b3-menu__avemoji") as HTMLElement; - iconElement.setAttribute("data-icon", cellElement.dataset.icon); iconElement.addEventListener("click", (event) => { const rect = iconElement.getBoundingClientRect(); openEmojiPanel("", "av", { @@ -623,14 +649,32 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen avID, data: cellElement.dataset.icon, }]); - iconElement.setAttribute("data-icon", unicode); + iconElement.dataset.icon = unicode; iconElement.innerHTML = unicode ? unicode2Emoji(unicode) : ``; updateAttrViewCellAnimation(blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {icon: unicode}); }, iconElement.querySelector("img")); event.preventDefault(); event.stopPropagation(); }); - element.querySelector("input").addEventListener("keydown", (event: KeyboardEvent) => { + const inputElement = element.querySelector("input"); + inputElement.addEventListener("keydown", (event: KeyboardEvent) => { + if (event.isComposing) { + return; + } + if (event.key === "Enter") { + menu.close(); + event.preventDefault(); + } + }); + const descElement = element.querySelector('textarea'); + inputElement.nextElementSibling.addEventListener("click", () => { + const descPanelElement = descElement.parentElement + descPanelElement.classList.toggle("fn__none"); + if (!descPanelElement.classList.contains("fn__none")) { + descElement.focus(); + } + }) + descElement.addEventListener("keydown", (event: KeyboardEvent) => { if (event.isComposing) { return; } diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts index 8cbe910eb..1559d14bc 100644 --- a/app/src/protyle/render/av/render.ts +++ b/app/src/protyle/render/av/render.ts @@ -10,6 +10,7 @@ import {getCalcValue} from "./calc"; import {renderAVAttribute} from "./blockAttr"; import {showMessage} from "../../../dialog/message"; import {addClearButton} from "../../../util/addClearButton"; +import {escapeAriaLabel, escapeAttr, escapeHtml} from "../../../util/escape"; export const avRender = (element: Element, protyle: IProtyle, cb?: () => void, viewID?: string) => { let avElements: Element[] = []; @@ -130,11 +131,13 @@ export const avRender = (element: Element, protyle: IProtyle, cb?: () => void, v if (column.hidden) { return; } - tableHTML += `
" style="width: ${column.width || "200px"};"> ${column.icon ? unicode2Emoji(column.icon, "av__cellheadericon", true) : ``} - ${column.name} + ${escapeHtml(column.name)} ${column.pin ? '' : ""}
`; @@ -199,9 +202,9 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex)} let tabHTML = ""; let viewData: IAVView; response.data.views.forEach((item: IAVView) => { - tabHTML += `
" class="ariaLabel item${item.id === response.data.viewID ? " item--focus" : ""}"> + tabHTML += `
" class="ariaLabel item${item.id === response.data.viewID ? " item--focus" : ""}"> ${item.icon ? unicode2Emoji(item.icon, "item__graphic", true) : ''} - ${item.name} + ${escapeHtml(item.name)}
`; if (item.id === response.data.viewID) { viewData = item; diff --git a/app/src/protyle/render/av/view.ts b/app/src/protyle/render/av/view.ts index 22dd0e8e3..2d24a8065 100644 --- a/app/src/protyle/render/av/view.ts +++ b/app/src/protyle/render/av/view.ts @@ -6,6 +6,7 @@ import {focusBlock} from "../../util/selection"; import {Constants} from "../../../constants"; import {upDownHint} from "../../../util/upDownHint"; import {avRender} from "./render"; +import {escapeAriaLabel, escapeAttr} from "../../../util/escape"; export const openViewMenu = (options: { protyle: IProtyle, blockElement: HTMLElement, element: HTMLElement }) => { if (options.protyle.disabled) { @@ -120,9 +121,13 @@ export const bindViewEvent = (options: { } }); inputElement.select(); - const descElement = options.menuElement.querySelector('.b3-text-field[data-type="desc"]') as HTMLInputElement; + const descElement = options.menuElement.querySelector('.b3-text-field[data-type="desc"]') as HTMLTextAreaElement; inputElement.nextElementSibling.addEventListener("click", () => { - descElement.parentElement.classList.toggle("fn__none"); + const descPanelElement = descElement.parentElement + descPanelElement.classList.toggle("fn__none"); + if (!descPanelElement.classList.contains("fn__none")) { + descElement.focus(); + } }) descElement.addEventListener("blur", () => { if (descElement.value !== descElement.dataset.value) { @@ -196,14 +201,14 @@ export const getViewHTML = (data: IAV) => {
${view.icon ? unicode2Emoji(view.icon) : ''} -
- - +
+ +
- +
diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts index 6732a78fa..b9a38a450 100644 --- a/app/src/protyle/wysiwyg/transaction.ts +++ b/app/src/protyle/wysiwyg/transaction.ts @@ -743,7 +743,7 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo: "replaceAttrViewBlock", "updateAttrViewColTemplate", "setAttrViewColPin", "addAttrViewView", "setAttrViewColIcon", "removeAttrViewView", "setAttrViewViewName", "setAttrViewViewIcon", "duplicateAttrViewView", "sortAttrViewView", "updateAttrViewColRelation", "setAttrViewPageSize", "updateAttrViewColRollup", "sortAttrViewKey", - "duplicateAttrViewKey", "setAttrViewViewDesc"].includes(operation.action)) { + "duplicateAttrViewKey", "setAttrViewViewDesc", "setAttrViewColDesc"].includes(operation.action)) { refreshAV(protyle, operation); return; } diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts index a2ee8c0c9..defcbeb53 100644 --- a/app/src/types/index.d.ts +++ b/app/src/types/index.d.ts @@ -54,6 +54,7 @@ type TOperation = | "setAttrViewColDate" | "unbindAttrViewBlock" | "setAttrViewViewDesc" + | "setAttrViewColDesc" type TBazaarType = "templates" | "icons" | "widgets" | "themes" | "plugins" type TCardType = "doc" | "notebook" | "all" type TEventBus = "ws-main" | "sync-start" | "sync-end" | "sync-fail" | @@ -799,6 +800,7 @@ interface IAVColumn { icon: string, id: string, name: string, + desc: string, wrap: boolean, pin: boolean, hidden: boolean,