From bde7b753a0cdb2cee0b781fd97c999f9f0d28354 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 20 Sep 2025 14:00:58 +0300 Subject: [PATCH] chore(react/type_widget): save SVG attachment --- .../src/widgets/type_widgets/Mermaid.tsx | 1 + .../src/widgets/type_widgets/code/Code.tsx | 6 +++++- .../type_widgets/helpers/SvgSplitEditor.tsx | 21 ++++++++++++++++++- .../abstract_svg_split_type_widget.ts | 11 ---------- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/Mermaid.tsx b/apps/client/src/widgets/type_widgets/Mermaid.tsx index 81406b553..65574aa01 100644 --- a/apps/client/src/widgets/type_widgets/Mermaid.tsx +++ b/apps/client/src/widgets/type_widgets/Mermaid.tsx @@ -27,6 +27,7 @@ export default function Mermaid(props: TypeWidgetProps) { return ( diff --git a/apps/client/src/widgets/type_widgets/code/Code.tsx b/apps/client/src/widgets/type_widgets/code/Code.tsx index d877af29b..da6335bd6 100644 --- a/apps/client/src/widgets/type_widgets/code/Code.tsx +++ b/apps/client/src/widgets/type_widgets/code/Code.tsx @@ -17,7 +17,10 @@ export interface EditableCodeProps extends TypeWidgetProps { debounceUpdate?: boolean; lineWrapping?: boolean; updateInterval?: number; + /** Invoked when the content of the note is changed, such as a different revision or a note switch. */ onContentChanged?: (content: string) => void; + /** Invoked after the content of the note has been uploaded to the server, using a spaced update. */ + dataSaved?: () => void; } export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWidgetProps) { @@ -43,7 +46,7 @@ export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWi ) } -export function EditableCode({ note, ntxId, debounceUpdate, parentComponent, updateInterval, onContentChanged, ...editorProps }: EditableCodeProps) { +export function EditableCode({ note, ntxId, debounceUpdate, parentComponent, updateInterval, onContentChanged, dataSaved, ...editorProps }: EditableCodeProps) { const editorRef = useRef(null); const containerRef = useRef(null); const [ vimKeymapEnabled ] = useTriliumOptionBool("vimKeymapEnabled"); @@ -57,6 +60,7 @@ export function EditableCode({ note, ntxId, debounceUpdate, parentComponent, upd codeEditor.setMimeType(note.mime); codeEditor.clearHistory(); }, + dataSaved, updateInterval }); diff --git a/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx b/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx index 3896c03c6..13661b1c4 100644 --- a/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx +++ b/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx @@ -2,8 +2,13 @@ import { useState } from "preact/hooks"; import { t } from "../../../services/i18n"; import SplitEditor, { PreviewButton, SplitEditorProps } from "./SplitEditor"; import { RawHtmlBlock } from "../../react/RawHtml"; +import server from "../../../services/server"; interface SvgSplitEditorProps extends Omit { + /** + * The name of the note attachment (without .svg extension) that will be used for storing the preview. + */ + attachmentName: string; /** * Called upon when the SVG preview needs refreshing, such as when the editor has switched to a new note or the content has switched. * @@ -14,7 +19,7 @@ interface SvgSplitEditorProps extends Omit { renderSvg(content: string): string | Promise; } -export default function SvgSplitEditor({ renderSvg, ...props }: SvgSplitEditorProps) { +export default function SvgSplitEditor({ note, attachmentName, renderSvg, ...props }: SvgSplitEditorProps) { const [ svg, setSvg ] = useState(); const [ error, setError ] = useState(); @@ -31,10 +36,24 @@ export default function SvgSplitEditor({ renderSvg, ...props }: SvgSplitEditorPr } } + function onSave() { + const payload = { + role: "image", + title: `${attachmentName}.svg`, + mime: "image/svg+xml", + content: svg, + position: 0 + }; + + server.post(`notes/${note.noteId}/attachments?matchBy=title`, payload); + } + return ( )} diff --git a/apps/client/src/widgets/type_widgets_old/abstract_svg_split_type_widget.ts b/apps/client/src/widgets/type_widgets_old/abstract_svg_split_type_widget.ts index 29d4ccbf0..90f84f3bf 100644 --- a/apps/client/src/widgets/type_widgets_old/abstract_svg_split_type_widget.ts +++ b/apps/client/src/widgets/type_widgets_old/abstract_svg_split_type_widget.ts @@ -95,15 +95,7 @@ export default abstract class AbstractSvgSplitTypeWidget extends AbstractSplitTy } #saveSvg() { - const payload = { - role: "image", - title: `${this.attachmentName}.svg`, - mime: "image/svg+xml", - content: this.svg, - position: 0 - }; - server.post(`notes/${this.noteId}/attachments?matchBy=title`, payload); } cleanup(): void { @@ -112,9 +104,6 @@ export default abstract class AbstractSvgSplitTypeWidget extends AbstractSplitTy super.cleanup(); } - /** - * Called to obtain the name of the note attachment (without .svg extension) that will be used for storing the preview. - */ abstract get attachmentName(): string; /**