chore(client/ts): fix errors in editable_text

This commit is contained in:
Elian Doran 2025-03-21 17:34:39 +02:00
parent ebbf29b1a5
commit 1ab87be0e6
No known key found for this signature in database
4 changed files with 48 additions and 21 deletions

View File

@ -193,6 +193,8 @@ export type CommandMappings = {
showPasswordNotSet: CommandData; showPasswordNotSet: CommandData;
showProtectedSessionPasswordDialog: CommandData; showProtectedSessionPasswordDialog: CommandData;
showUploadAttachmentsDialog: CommandData & { noteId: string }; showUploadAttachmentsDialog: CommandData & { noteId: string };
showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string };
closeProtectedSessionPasswordDialog: CommandData; closeProtectedSessionPasswordDialog: CommandData;
copyImageReferenceToClipboard: CommandData; copyImageReferenceToClipboard: CommandData;
copyImageToClipboard: CommandData; copyImageToClipboard: CommandData;

View File

@ -16,7 +16,7 @@ export interface SetNoteOpts {
viewScope?: ViewScope; viewScope?: ViewScope;
} }
export type GetTextEditorCallback = () => void; export type GetTextEditorCallback = (editor: TextEditor) => void;
class NoteContext extends Component implements EventListener<"entitiesReloaded"> { class NoteContext extends Component implements EventListener<"entitiesReloaded"> {
ntxId: string | null; ntxId: string | null;

View File

@ -210,6 +210,7 @@ declare global {
config: MermaidConfig config: MermaidConfig
} }
}); });
destroy();
} }
var CKEditor: { var CKEditor: {
@ -287,18 +288,20 @@ declare global {
interface Range { interface Range {
toJSON(): object; toJSON(): object;
getItems(): TextNode[];
} }
interface Writer { interface Writer {
setAttribute(name: string, value: string, el: CKNode); setAttribute(name: string, value: string, el: CKNode);
createPositionAt(el: CKNode, opt?: "end" | number); createPositionAt(el: CKNode, opt?: "end" | number);
setSelection(pos: number, pos?: number); setSelection(pos: number, pos?: number);
insertText(text: string, opts: Record<string, unknown> | undefined, position?: TextPosition); insertText(text: string, opts: Record<string, unknown> | undefined | TextPosition, position?: TextPosition);
addMarker(name: string, opts: { addMarker(name: string, opts: {
range: Range; range: Range;
usingOperation: boolean; usingOperation: boolean;
}); });
removeMarker(name: string); removeMarker(name: string);
createRange(start: number, end: number): Range; createRange(start: number, end: number): Range;
createElement(type: string, opts: Record<string, string>);
} }
interface TextNode { interface TextNode {
previousSibling?: TextNode; previousSibling?: TextNode;
@ -347,6 +350,17 @@ declare global {
}; };
} }
interface CKEvent {
stop(): void;
}
interface PluginEventData {
title: string;
message: {
message: string;
};
}
interface TextEditor { interface TextEditor {
create(el: HTMLElement, config: { create(el: HTMLElement, config: {
removePlugins?: string[]; removePlugins?: string[];
@ -365,6 +379,11 @@ declare global {
selection: { selection: {
getFirstPosition(): undefined | TextPosition; getFirstPosition(): undefined | TextPosition;
getLastPosition(): undefined | TextPosition; getLastPosition(): undefined | TextPosition;
getSelectedElement(): CKNode;
hasAttribute(attribute: string): boolean;
getAttribute(attribute: string): string;
getFirstRange(): Range;
isCollapsed: boolean;
}; };
differ: { differ: {
getChanges(): { getChanges(): {
@ -378,15 +397,13 @@ declare global {
}[]; }[];
} }
}, },
insertContent(modelFragment: any, selection: any); insertContent(modelFragment: any, selection?: any);
change(cb: (writer: Writer) => void) change(cb: (writer: Writer) => void)
}, },
editing: { editing: {
view: { view: {
document: { document: {
on(event: string, cb: (event: { on(event: string, cb: (event: CKEvent, data: {
stop();
}, data: {
preventDefault(); preventDefault();
}) => void, opts?: { }) => void, opts?: {
priority: "high" priority: "high"

View File

@ -8,7 +8,7 @@ import froca from "../../services/froca.js";
import noteCreateService from "../../services/note_create.js"; import noteCreateService from "../../services/note_create.js";
import AbstractTextTypeWidget from "./abstract_text_type_widget.js"; import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
import link from "../../services/link.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 dialogService from "../../services/dialog.js";
import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js"; import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js";
import options from "../../services/options.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 editor = await editorClass.create(elementOrData, finalConfig);
const notificationsPlugin = editor.plugins.get("Notification"); 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 title = data.title;
const message = data.message.message; const message = data.message.message;
@ -253,6 +253,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
editor.model.document.on("change:data", () => this.spacedUpdate.scheduleUpdate()); editor.model.document.on("change:data", () => this.spacedUpdate.scheduleUpdate());
if (glob.isDev && ENABLE_INSPECTOR) { if (glob.isDev && ENABLE_INSPECTOR) {
//@ts-expect-error TODO: Check if this still works.
await import(/* webpackIgnore: true */ "../../../libraries/ckeditor/inspector.js"); await import(/* webpackIgnore: true */ "../../../libraries/ckeditor/inspector.js");
CKEditorInspector.attach(editor); CKEditorInspector.attach(editor);
} }
@ -288,8 +289,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
const blob = await note.getBlob(); const blob = await note.getBlob();
await this.spacedUpdate.allowUpdateWithoutChange(async () => { await this.spacedUpdate.allowUpdateWithoutChange(async () => {
const data = blob.content || ""; const data = blob?.content || "";
const newContentLanguage = this.note.getLabelValue("language"); const newContentLanguage = this.note?.getLabelValue("language");
if (this.contentLanguage !== newContentLanguage) { if (this.contentLanguage !== newContentLanguage) {
await this.reinitialize(data); await this.reinitialize(data);
} else { } else {
@ -359,7 +360,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
}); });
} }
addTextToActiveEditorEvent({ text }) { addTextToActiveEditorEvent({ text }: EventData<"addTextToActiveEditor">) {
if (!this.isActive()) { if (!this.isActive()) {
return; return;
} }
@ -367,7 +368,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
this.addTextToEditor(text); this.addTextToEditor(text);
} }
async addLink(notePath, linkTitle, externalLink = false) { async addLink(notePath: string, linkTitle: string, externalLink: boolean = false) {
await this.initialized; await this.initialized;
if (linkTitle) { if (linkTitle) {
@ -391,7 +392,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
return !selection.isCollapsed; return !selection.isCollapsed;
} }
async executeWithTextEditorEvent({ callback, resolve, ntxId }) { async executeWithTextEditorEvent({ callback, resolve, ntxId }: EventData<"executeWithTextEditor">) {
if (!this.isNoteContext(ntxId)) { if (!this.isNoteContext(ntxId)) {
return; return;
} }
@ -435,7 +436,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
const notePath = selectedElement.getAttribute("notePath"); const notePath = selectedElement.getAttribute("notePath");
if (notePath) { if (notePath) {
await appContext.tabManager.getActiveContext().setNote(notePath); await appContext.tabManager.getActiveContext()?.setNote(notePath);
return; return;
} }
} }
@ -448,7 +449,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
const notePath = link.getNotePathFromUrl(selectedLinkUrl); const notePath = link.getNotePathFromUrl(selectedLinkUrl);
if (notePath) { if (notePath) {
await appContext.tabManager.getActiveContext().setNote(notePath); await appContext.tabManager.getActiveContext()?.setNote(notePath);
} else { } else {
window.open(selectedLinkUrl, "_blank"); window.open(selectedLinkUrl, "_blank");
} }
@ -458,7 +459,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
this.triggerCommand("showIncludeNoteDialog", { textTypeWidget: this }); this.triggerCommand("showIncludeNoteDialog", { textTypeWidget: this });
} }
addIncludeNote(noteId, boxSize) { addIncludeNote(noteId: string, boxSize: string) {
this.watchdog.editor.model.change((writer) => { this.watchdog.editor.model.change((writer) => {
// Insert <includeNote>*</includeNote> at the current selection position // Insert <includeNote>*</includeNote> at the current selection position
// in a way that will result in creating a valid model structure // 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); const note = await froca.getNote(noteId);
if (!note) {
return;
}
this.watchdog.editor.model.change((writer) => { this.watchdog.editor.model.change((writer) => {
const encodedTitle = encodeURIComponent(note.title); 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, { const resp = await noteCreateService.createNoteWithTypePrompt(this.notePath, {
activate: false, activate: false,
title: title title: title
}); });
if (!resp) { if (!resp || !resp.note) {
return; return;
} }
return resp.note.getBestNotePathString(); return resp.note.getBestNotePathString();
} }
async refreshIncludedNoteEvent({ noteId }) { async refreshIncludedNoteEvent({ noteId }: EventData<"refreshIncludedNote">) {
this.refreshIncludedNote(this.$editor, noteId); this.refreshIncludedNote(this.$editor, noteId);
} }
async reinitialize(data) { async reinitialize(data: string) {
if (!this.watchdog) { if (!this.watchdog) {
return; return;
} }