mirror of
https://github.com/zadam/trilium.git
synced 2025-11-11 08:58:58 +01:00
chore(react/type_widget): finalize SVG split editor
This commit is contained in:
parent
d95ed4a5d2
commit
cc19a217ad
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user