This problem very similar to this one, but I’m using only Y.Array’s and primitive data.
I have an application which has containers that contain elements. These containers are implemented as Y.Array’s. Elements are primitive strings.
You can drag an element from a container to another. This is currently implemented as a splice() in the first Y.Array and an insert() in the second Y.Array.
This works well until I introduce undo-redo functionality. That’s when duplications start occurring.
This is the output of some test I implemented:
Before user 1 moves data from A to B: (A: ['data-being-moved'] , B: [] )
After user 1 moves data from A to B: (A: [] , B: ['data-being-moved'] )
After user 2 moves data from B to A: (A: ['data-being-moved'] , B: [] )
After user 2 undoes B-to-A move: (A: [] , B: ['data-being-moved'] )
After user 1 undoes A-to-B move: (A: ['data-being-moved'] , B: ['data-being-moved'] )
How would this functionality be implemented in Yjs?
Thanks.
Full test implementation:
const yDoc1 = new Y.Doc();
const yDoc2 = new Y.Doc();
yDoc1.on('update', (update) => Y.applyUpdate(yDoc2, update));
yDoc2.on('update', (update) => Y.applyUpdate(yDoc1, update));
const yArrayA1 = yDoc1.getArray<string>('arrayA');
const yArrayA2 = yDoc2.getArray<string>('arrayA');
const yArrayB1 = yDoc1.getArray<string>('arrayB');
const yArrayB2 = yDoc2.getArray<string>('arrayB');
function logArrays(message: string) {
console.log(
`${message}:`,
'(A:',
yArrayA1.toArray(),
', B:',
yArrayB1.toArray(),
')'
);
}
// Initialize Y.Doc data
Y.transact(
yDoc1,
() => {
yArrayA1.push(['data-being-moved']);
},
yDoc1.clientID
);
const undoManager1 = new Y.UndoManager([yArrayA1, yArrayB1], {
trackedOrigins: new Set([yDoc1.clientID]),
});
const undoManager2 = new Y.UndoManager([yArrayA2, yArrayB2], {
trackedOrigins: new Set([yDoc2.clientID]),
});
logArrays('Before user 1 moves data from A to B');
// User 1 moves data from yArrayA to yArrayB
Y.transact(
yDoc1,
() => {
yArrayA1.delete(0);
yArrayB1.push(['data-being-moved']);
},
yDoc1.clientID
);
logArrays('After user 1 moves data from A to B');
// User 2 moves data from yArrayB to yArrayA
Y.transact(
yDoc2,
() => {
yArrayB2.delete(0);
yArrayA2.push(['data-being-moved']);
},
yDoc2.clientID
);
logArrays('After user 2 moves data from B to A');
// User 2 undoes move from B to A
undoManager2.undo();
logArrays('After user 2 undoes B-to-A move');
// User 1 undoes move from A to B
undoManager1.undo();
logArrays('After user 1 undoes A-to-B move');