diff --git a/app/src/boot/globalEvent/keydown.ts b/app/src/boot/globalEvent/keydown.ts index f7d01aacf..5caf1db52 100644 --- a/app/src/boot/globalEvent/keydown.ts +++ b/app/src/boot/globalEvent/keydown.ts @@ -64,7 +64,6 @@ import {Search} from "../../search"; import {Custom} from "../../layout/dock/Custom"; import {transaction} from "../../protyle/wysiwyg/transaction"; import {quickMakeCard} from "../../card/makeCard"; -import {copyPNG} from "../../menus/util"; import {getContentByInlineHTML} from "../../protyle/wysiwyg/keydown"; import {searchKeydown} from "./searchKeydown"; import {openNewWindow} from "../../window/openNewWindow"; @@ -74,6 +73,7 @@ import {getPlainText} from "../../protyle/util/paste"; import {commandPanel, execByCommand} from "./command/panel"; import {filterHotkey} from "./commonHotkey"; import {setReadOnly} from "../../config/util/setReadOnly"; +import {copyPNGByLink} from "../../menus/util"; const switchDialogEvent = (app: App, event: MouseEvent) => { event.preventDefault(); @@ -500,7 +500,7 @@ const editKeydown = (app: App, event: KeyboardEvent) => { } else { const selectImgElement = nodeElement.querySelector(".img--select"); if (selectImgElement) { - copyPNG(selectImgElement.querySelector("img")); + copyPNGByLink(selectImgElement.querySelector("img").getAttribute("src")); return true; } actionElement = nodeElement; diff --git a/app/src/menus/protyle.ts b/app/src/menus/protyle.ts index 1cacbfa30..a9e7b9127 100644 --- a/app/src/menus/protyle.ts +++ b/app/src/menus/protyle.ts @@ -43,7 +43,7 @@ import {blockRender} from "../protyle/render/blockRender"; import {renameAsset} from "../editor/rename"; import {electronUndo} from "../protyle/undo"; import {pushBack} from "../mobile/util/MobileBackFoward"; -import {copyPNG, exportAsset} from "./util"; +import {copyPNGByLink, exportAsset} from "./util"; import {removeInlineType} from "../protyle/toolbar/util"; import {alignImgCenter, alignImgLeft} from "../protyle/wysiwyg/commonHotkey"; import {checkFold, renameTag} from "../util/noRelyPCFunction"; @@ -957,7 +957,7 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme accelerator: window.siyuan.config.keymap.editor.general.copyBlockRef.custom, icon: "iconImage", click() { - copyPNG(imgElement); + copyPNGByLink(imgElement.getAttribute("src")); } }).element); if (!protyle.disabled) { diff --git a/app/src/menus/util.ts b/app/src/menus/util.ts index 5f082caeb..a484dbb88 100644 --- a/app/src/menus/util.ts +++ b/app/src/menus/util.ts @@ -163,9 +163,9 @@ export const openEditorTab = (app: App, ids: string[], notebookId?: string, path /// #endif }; -export const copyPNG = (imgElement: HTMLImageElement) => { +export const copyPNGByLink = (link:string) => { if (isInAndroid()) { - window.JSAndroid.writeImageClipboard(imgElement.getAttribute("src")); + window.JSAndroid.writeImageClipboard(link); return; } else { const canvas = document.createElement("canvas"); @@ -183,6 +183,7 @@ export const copyPNG = (imgElement: HTMLImageElement) => { ]); }, "image/png", 1); }; - tempElement.src = imgElement.getAttribute("src"); + tempElement.src = link; } -}; +} + diff --git a/app/src/protyle/render/av/asset.ts b/app/src/protyle/render/av/asset.ts index c4ad8ebf6..f21e28ede 100644 --- a/app/src/protyle/render/av/asset.ts +++ b/app/src/protyle/render/av/asset.ts @@ -7,7 +7,7 @@ import {uploadFiles} from "../../upload"; import {pathPosix} from "../../../util/pathName"; import {openMenu} from "../../../menus/commonMenuItem"; import {MenuItem} from "../../../menus/Menu"; -import {exportAsset} from "../../../menus/util"; +import {copyPNGByLink, exportAsset} from "../../../menus/util"; import {setPosition} from "../../../util/setPosition"; import {previewImage} from "../../preview/image"; import {genAVValueHTML} from "./blockAttr"; @@ -15,6 +15,7 @@ import {hideMessage, showMessage} from "../../../dialog/message"; import {fetchPost} from "../../../util/fetch"; import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest"; import {genCellValueByElement, getTypeByCellElement} from "./cell"; +import {writeText} from "../../util/compatibility"; export const bindAssetEvent = (options: { protyle: IProtyle, @@ -174,23 +175,33 @@ export const updateAssetCell = (options: { } }; -export const editAssetItem = (protyle: IProtyle, cellElements: HTMLElement[], target: HTMLElement, blockElement: Element) => { - const linkAddress = target.dataset.content; - const type = target.dataset.type as "image" | "file"; +export const editAssetItem = (options: { + protyle: IProtyle, + cellElements: HTMLElement[], + blockElement: Element , + content: string, + type: "image" | "file", + name: string, + index: number, + rect: DOMRect +}) => { + const linkAddress =options.content; + const type = options.type as "image" | "file"; const menu = new Menu("av-asset-edit", () => { - if (textElements.length < 2 || !textElements[0].value || - (textElements[0].value === linkAddress && textElements[1].value === target.dataset.name)) { + if (!textElements[0].value || + (!textElements[1] && textElements[0].value === linkAddress) || + (textElements[1] && textElements[0].value === linkAddress && textElements[1].value === options.name)) { return; } updateAssetCell({ - protyle, - cellElements, - blockElement, + protyle: options.protyle, + cellElements: options.cellElements, + blockElement: options.blockElement, updateValue: { - index: parseInt(target.dataset.index), + index: options.index, value: { content: textElements[0].value, - name: textElements[1].value, + name: textElements[1] ? textElements[1].value : "", type } } @@ -210,6 +221,12 @@ ${window.siyuan.languages.title} `, }); } else { + menu.addItem({ + iconHTML: "", + type: "readonly", + label: `${window.siyuan.languages.link} +`, + }); menu.addItem({ icon: "iconPreview", label: window.siyuan.languages.cardPreview, @@ -217,24 +234,39 @@ ${window.siyuan.languages.title} previewImage(linkAddress); } }); + menu.addItem({ + label: window.siyuan.languages.copy, + icon: "iconCopy", + click() { + writeText(`![](${linkAddress.replace(/%20/g, " ")})`); + } + }); + menu.addItem({ + label: window.siyuan.languages.copyAsPNG, + icon: "iconImage", + click() { + copyPNGByLink(linkAddress); + } + }); + menu.addSeparator() } menu.addItem({ icon: "iconTrashcan", label: window.siyuan.languages.delete, click() { updateAssetCell({ - protyle, - cellElements, - blockElement, - removeIndex: parseInt(target.dataset.index) + protyle: options.protyle, + cellElements: options.cellElements, + blockElement: options.blockElement, + removeIndex: options.index }); } }); - openMenu(protyle ? protyle.app : window.siyuan.ws.app, linkAddress, false, false); + openMenu(options.protyle ? options.protyle.app : window.siyuan.ws.app, linkAddress, false, false); if (linkAddress?.startsWith("assets/")) { window.siyuan.menus.menu.append(new MenuItem(exportAsset(linkAddress)).element); } - const rect = target.getBoundingClientRect(); + const rect = options.rect; menu.open({ x: rect.right, y: rect.top, @@ -242,11 +274,11 @@ ${window.siyuan.languages.title} h: rect.height, }); const textElements = menu.element.querySelectorAll("textarea"); + textElements[0].value = linkAddress; + textElements[0].focus(); + textElements[0].select(); if (textElements.length > 1) { - textElements[1].value = target.dataset.name; - textElements[0].value = linkAddress; - textElements[0].focus(); - textElements[0].select(); + textElements[1].value = options.name; } }; diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index ff5ec37b0..86f926385 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -1203,7 +1203,16 @@ export const openMenuPanel = (options: { event.stopPropagation(); break; } else if (type === "editAssetItem") { - editAssetItem(options.protyle, options.cellElements, target.parentElement, options.blockElement); + editAssetItem({ + protyle: options.protyle, + cellElements: options.cellElements, + blockElement: options.blockElement, + content: target.parentElement.dataset.content, + type: target.parentElement.dataset.type as "image" | "file", + name: target.parentElement.dataset.name, + index: parseInt(target.parentElement.dataset.index), + rect: target.parentElement.getBoundingClientRect() + }); event.preventDefault(); event.stopPropagation(); break; diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 95a3ebd80..3ab8de8b7 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -1546,6 +1546,35 @@ export class WYSIWYG { /// #endif return false; } + const avCellElement = hasClosestByClassName(target, "av__cell"); + if (avCellElement) { + if (getTypeByCellElement(avCellElement) === "mAsset") { + const assetImgElement = hasClosestByClassName(target, "av__cellassetimg") || hasClosestByClassName(target, "av__celltext--url"); + if (assetImgElement) { + let index = 0; + Array.from(avCellElement.children).find((item, i) => { + if (item === assetImgElement) { + index = i; + return true; + } + }) + editAssetItem({ + protyle, + cellElements: [avCellElement], + blockElement: hasClosestBlock(assetImgElement) as HTMLElement, + content: target.tagName === "IMG" ? target.getAttribute("src") : target.getAttribute("data-url"), + type: target.tagName === "IMG" ? "image" : "file", + name: target.tagName === "IMG" ? "" : target.textContent, + index, + rect: target.getBoundingClientRect() + }) + event.stopPropagation(); + event.preventDefault(); + return; + } + } + } + // 在 span 前面,防止单元格哪 block-ref 被修改 const avRowElement = hasClosestByClassName(target, "av__row"); if (avRowElement && avContextmenu(protyle, avRowElement, {