From cc19a217ade040cc73a19932e1d4ed435a174e90 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 20 Sep 2025 21:33:57 +0300 Subject: [PATCH] chore(react/type_widget): finalize SVG split editor --- .../type_widgets/helpers/SvgSplitEditor.tsx | 9 ++ .../abstract_code_type_widget.ts | 60 ------------- .../abstract_split_type_widget.ts | 87 ------------------- .../abstract_svg_split_type_widget.ts | 40 --------- 4 files changed, 9 insertions(+), 187 deletions(-) delete mode 100644 apps/client/src/widgets/type_widgets_old/abstract_code_type_widget.ts delete mode 100644 apps/client/src/widgets/type_widgets_old/abstract_split_type_widget.ts delete mode 100644 apps/client/src/widgets/type_widgets_old/abstract_svg_split_type_widget.ts diff --git a/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx b/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx index 38ea1322a..84ad7c8e2 100644 --- a/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx +++ b/apps/client/src/widgets/type_widgets/helpers/SvgSplitEditor.tsx @@ -67,6 +67,15 @@ export default function SvgSplitEditor({ ntxId, note, attachmentName, renderSvg, server.post(`notes/${note.noteId}/attachments?matchBy=title`, payload); } + // Save the SVG when entering a note only when it does not have an attachment. + useEffect(() => { + note?.getAttachments().then((attachments) => { + if (!attachments.find((a) => a.title === `${attachmentName}.svg`)) { + onSave(); + } + }); + }, [ note ]); + // Import/export useTriliumEvent("exportSvg", ({ ntxId: eventNtxId }) => { if (eventNtxId !== ntxId || !svg) return; diff --git a/apps/client/src/widgets/type_widgets_old/abstract_code_type_widget.ts b/apps/client/src/widgets/type_widgets_old/abstract_code_type_widget.ts deleted file mode 100644 index ede647ff7..000000000 --- a/apps/client/src/widgets/type_widgets_old/abstract_code_type_widget.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { getThemeById } from "@triliumnext/codemirror"; -import type FNote from "../../entities/fnote.js"; -import options from "../../services/options.js"; -import TypeWidget from "./type_widget.js"; -import CodeMirror, { type EditorConfig } from "@triliumnext/codemirror"; -import type { EventData } from "../../components/app_context.js"; - - -/** - * An abstract {@link TypeWidget} which implements the CodeMirror editor, meant to be used as a parent for - * widgets requiring the editor. - * - * The widget handles the loading and initialization of the CodeMirror editor, as well as some common - * actions. - * - * The derived class must: - * - * - Define `$editor` in the constructor. - * - Call `super.doRender()` in the extended class. - * - Call `this._update(note, content)` in `#doRefresh(note)`. - */ -export default class AbstractCodeTypeWidget extends TypeWidget { - - protected $editor!: JQuery; - protected codeEditor!: CodeMirror; - - doRender() { - this.initialized = this.#initEditor(); - } - - async #initEditor() { - // Load the theme. - - } - - /** - * Can be extended in derived classes to add extra options to the CodeMirror constructor. The options are appended - * at the end, so it is possible to override the default values introduced by the abstract editor as well. - * - * @returns the extra options to be passed to the CodeMirror constructor. - */ - getExtraOpts(): Partial { - return {}; - } - - /** - * Called as soon as the CodeMirror library has been loaded and the editor was constructed. Can be extended in - * derived classes to add additional functionality or to register event handlers. - * - * By default, it does nothing. - */ - onEditorInitialized() { - // Do nothing by default. - } - - focus() { - this.codeEditor.focus(); - } - -} diff --git a/apps/client/src/widgets/type_widgets_old/abstract_split_type_widget.ts b/apps/client/src/widgets/type_widgets_old/abstract_split_type_widget.ts deleted file mode 100644 index 01c4cad8f..000000000 --- a/apps/client/src/widgets/type_widgets_old/abstract_split_type_widget.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type FNote from "../../entities/fnote.js"; -import utils from "../../services/utils.js"; -import EditableCodeTypeWidget from "./editable_code.js"; -import TypeWidget from "./type_widget.js"; -import Split from "split.js"; -import { DEFAULT_GUTTER_SIZE } from "../../services/resizer.js"; -import options from "../../services/options.js"; -import type { EventData } from "../../components/app_context.js"; -import type OnClickButtonWidget from "../buttons/onclick_button.js"; -import type { EditorConfig } from "@triliumnext/codemirror"; - -export default abstract class AbstractSplitTypeWidget extends TypeWidget { - - private splitInstance?: Split.Instance; - - protected $preview!: JQuery; - private $editorCol!: JQuery; - private $previewCol!: JQuery; - private $editor!: JQuery; - private $errorContainer!: JQuery; - private editorTypeWidget: EditableCodeTypeWidget; - private layoutOrientation?: "horizontal" | "vertical"; - private isReadOnly?: boolean; - - constructor() { - super(); - - this.editorTypeWidget.updateBackgroundColor = () => {}; - this.editorTypeWidget.isEnabled = () => true; - - const defaultOptions = this.editorTypeWidget.getExtraOpts(); - this.editorTypeWidget.getExtraOpts = () => { - return { - ...defaultOptions, - ...this.buildEditorExtraOptions() - }; - }; - } - - doRender(): void { - // Preview pane - this.$previewCol = this.$widget.find(".note-detail-split-preview-col"); - this.$preview = this.$widget.find(".note-detail-split-preview"); - - // Editor pane - this.$editorCol = this.$widget.find(".note-detail-split-editor-col"); - this.$editor = this.$widget.find(".note-detail-split-editor"); - this.$editor.append(this.editorTypeWidget.render()); - this.$errorContainer = this.$widget.find(".note-detail-error-container"); - this.#adjustLayoutOrientation(); - - // Preview pane buttons - const $previewButtons = this.$previewCol.find(".preview-buttons"); - const previewButtons = this.buildPreviewButtons(); - $previewButtons.toggle(previewButtons.length > 0); - for (const previewButton of previewButtons) { - const $button = previewButton.render(); - $button.removeClass("button-widget") - .addClass("btn") - .addClass("tn-tool-button"); - $previewButtons.append($button); - previewButton.refreshIcon(); - } - - super.doRender(); - } - - async doRefresh(note: FNote) { - this.#adjustLayoutOrientation(); - - if (!this.isReadOnly) { - await this.editorTypeWidget.initialized; - this.editorTypeWidget.noteContext = this.noteContext; - this.editorTypeWidget.spacedUpdate = this.spacedUpdate; - this.editorTypeWidget.doRefresh(note); - } - } - - buildPreviewButtons(): OnClickButtonWidget[] { - return []; - } - - getData() { - return this.editorTypeWidget.getData(); - } - -} 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 deleted file mode 100644 index 978bdc50b..000000000 --- a/apps/client/src/widgets/type_widgets_old/abstract_svg_split_type_widget.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { EventData } from "../../components/app_context.js"; -import type FNote from "../../entities/fnote.js"; -import { t } from "../../services/i18n.js"; -import server from "../../services/server.js"; -import toast from "../../services/toast.js"; -import utils from "../../services/utils.js"; -import OnClickButtonWidget from "../buttons/onclick_button.js"; -import AbstractSplitTypeWidget from "./abstract_split_type_widget.js"; - -export default abstract class AbstractSvgSplitTypeWidget extends AbstractSplitTypeWidget { - - private $renderContainer!: JQuery; - private zoomHandler: () => void; - private zoomInstance?: SvgPanZoom.Instance; - private svg?: string; - - - doRender(): void { - super.doRender(); - this.$preview.append(this.$renderContainer); - $(window).on("resize", this.zoomHandler); - } - - async doRefresh(note: FNote) { - super.doRefresh(note); - - const blob = await note?.getBlob(); - const content = blob?.content || ""; - this.onContentChanged(content, true); - - // Save the SVG when entering a note only when it does not have an attachment. - this.note?.getAttachments().then((attachments) => { - const attachmentName = `${this.attachmentName}.svg`; - if (!attachments.find((a) => a.title === attachmentName)) { - this.#saveSvg(); - } - }); - } - -}