Skip to content

Commit 61330b7

Browse files
committed
feat: add accepting and rejecting changes
1 parent e82fdb1 commit 61330b7

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

examples/07-collaboration/01-partykit/App.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,19 @@ export default function App() {
3636
onClick={() => {
3737
editor.pauseYjsSync();
3838
}}>
39-
Pause
39+
Pause syncing
4040
</button>
4141
<button
4242
onClick={() => {
43-
editor.resumeYjsSync();
43+
editor.resumeYjsSync(true);
4444
}}>
45-
Play
45+
Play (accept changes)
46+
</button>
47+
<button
48+
onClick={() => {
49+
editor.resumeYjsSync(false);
50+
}}>
51+
Play (reject changes)
4652
</button>
4753
<BlockNoteView editor={editor} />
4854
</>

packages/core/src/editor/BlockNoteEditor.ts

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,44 @@ export class BlockNoteEditor<
942942
};
943943
}
944944

945+
/**
946+
* To find a fragment in another ydoc, we need to search for it.
947+
*/
948+
private findTypeInOtherYdoc<T extends Y.AbstractType<any>>(
949+
ytype: T,
950+
otherYdoc: Y.Doc
951+
): T {
952+
const ydoc = ytype.doc!;
953+
if (ytype._item === null) {
954+
/**
955+
* If is a root type, we need to find the root key in the original ydoc
956+
* and use it to get the type in the other ydoc.
957+
*/
958+
const rootKey = Array.from(ydoc.share.keys()).find(
959+
(key) => ydoc.share.get(key) === ytype
960+
);
961+
if (rootKey == null) {
962+
throw new Error("type does not exist in other ydoc");
963+
}
964+
return otherYdoc.get(rootKey, ytype.constructor as new () => T) as T;
965+
} else {
966+
/**
967+
* If it is a sub type, we use the item id to find the history type.
968+
*/
969+
const ytypeItem = ytype._item;
970+
const otherStructs =
971+
otherYdoc.store.clients.get(ytypeItem.id.client) ?? [];
972+
const itemIndex = Y.findIndexSS(otherStructs, ytypeItem.id.clock);
973+
const otherItem = otherStructs[itemIndex] as Y.Item;
974+
const otherContent = otherItem.content as Y.ContentType;
975+
return otherContent.type as T;
976+
}
977+
}
978+
979+
public get isRemoteSyncing() {
980+
return this.yjsState !== undefined;
981+
}
982+
945983
private yjsState:
946984
| {
947985
prevFragment: Y.XmlFragment;
@@ -950,15 +988,22 @@ export class BlockNoteEditor<
950988
| undefined;
951989

952990
public pauseYjsSync() {
991+
if (this.isRemoteSyncing) {
992+
return;
993+
}
994+
953995
const prevFragment = this.options.collaboration?.fragment;
954996

955997
if (!prevFragment) {
956998
throw new Error("No Yjs document found");
957999
}
9581000

959-
const nextFragment = prevFragment.clone();
1001+
const update = Y.encodeStateAsUpdate(prevFragment.doc!);
1002+
9601003
const doc = new Y.Doc();
961-
doc.getMap().set("cpy", nextFragment);
1004+
Y.applyUpdate(doc, update);
1005+
1006+
const nextFragment = this.findTypeInOtherYdoc(prevFragment, doc);
9621007

9631008
this.yjsState = {
9641009
prevFragment,
@@ -970,17 +1015,21 @@ export class BlockNoteEditor<
9701015
this._tiptapEditor.registerPlugin(ySyncPlugin(nextFragment));
9711016
}
9721017

973-
public resumeYjsSync() {
1018+
public resumeYjsSync(mergeChanges = false) {
9741019
if (!this.yjsState) {
9751020
throw new Error("No Yjs document found");
9761021
}
9771022
this._tiptapEditor.unregisterPlugin(ySyncPluginKey);
978-
this._tiptapEditor.registerPlugin(
979-
new SyncPlugin(this.yjsState.prevFragment).plugin
980-
);
1023+
const fragment = this.yjsState.prevFragment;
1024+
if (mergeChanges) {
1025+
const update = Y.encodeStateAsUpdate(this.yjsState.nextFragment.doc!);
1026+
Y.applyUpdate(fragment.doc!, update);
1027+
}
1028+
this._tiptapEditor.registerPlugin(new SyncPlugin(fragment).plugin);
9811029
this.cursorPlugin = new CursorPlugin(this.options.collaboration!);
9821030
this._tiptapEditor.registerPlugin(this.cursorPlugin.plugin);
9831031
this._tiptapEditor.registerPlugin(new UndoPlugin().plugin);
1032+
this.yjsState = undefined;
9841033
}
9851034

9861035
/**

0 commit comments

Comments
 (0)