diff --git a/app/src/plugin/API.ts b/app/src/plugin/API.ts index 7f7872c97..18e3f8503 100644 --- a/app/src/plugin/API.ts +++ b/app/src/plugin/API.ts @@ -2,7 +2,6 @@ import {confirmDialog} from "../dialog/confirmDialog"; import {Plugin} from "./index"; import {showMessage} from "../dialog/message"; import {Dialog} from "../dialog"; -import {Menu as SiyuanMenu} from "../menus/Menu"; import {fetchGet, fetchPost, fetchSyncPost} from "../util/fetch"; import {getBackend, getFrontend} from "../util/functions"; /// #if !MOBILE @@ -14,64 +13,7 @@ import {App} from "../index"; import {Constants} from "../constants"; import {Model} from "../layout/Model"; import {Setting} from "./Setting"; - -export class Menu { - private menu: SiyuanMenu; - public isOpen: boolean; - - constructor(id?: string, closeCB?: () => void) { - this.menu = window.siyuan.menus.menu; - this.isOpen = false; - if (id) { - const dataName = this.menu.element.getAttribute("data-name"); - if (dataName && dataName === id) { - this.isOpen = true; - } - } - this.menu.remove(); - if (!this.isOpen) { - this.menu.element.setAttribute("data-name", id); - this.menu.removeCB = closeCB; - } - } - - showSubMenu(subMenuElement: HTMLElement) { - this.menu.showSubMenu(subMenuElement); - } - - addItem(option: IMenu) { - if (this.isOpen) { - return; - } - return this.menu.addItem(option); - } - - addSeparator(index?: number) { - if (this.isOpen) { - return; - } - this.menu.addSeparator(index); - } - - open(options: { x: number, y: number, h?: number, w?: number, isLeft?: boolean }) { - if (this.isOpen) { - return; - } - this.menu.popup(options, options.isLeft); - } - - fullscreen(position: "bottom" | "all" = "all") { - if (this.isOpen) { - return; - } - this.menu.fullscreen(position); - this.menu.element.style.zIndex = "310"; - } - - close() { - this.menu.remove(); - } -} +import {Menu} from "./Meun"; let openTab; /// #if MOBILE diff --git a/app/src/plugin/Meun.ts b/app/src/plugin/Meun.ts new file mode 100644 index 000000000..99983c7c6 --- /dev/null +++ b/app/src/plugin/Meun.ts @@ -0,0 +1,59 @@ +import {Menu as SiyuanMenu} from "../menus/Menu"; + +export class Menu { + private menu: SiyuanMenu; + public isOpen: boolean; + + constructor(id?: string, closeCB?: () => void) { + this.menu = window.siyuan.menus.menu; + this.isOpen = false; + if (id) { + const dataName = this.menu.element.getAttribute("data-name"); + if (dataName && dataName === id) { + this.isOpen = true; + } + } + this.menu.remove(); + if (!this.isOpen) { + this.menu.element.setAttribute("data-name", id); + this.menu.removeCB = closeCB; + } + } + + showSubMenu(subMenuElement: HTMLElement) { + this.menu.showSubMenu(subMenuElement); + } + + addItem(option: IMenu) { + if (this.isOpen) { + return; + } + return this.menu.addItem(option); + } + + addSeparator(index?: number) { + if (this.isOpen) { + return; + } + this.menu.addSeparator(index); + } + + open(options: { x: number, y: number, h?: number, w?: number, isLeft?: boolean }) { + if (this.isOpen) { + return; + } + this.menu.popup(options, options.isLeft); + } + + fullscreen(position: "bottom" | "all" = "all") { + if (this.isOpen) { + return; + } + this.menu.fullscreen(position); + this.menu.element.style.zIndex = "310"; + } + + close() { + this.menu.remove(); + } +} diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index c576fdd5a..2ba51714e 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -1,105 +1,10 @@ +import {Menu} from "../../../plugin/Meun"; import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "../../util/hasClosest"; import {transaction} from "../../wysiwyg/transaction"; -import {Menu} from "../../../plugin/API"; -import {getIconByType} from "./render"; import {openEditorTab} from "../../../menus/util"; import {copySubMenu} from "../../../menus/commonMenuItem"; -import {popTextCell} from "./cell"; - -export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, cellElement: HTMLElement) => { - const type = cellElement.getAttribute("data-dtype") as TAVCol; - const menu = new Menu("av-header-cell"); - menu.addItem({ - icon: getIconByType(type), - label: ``, - bind() { - - } - }); - if (type !== "block") { - menu.addItem({ - icon: "iconEdit", - label: window.siyuan.languages.edit, - click() { - - } - }); - } - menu.addSeparator(); - menu.addItem({ - icon: "iconUp", - label: window.siyuan.languages.fileNameNatASC, - click() { - - } - }); - menu.addItem({ - icon: "iconDown", - label: window.siyuan.languages.fileNameNatDESC, - click() { - - } - }); - menu.addItem({ - icon: "iconFilter", - label: window.siyuan.languages.filter, - click() { - - } - }); - menu.addSeparator(); - if (type !== "block") { - menu.addItem({ - icon: "iconEyeoff", - label: window.siyuan.languages.hide, - click() { - - } - }); - menu.addItem({ - icon: "iconCopy", - label: window.siyuan.languages.duplicate, - click() { - - } - }); - menu.addItem({ - icon: "iconTrashcan", - label: window.siyuan.languages.delete, - click() { - const id = cellElement.getAttribute("data-id"); - transaction(protyle, [{ - action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), - }], [{ - action: "addAttrViewCol", - name: cellElement.textContent.trim(), - parentID: blockElement.getAttribute("data-av-id"), - type: type, - id - }]); - removeCol(cellElement); - } - }); - menu.addSeparator(); - } - menu.addItem({ - label: `
${window.siyuan.languages.wrap} -
`, - click() { - - } - }); - const cellRect = cellElement.getBoundingClientRect(); - menu.open({ - x: cellRect.left, - y: cellRect.bottom, - h: cellRect.height - }); - (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement)?.select(); - -}; +import {popTextCell, showHeaderCellMenu} from "./cell"; +import {getColIconByType} from "./col"; export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => { const blockElement = hasClosestBlock(event.target); @@ -226,7 +131,7 @@ export const avContextmenu = (protyle: IProtyle, event: MouseEvent & { detail: a const editAttrSubmenu: IMenu[] = []; rowElement.parentElement.querySelectorAll(".av__row--header .av__cell").forEach((cellElement) => { editAttrSubmenu.push({ - icon: getIconByType(cellElement.getAttribute("data-dtype") as TAVCol), + icon: getColIconByType(cellElement.getAttribute("data-dtype") as TAVCol), label: cellElement.textContent.trim(), click() { } @@ -244,14 +149,3 @@ export const avContextmenu = (protyle: IProtyle, event: MouseEvent & { detail: a }); return true; }; - -const removeCol = (cellElement: HTMLElement) => { - const index = cellElement.getAttribute("data-index"); - const blockElement = hasClosestBlock(cellElement); - if (!blockElement) { - return false; - } - blockElement.querySelectorAll(".av__row").forEach((item) => { - item.querySelector(`[data-index="${index}"]`).remove(); - }); -}; diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 180f10885..4ad30bd6f 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -1,5 +1,7 @@ import {transaction} from "../../wysiwyg/transaction"; import {hasClosestBlock} from "../../util/hasClosest"; +import {Menu} from "../../../plugin/Meun"; +import {getColIconByType} from "./col"; export const popTextCell = (protyle: IProtyle, cellElement: HTMLElement) => { const type = cellElement.parentElement.parentElement.firstElementChild.children[parseInt(cellElement.getAttribute("data-index")) + 1].getAttribute("data-dtype") as TAVCol; @@ -62,3 +64,108 @@ const updateCellValue = (protyle: IProtyle, cellElement: HTMLElement, type: TAVC avMaskElement.remove(); }); }; + +const removeCol = (cellElement: HTMLElement) => { + const index = cellElement.getAttribute("data-index"); + const blockElement = hasClosestBlock(cellElement); + if (!blockElement) { + return false; + } + blockElement.querySelectorAll(".av__row").forEach((item) => { + item.querySelector(`[data-index="${index}"]`).remove(); + }); +}; + +export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, cellElement: HTMLElement) => { + const type = cellElement.getAttribute("data-dtype") as TAVCol; + const menu = new Menu("av-header-cell"); + menu.addItem({ + icon: getColIconByType(type), + label: ``, + bind() { + + } + }); + if (type !== "block") { + menu.addItem({ + icon: "iconEdit", + label: window.siyuan.languages.edit, + click() { + + } + }); + } + menu.addSeparator(); + menu.addItem({ + icon: "iconUp", + label: window.siyuan.languages.fileNameNatASC, + click() { + + } + }); + menu.addItem({ + icon: "iconDown", + label: window.siyuan.languages.fileNameNatDESC, + click() { + + } + }); + menu.addItem({ + icon: "iconFilter", + label: window.siyuan.languages.filter, + click() { + + } + }); + menu.addSeparator(); + if (type !== "block") { + menu.addItem({ + icon: "iconEyeoff", + label: window.siyuan.languages.hide, + click() { + + } + }); + menu.addItem({ + icon: "iconCopy", + label: window.siyuan.languages.duplicate, + click() { + + } + }); + menu.addItem({ + icon: "iconTrashcan", + label: window.siyuan.languages.delete, + click() { + const id = cellElement.getAttribute("data-id"); + transaction(protyle, [{ + action: "removeAttrViewCol", + id, + parentID: blockElement.getAttribute("data-av-id"), + }], [{ + action: "addAttrViewCol", + name: cellElement.textContent.trim(), + parentID: blockElement.getAttribute("data-av-id"), + type: type, + id + }]); + removeCol(cellElement); + } + }); + menu.addSeparator(); + } + menu.addItem({ + label: `
${window.siyuan.languages.wrap} +
`, + click() { + + } + }); + const cellRect = cellElement.getBoundingClientRect(); + menu.open({ + x: cellRect.left, + y: cellRect.bottom, + h: cellRect.height + }); + (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement)?.select(); +}; diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts new file mode 100644 index 000000000..425ccc437 --- /dev/null +++ b/app/src/protyle/render/av/col.ts @@ -0,0 +1,8 @@ +export const getColIconByType = (type: TAVCol) => { + switch (type) { + case "text": + return "iconAlignLeft"; + case "block": + return "iconParagraph"; + } +}; diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts index 0cb7a092a..6f8345e5e 100644 --- a/app/src/protyle/render/av/render.ts +++ b/app/src/protyle/render/av/render.ts @@ -1,15 +1,8 @@ import {fetchPost} from "../../../util/fetch"; +import {getColIconByType} from "./col"; +import {showHeaderCellMenu} from "./cell"; -export const getIconByType = (type: TAVCol) => { - switch (type) { - case "text": - return "iconAlignLeft"; - case "block": - return "iconParagraph"; - } -}; - -export const avRender = (element: Element) => { +export const avRender = (element: Element, cb?: () => void) => { let avElements: Element[] = []; if (element.getAttribute("data-type") === "NodeAttributeView") { // 编辑器内代码块编辑渲染 @@ -35,7 +28,7 @@ export const avRender = (element: Element) => { return; } tableHTML += `
- + ${column.name}
`; index++; @@ -85,7 +78,27 @@ export const avRender = (element: Element) => { `; e.setAttribute("data-render", "true"); + if (cb) { + cb(); + } }); }); } }; + +export const refreshAV = (protyle: IProtyle, operation: IOperation) => { + if (operation.action === "addAttrViewCol") { + Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${operation.id}"]`)).forEach((item: HTMLElement) => { + item.removeAttribute("data-render"); + avRender(item, () => { + showHeaderCellMenu(protyle, item, item.querySelector(".av__row--header").lastElementChild.previousElementSibling as HTMLElement); + }); + }); + } else if (operation.action === "insertAttrViewBlock") { + Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${operation.id}"]`)).forEach((item: HTMLElement) => { + item.removeAttribute("data-render"); + avRender(item); + }); + } +}; +