Restoring TipTap previous state

Hello,

In my app, I need to automatically save the TipTap editor state and restore it after a few seconds when a specific user action occurs. I’m using the latest versions of TipTap and YJS.

I’ve tried two approaches, but both have issues:

1- Save and Restore TipTap JSON State
Here’s the simplified code:

const state = editor.getJSON();
// Save the state
// Restore it
editor.commands.setContent(state);

It visually works, but I get this error:

RangeError: Applying a mismatched transaction
    at EditorState.applyInner
    at EditorState.applyTransaction
    at EditorState.apply
    at Editor.dispatchTransaction
    at EditorView.dispatch

I suspect this happens because the JSON state isn’t synced with YJS.

2- Use YJS Snapshots to Restore State
I explored the YJS snapshot feature but ran into additional challenges. Specifically, I couldn’t find a straightforward way to restore an update. To simplify, I attempted to create a new update to revert the diff between the current state and the snapshot.

I found this post, but the suggested solution didn’t work in my case (no errors, but the document remains unchanged).

Here’s a simplified version of my current code:

this.document.gc = false;
const tempDocument = Y.createDocFromSnapshot(this.document, snapshot);

const currentStateVector = Y.encodeStateVector(this.document);
const snapshotStateVector = Y.encodeStateVector(tempDocument);

const changesSinceSnapshotUpdate = Y.encodeStateAsUpdate(this.document, snapshotStateVector);

const um = new Y.UndoManager([...tempDocument.share.values()]);
Y.applyUpdate(tempDocument, changesSinceSnapshotUpdate);
um.undo();

const revertChangesSinceSnapshotUpdate = Y.encodeStateAsUpdate(tempDocument, currentStateVector);
Y.applyUpdate(this.document, revertChangesSinceSnapshotUpdate, { user: { id: 'revert' } });
  • Am I overlooking something with either approach?
  • Is there a better way to handle this scenario with TipTap and YJS?
  • Any specific recommendations or examples for restoring a previous state seamlessly?

Thank you in advance for your insights!

For the first issue, you should consult the TipTap authors. Yjs should be able to handle this.

For the second issue: The sample code looks about right.

  • Try setting const changesSinceSnapshotUpdate = Y.encodeStateAsUpdate(this.document).
  • Try adding the specific type to the Y.UndoManager([tempDocument.getText('name')]).
  • Try setting an origin when applying an update: tempDocument.transact(() => { Y.applyUpdate(..) }, null).