feat(ckeditor/watchdog): use data stored in the spaced update

This commit is contained in:
Elian Doran 2025-12-07 19:30:35 +02:00
parent f662b95dc9
commit 1bbf86fbeb
No known key found for this signature in database
3 changed files with 24 additions and 7 deletions

View File

@ -78,12 +78,23 @@ export function useSpacedUpdate(callback: () => void | Promise<void>, interval =
return spacedUpdateRef.current;
}
export interface SavedData {
content: string;
attachments?: {
role: string;
title: string;
mime: string;
content: string;
position: number;
}[];
}
export function useEditorSpacedUpdate({ note, noteContext, getData, onContentChange, dataSaved, updateInterval }: {
note: FNote,
noteContext: NoteContext | null | undefined,
getData: () => Promise<object | undefined> | object | undefined,
getData: () => Promise<SavedData | undefined> | SavedData | undefined,
onContentChange: (newContent: string) => void,
dataSaved?: () => void,
dataSaved?: (savedData: SavedData) => void,
updateInterval?: number;
}) {
const parentComponent = useContext(ParentComponent);
@ -99,7 +110,7 @@ export function useEditorSpacedUpdate({ note, noteContext, getData, onContentCha
protected_session_holder.touchProtectedSessionIfNecessary(note);
await server.put(`notes/${note.noteId}/data`, data, parentComponent?.componentId);
dataSaved?.();
dataSaved?.(data);
}
}, [ note, getData, dataSaved ])
const spacedUpdate = useSpacedUpdate(callback);

View File

@ -3,7 +3,7 @@ import NoteContext from "../../../components/note_context";
import FNote from "../../../entities/fnote";
import { AppState, BinaryFileData, ExcalidrawImperativeAPI, ExcalidrawProps, LibraryItem } from "@excalidraw/excalidraw/types";
import { useRef } from "preact/hooks";
import { useEditorSpacedUpdate } from "../../react/hooks";
import { SavedData, useEditorSpacedUpdate } from "../../react/hooks";
import { ExcalidrawElement, NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import { exportToSvg, getSceneVersion } from "@excalidraw/excalidraw";
import server from "../../../services/server";
@ -77,7 +77,7 @@ export default function useCanvasPersistence(note: FNote, noteContext: NoteConte
const api = apiRef.current;
if (!api) return;
const { content, svg } = await getData(api);
const attachments = [{ role: "image", title: "canvas-export.svg", mime: "image/svg+xml", content: svg, position: 0 }];
const attachments: SavedData["attachments"] = [{ role: "image", title: "canvas-export.svg", mime: "image/svg+xml", content: svg, position: 0 }];
// libraryChanged is unset in dataSaved()
if (libraryChanged.current) {
@ -124,7 +124,7 @@ export default function useCanvasPersistence(note: FNote, noteContext: NoteConte
title: libraryItem.id + libraryItem.name,
mime: "application/json",
content: JSON.stringify(libraryItem),
position: position
position
});
position += 10;

View File

@ -57,6 +57,10 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
onContentChange(newContent) {
contentRef.current = newContent;
watchdogRef.current?.editor?.setData(newContent);
},
dataSaved(savedData) {
// Store back the saved data in order to retrieve it in case the CKEditor crashes.
contentRef.current = savedData.content;
}
});
const templates = useTemplates();
@ -245,7 +249,9 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
}
initialized.current.resolve();
editor.setData(contentRef.current ?? "");
// Restore the data, either on the first render or if the editor crashes.
// We are not using CKEditor's built-in watch dog content, instead we are using the data we store regularly in the spaced update (see `dataSaved`).
editor.setData(contentRef.current);
parentComponent?.triggerEvent("textEditorRefreshed", { ntxId, editor });
}}
/>}