From 1ab87be0e66d19eaa32a1e84fecb96598bcf7539 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 21 Mar 2025 17:34:39 +0200 Subject: [PATCH] chore(client/ts): fix errors in editable_text --- src/public/app/components/app_context.ts | 2 + src/public/app/components/note_context.ts | 2 +- src/public/app/types.d.ts | 27 ++++++++++--- .../app/widgets/type_widgets/editable_text.ts | 38 +++++++++++-------- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index 367d99e8b..2d95e8632 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -193,6 +193,8 @@ export type CommandMappings = { showPasswordNotSet: CommandData; showProtectedSessionPasswordDialog: CommandData; showUploadAttachmentsDialog: CommandData & { noteId: string }; + showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget }; + showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string }; closeProtectedSessionPasswordDialog: CommandData; copyImageReferenceToClipboard: CommandData; copyImageToClipboard: CommandData; diff --git a/src/public/app/components/note_context.ts b/src/public/app/components/note_context.ts index 7d9f3d246..6c93fcc5b 100644 --- a/src/public/app/components/note_context.ts +++ b/src/public/app/components/note_context.ts @@ -16,7 +16,7 @@ export interface SetNoteOpts { viewScope?: ViewScope; } -export type GetTextEditorCallback = () => void; +export type GetTextEditorCallback = (editor: TextEditor) => void; class NoteContext extends Component implements EventListener<"entitiesReloaded"> { ntxId: string | null; diff --git a/src/public/app/types.d.ts b/src/public/app/types.d.ts index 8c70dc661..01b5c6812 100644 --- a/src/public/app/types.d.ts +++ b/src/public/app/types.d.ts @@ -210,6 +210,7 @@ declare global { config: MermaidConfig } }); + destroy(); } var CKEditor: { @@ -287,18 +288,20 @@ declare global { interface Range { toJSON(): object; + getItems(): TextNode[]; } interface Writer { setAttribute(name: string, value: string, el: CKNode); createPositionAt(el: CKNode, opt?: "end" | number); setSelection(pos: number, pos?: number); - insertText(text: string, opts: Record | undefined, position?: TextPosition); + insertText(text: string, opts: Record | undefined | TextPosition, position?: TextPosition); addMarker(name: string, opts: { range: Range; usingOperation: boolean; }); removeMarker(name: string); createRange(start: number, end: number): Range; + createElement(type: string, opts: Record); } interface TextNode { previousSibling?: TextNode; @@ -347,6 +350,17 @@ declare global { }; } + interface CKEvent { + stop(): void; + } + + interface PluginEventData { + title: string; + message: { + message: string; + }; + } + interface TextEditor { create(el: HTMLElement, config: { removePlugins?: string[]; @@ -365,6 +379,11 @@ declare global { selection: { getFirstPosition(): undefined | TextPosition; getLastPosition(): undefined | TextPosition; + getSelectedElement(): CKNode; + hasAttribute(attribute: string): boolean; + getAttribute(attribute: string): string; + getFirstRange(): Range; + isCollapsed: boolean; }; differ: { getChanges(): { @@ -378,15 +397,13 @@ declare global { }[]; } }, - insertContent(modelFragment: any, selection: any); + insertContent(modelFragment: any, selection?: any); change(cb: (writer: Writer) => void) }, editing: { view: { document: { - on(event: string, cb: (event: { - stop(); - }, data: { + on(event: string, cb: (event: CKEvent, data: { preventDefault(); }) => void, opts?: { priority: "high" diff --git a/src/public/app/widgets/type_widgets/editable_text.ts b/src/public/app/widgets/type_widgets/editable_text.ts index 2863b025a..9f4278197 100644 --- a/src/public/app/widgets/type_widgets/editable_text.ts +++ b/src/public/app/widgets/type_widgets/editable_text.ts @@ -8,7 +8,7 @@ import froca from "../../services/froca.js"; import noteCreateService from "../../services/note_create.js"; import AbstractTextTypeWidget from "./abstract_text_type_widget.js"; import link from "../../services/link.js"; -import appContext from "../../components/app_context.js"; +import appContext, { type EventData } from "../../components/app_context.js"; import dialogService from "../../services/dialog.js"; import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js"; import options from "../../services/options.js"; @@ -216,7 +216,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { const editor = await editorClass.create(elementOrData, finalConfig); const notificationsPlugin = editor.plugins.get("Notification"); - notificationsPlugin.on("show:warning", (evt, data) => { + notificationsPlugin.on("show:warning", (evt: CKEvent, data: PluginEventData) => { const title = data.title; const message = data.message.message; @@ -253,6 +253,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { editor.model.document.on("change:data", () => this.spacedUpdate.scheduleUpdate()); if (glob.isDev && ENABLE_INSPECTOR) { + //@ts-expect-error TODO: Check if this still works. await import(/* webpackIgnore: true */ "../../../libraries/ckeditor/inspector.js"); CKEditorInspector.attach(editor); } @@ -288,8 +289,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { const blob = await note.getBlob(); await this.spacedUpdate.allowUpdateWithoutChange(async () => { - const data = blob.content || ""; - const newContentLanguage = this.note.getLabelValue("language"); + const data = blob?.content || ""; + const newContentLanguage = this.note?.getLabelValue("language"); if (this.contentLanguage !== newContentLanguage) { await this.reinitialize(data); } else { @@ -359,7 +360,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { }); } - addTextToActiveEditorEvent({ text }) { + addTextToActiveEditorEvent({ text }: EventData<"addTextToActiveEditor">) { if (!this.isActive()) { return; } @@ -367,7 +368,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { this.addTextToEditor(text); } - async addLink(notePath, linkTitle, externalLink = false) { + async addLink(notePath: string, linkTitle: string, externalLink: boolean = false) { await this.initialized; if (linkTitle) { @@ -391,7 +392,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { return !selection.isCollapsed; } - async executeWithTextEditorEvent({ callback, resolve, ntxId }) { + async executeWithTextEditorEvent({ callback, resolve, ntxId }: EventData<"executeWithTextEditor">) { if (!this.isNoteContext(ntxId)) { return; } @@ -435,7 +436,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { const notePath = selectedElement.getAttribute("notePath"); if (notePath) { - await appContext.tabManager.getActiveContext().setNote(notePath); + await appContext.tabManager.getActiveContext()?.setNote(notePath); return; } } @@ -448,7 +449,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { const notePath = link.getNotePathFromUrl(selectedLinkUrl); if (notePath) { - await appContext.tabManager.getActiveContext().setNote(notePath); + await appContext.tabManager.getActiveContext()?.setNote(notePath); } else { window.open(selectedLinkUrl, "_blank"); } @@ -458,7 +459,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { this.triggerCommand("showIncludeNoteDialog", { textTypeWidget: this }); } - addIncludeNote(noteId, boxSize) { + addIncludeNote(noteId: string, boxSize: string) { this.watchdog.editor.model.change((writer) => { // Insert * at the current selection position // in a way that will result in creating a valid model structure @@ -471,8 +472,11 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { }); } - async addImage(noteId) { + async addImage(noteId: string) { const note = await froca.getNote(noteId); + if (!note) { + return; + } this.watchdog.editor.model.change((writer) => { const encodedTitle = encodeURIComponent(note.title); @@ -482,24 +486,28 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { }); } - async createNoteForReferenceLink(title) { + async createNoteForReferenceLink(title: string) { + if (!this.notePath) { + return; + } + const resp = await noteCreateService.createNoteWithTypePrompt(this.notePath, { activate: false, title: title }); - if (!resp) { + if (!resp || !resp.note) { return; } return resp.note.getBestNotePathString(); } - async refreshIncludedNoteEvent({ noteId }) { + async refreshIncludedNoteEvent({ noteId }: EventData<"refreshIncludedNote">) { this.refreshIncludedNote(this.$editor, noteId); } - async reinitialize(data) { + async reinitialize(data: string) { if (!this.watchdog) { return; }