diff --git a/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx b/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx index f8bd794fa..38ea1322a 100644 --- a/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx +++ b/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx @@ -5,7 +5,9 @@ import { RawHtmlBlock } from "../../react/RawHtml"; import server from "../../../services/server"; import svgPanZoom, { zoomIn } from "svg-pan-zoom"; import { RefObject } from "preact"; -import { useElementSize } from "../../react/hooks"; +import { useElementSize, useTriliumEvent } from "../../react/hooks"; +import utils from "../../../services/utils"; +import toast from "../../../services/toast"; interface SvgSplitEditorProps extends Omit { /** @@ -22,7 +24,18 @@ interface SvgSplitEditorProps extends Omit { renderSvg(content: string): string | Promise; } -export default function SvgSplitEditor({ note, attachmentName, renderSvg, ...props }: SvgSplitEditorProps) { +/** + * A specialization of `SplitTypeWidget` meant for note types that have a SVG preview. + * + * This adds the following functionality: + * + * - Automatic handling of the preview when content or the note changes via {@link renderSvg}. + * - Built-in pan and zoom functionality with automatic re-centering. + * - Automatically displays errors to the user if {@link renderSvg} failed. + * - Automatically saves the SVG attachment. + * + */ +export default function SvgSplitEditor({ ntxId, note, attachmentName, renderSvg, ...props }: SvgSplitEditorProps) { const [ svg, setSvg ] = useState(); const [ error, setError ] = useState(); const containerRef = useRef(null); @@ -54,13 +67,28 @@ export default function SvgSplitEditor({ note, attachmentName, renderSvg, ...pro server.post(`notes/${note.noteId}/attachments?matchBy=title`, payload); } + // Import/export + useTriliumEvent("exportSvg", ({ ntxId: eventNtxId }) => { + if (eventNtxId !== ntxId || !svg) return; + utils.downloadSvg(note.title, svg); + }); + useTriliumEvent("exportPng", async ({ ntxId: eventNtxId }) => { + if (eventNtxId !== ntxId || !svg) return; + try { + await utils.downloadSvgAsPng(note.title, svg); + } catch (e) { + console.warn(e); + toast.showError(t("svg.export_to_png")); + } + }); + // Pan & zoom. const zoomRef = useResizer(containerRef, note.noteId, svg); return ( ; @@ -47,27 +36,5 @@ export default abstract class AbstractSvgSplitTypeWidget extends AbstractSplitTy } }); } - async exportSvgEvent({ ntxId }: EventData<"exportSvg">) { - if (!this.isNoteContext(ntxId) || this.note?.type !== "mermaid" || !this.svg) { - return; - } - - utils.downloadSvg(this.note.title, this.svg); - } - - async exportPngEvent({ ntxId }: EventData<"exportPng">) { - console.log("Export to PNG", this.noteContext?.noteId, ntxId, this.svg); - if (!this.isNoteContext(ntxId) || this.note?.type !== "mermaid" || !this.svg) { - console.log("Return"); - return; - } - - try { - await utils.downloadSvgAsPng(this.note.title, this.svg); - } catch (e) { - console.warn(e); - toast.showError(t("svg.export_to_png")); - } - } }