Hello,
I have an application featuring a rich content editor based on TipTap. Currently, the application supports real-time updates for a single editor, using websockets for data synchronization. Now, I’m interested in extending this to allow multi-user editing. For this, I’ve started integrating @tiptap/extension-collaboration
along with Yjs.
Objective:
I wish to create a custom provider to plug into my existing websocket service for Yjs. Specifically, the provider must adhere to a custom save format that my application uses.
Issue:
I have initiated the development of a custom Yjs provider, but it is incomplete and not functional. I need guidance on the required logic and structure.
Code Sample:
Here is a skeleton of the custom provider I started building:
import * as Y from 'yjs';
import { Observable } from 'lib0/observable';
export class MyCustomProvider extends Observable {
constructor(doc, updateHandler) {
super();
this.doc = doc;
this._synced = false;
this._updateCallback = null;
this._updateHandler = (update, origin) => {
if (origin !== this) {
if (updateHandler) {
// This is working, I get the updates every time the doc is updated
updateHandler(update, origin);
}
}
}
this.doc.on('update', this._updateHandler);
}
// This is called by the editor to apply updates
applyUpdates(updates) {
this.doc.transact(() => {
updates.forEach(update =>
// This is not working, the updates are not applied to the doc
Y.applyUpdate(this.doc, update)
)
});
}
destroy() {
this.doc.off('update', this._updateHandler);
super.destroy();
}
}
I instantiate and use it like so:
import { Editor } from '@tiptap/core';
import Collaboration from '@tiptap/extension-collaboration';
import * as Y from 'yjs';
const doc = new Y.Doc();
const documentProvider = new NapkinCustomProvider(doc, onUpdate);
const editor = new Editor({
extensions: [
Collaboration.configure({
document: documentProvider.doc,
}),
],
});
function onUpdate(update, origin) {
// Send the update through the network
}
// Called when the second user receives updates from the network
function onReceiveUpdates(updates) {
// Apply the update to the document
this.documentProvider.applyUpdates(updates);
}
Problems:
-
Although the
onUpdate
function receives updates, applying these updates on the second user’s document usingUint8Array
does not yield any changes. -
There is a gap in my understanding of how to correctly structure a custom provider for Yjs to use with TipTap.
Questions:
-
Is there a guide, documentation, or example detailing how to correctly structure a custom Yjs provider?
-
Are there specific steps to ensure that
Uint8Array
updates received through websockets are correctly applied to the Yjs document?
I looked at the documentation and didn’t find anything.
I look forward to your assistance on these issues.
Thank you!