Explorar o código

:art: fix https://github.com/siyuan-note/siyuan/issues/10264

Vanessa hai 1 ano
pai
achega
fa4d66dcce

+ 12 - 0
app/src/protyle/render/av/cell.ts

@@ -130,6 +130,18 @@ export const genCellValue = (colType: TAVCol, value: string | any) => {
                     checked: true
                 }
             };
+        } else if (colType === "date") {
+            cellValue = {
+                type: colType,
+                date: {
+                    content: null,
+                    isNotEmpty: false,
+                    content2: null,
+                    isNotEmpty2: false,
+                    hasEndDate: false,
+                    isNotTime: true,
+                }
+            };
         }
     } else if (typeof value === "undefined" || !value) {
         if (colType === "number") {

+ 5 - 5
app/src/protyle/render/av/keydown.ts

@@ -23,6 +23,11 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
         if (!rowElement) {
             return false;
         }
+        if (event.key === "Backspace" || event.key === "Delete") {
+            updateCellsValue(protyle, nodeElement, undefined, Array.from(nodeElement.querySelectorAll(".av__cell--active, .av__cell--select")));
+            event.preventDefault();
+            return true;
+        }
         // 复制、粘贴
         if (!event.ctrlKey && !event.metaKey) {
             nodeElement.querySelectorAll(".av__cell--active").forEach(item => {
@@ -41,11 +46,6 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
             event.preventDefault();
             return true;
         }
-        if (event.key === "Backspace" || event.key === "Delete") {
-            updateCellsValue(protyle, nodeElement, undefined, [selectCellElement]);
-            event.preventDefault();
-            return true;
-        }
         let newCellElement;
         if (event.key === "ArrowLeft" || matchHotKey("⇧⇥", event)) {
             const previousRowElement = rowElement.previousElementSibling;

+ 106 - 4
app/src/protyle/util/insertHTML.ts

@@ -6,11 +6,113 @@ import {fixTableRange, focusBlock, focusByWbr, getEditorRange} from "./selection
 import {Constants} from "../../constants";
 import {highlightRender} from "../render/highlightRender";
 import {scrollCenter} from "../../util/highlightById";
-import {updateAVName} from "../render/av/action";
-import {updateCellsValue} from "../render/av/cell";
+import {updateAttrViewCellAnimation, updateAVName} from "../render/av/action";
+import {
+    genCellValue,
+    genCellValueByElement,
+    getTypeByCellElement,
+    updateCellsValue
+} from "../render/av/cell";
 import {input} from "../wysiwyg/input";
+import {objEquals} from "../../util/functions";
 
-const processAV = (range: Range, html: string, protyle: IProtyle, blockElement: Element) => {
+const processAV = (range: Range, html: string, protyle: IProtyle, blockElement: HTMLElement) => {
+    if (html.endsWith("]") && html.startsWith("[")) {
+        try {
+            const values = JSON.parse(html);
+            const cellElements: Element[] = Array.from(blockElement.querySelectorAll(".av__cell--active, .av__cell--select")) || [];
+            if (cellElements.length === 0) {
+                blockElement.querySelectorAll(".av__row--select:not(.av__row--header)").forEach(rowElement => {
+                    rowElement.querySelectorAll(".av__cell").forEach(cellElement => {
+                        cellElements.push(cellElement);
+                    });
+                });
+            }
+            const doOperations: IOperation[] = [];
+            const undoOperations: IOperation[] = [];
+
+            const avID = blockElement.dataset.avId;
+            const id = blockElement.dataset.nodeId;
+            cellElements.forEach((item: HTMLElement, elementIndex) => {
+                let cellValue: IAVCellValue = values[elementIndex]
+                if (!cellValue) {
+                    return;
+                }
+                const rowElement = hasClosestByClassName(item, "av__row");
+                if (!rowElement) {
+                    return;
+                }
+                if (!blockElement.contains(item)) {
+                    item = cellElements[elementIndex] = blockElement.querySelector(`.av__row[data-id="${rowElement.dataset.id}"] .av__cell[data-col-id="${item.dataset.colId}"]`) as HTMLElement;
+                }
+                const type = getTypeByCellElement(item) || item.dataset.type as TAVCol;
+                if (["created", "updated", "template", "rollup"].includes(type)) {
+                    return;
+                }
+
+                const rowID = rowElement.getAttribute("data-id");
+                const cellId = item.getAttribute("data-id");
+                const colId = item.getAttribute("data-col-id");
+
+                const oldValue = genCellValueByElement(type, item);
+                if (cellValue.type !== type) {
+                    if (type === "date") {
+                        // 类型不能转换时就不进行替换
+                        return;
+                    }
+                    const content = cellValue[cellValue.type as "text"].content
+                    if (!content) {
+                        return;
+                    }
+                    cellValue = genCellValue(type, cellValue[cellValue.type as "text"].content.toString());
+                } else if (cellValue.type === "block") {
+                    cellValue.isDetached = true;
+                    delete cellValue.block.id;
+                }
+                cellValue.id = cellId;
+                if ((cellValue.type === "date" && typeof cellValue.date === "string") ||
+                    (cellValue.type === "relation" && typeof cellValue.relation === "string")) {
+                    return;
+                }
+                if (objEquals(cellValue, oldValue)) {
+                    return;
+                }
+                doOperations.push({
+                    action: "updateAttrViewCell",
+                    id: cellId,
+                    avID,
+                    keyID: colId,
+                    rowID,
+                    data: cellValue
+                });
+                undoOperations.push({
+                    action: "updateAttrViewCell",
+                    id: cellId,
+                    avID,
+                    keyID: colId,
+                    rowID,
+                    data: oldValue
+                });
+                updateAttrViewCellAnimation(item, cellValue);
+            });
+            if (doOperations.length > 0) {
+                doOperations.push({
+                    action: "doUpdateUpdated",
+                    id,
+                    data: dayjs().format("YYYYMMDDHHmmss"),
+                });
+                undoOperations.push({
+                    action: "doUpdateUpdated",
+                    id,
+                    data: blockElement.getAttribute("updated"),
+                });
+                transaction(protyle, doOperations, undoOperations);
+            }
+            return;
+        } catch (e) {
+            console.warn("insert cell: JSON.parse error")
+        }
+    }
     const text = protyle.lute.BlockDOM2EscapeMarkerContent(html);
     const cellsElement: HTMLElement[] = Array.from(blockElement.querySelectorAll(".av__cell--select"));
     const rowsElement = blockElement.querySelector(".av__row--select");
@@ -56,7 +158,7 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
     }
     if (blockElement.classList.contains("av")) {
         range.deleteContents();
-        processAV(range, html, protyle, blockElement);
+        processAV(range, html, protyle, blockElement as HTMLElement);
         return;
     }
     let id = blockElement.getAttribute("data-node-id");

+ 2 - 2
app/src/protyle/wysiwyg/index.ts

@@ -374,7 +374,7 @@ export class WYSIWYG {
             textPlain = textPlain || protyle.lute.BlockDOM2StdMd(html).trimEnd();
             textPlain = textPlain.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
             event.clipboardData.setData("text/plain", textPlain);
-            event.clipboardData.setData("text/html", selectAVElement ? html : protyle.lute.BlockDOM2HTML(html));
+            event.clipboardData.setData("text/html", protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
             event.clipboardData.setData("text/siyuan", html);
         });
 
@@ -1452,7 +1452,7 @@ export class WYSIWYG {
             }
             textPlain = textPlain.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
             event.clipboardData.setData("text/plain", textPlain);
-            event.clipboardData.setData("text/html", selectAVElement ? html : protyle.lute.BlockDOM2HTML(html));
+            event.clipboardData.setData("text/html", protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
             event.clipboardData.setData("text/siyuan", html);
         });
 

+ 20 - 12
app/src/util/highlightById.ts

@@ -39,19 +39,27 @@ export const highlightById = (protyle: IProtyle, id: string, top = false) => {
 };
 
 export const scrollCenter = (protyle: IProtyle, nodeElement?: Element, top = false, behavior: ScrollBehavior = "auto") => {
-    if (!protyle.disabled && !top && getSelection().rangeCount > 0 && hasClosestBlock(getSelection().getRangeAt(0).startContainer)) {
-        const editorElement = protyle.contentElement;
-        const cursorTop = getSelectionPosition(editorElement).top - editorElement.getBoundingClientRect().top;
-        let top = 0;
-        if (cursorTop < 0) {
-            top = editorElement.scrollTop + cursorTop;
-        } else if (cursorTop > editorElement.clientHeight - 74) {   // 74 = 移动端底部 + 段落块高度
-            top = editorElement.scrollTop + (cursorTop + 74 - editorElement.clientHeight);
+    if (!protyle.disabled && !top && getSelection().rangeCount > 0) {
+        const blockElement = hasClosestBlock(getSelection().getRangeAt(0).startContainer);
+        if (blockElement) {
+            // undo 时禁止数据库滚动
+            if (blockElement.classList.contains("av") && blockElement.dataset.render === "true" &&
+                (blockElement.querySelector(".av__row--header").getAttribute("style").indexOf("transform") > -1 || blockElement.querySelector(".av__row--footer").getAttribute("style").indexOf("transform") > -1)) {
+                return;
+            }
+            const editorElement = protyle.contentElement;
+            const cursorTop = getSelectionPosition(editorElement).top - editorElement.getBoundingClientRect().top;
+            let scrollTop = 0;
+            if (cursorTop < 0) {
+                scrollTop = editorElement.scrollTop + cursorTop;
+            } else if (cursorTop > editorElement.clientHeight - 74) {   // 74 = 移动端底部 + 段落块高度
+                scrollTop = editorElement.scrollTop + (cursorTop + 74 - editorElement.clientHeight);
+            }
+            if (scrollTop !== 0) {
+                editorElement.scroll({top: scrollTop, behavior});
+            }
+            return;
         }
-        if (top !== 0) {
-            editorElement.scroll({top, behavior});
-        }
-        return;
     }
 
     if (!nodeElement) {