mirror of
https://github.com/zadam/trilium.git
synced 2025-12-23 16:49:58 +01:00
chore(react/type_widget): finalize SVG split editor
This commit is contained in:
@@ -67,6 +67,15 @@ export default function SvgSplitEditor({ ntxId, note, attachmentName, renderSvg,
|
|||||||
server.post(`notes/${note.noteId}/attachments?matchBy=title`, payload);
|
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
|
// Import/export
|
||||||
useTriliumEvent("exportSvg", ({ ntxId: eventNtxId }) => {
|
useTriliumEvent("exportSvg", ({ ntxId: eventNtxId }) => {
|
||||||
if (eventNtxId !== ntxId || !svg) return;
|
if (eventNtxId !== ntxId || !svg) return;
|
||||||
|
|||||||
@@ -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<HTMLElement>;
|
|
||||||
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<EditorConfig> {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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<HTMLElement>;
|
|
||||||
private $editorCol!: JQuery<HTMLElement>;
|
|
||||||
private $previewCol!: JQuery<HTMLElement>;
|
|
||||||
private $editor!: JQuery<HTMLElement>;
|
|
||||||
private $errorContainer!: JQuery<HTMLElement>;
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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<HTMLElement>;
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user