Let’ say user does an action called ‘turn on share’
It triggers the following transaction
const toggleSharing = () => {
yDoc.transact(() => {
yDoc.getMap().set("sharing", !doc().sharing)
if (doc().sharing && !doc().roomId) {
yDoc.getMap().set("roomId", crypto.randomUUID())
}
})
}
And I listen to local changes in “update” handler and send the message to other peers
yDoc.on("update", (update, _, __, tr) => {
console.log('update', tr.local, tr.origin)
if (tr.local) {
// change made by current user, send to peers
const base64Update = fromUint8ArrayToBase64(update)
const message = {type: 'docUpdate', data: base64Update}
sendMessage(message)
}
// update local doc
setDoc(yDoc.getMap().toJSON() as any)
})
And on peer side I do
const {type, data} = message
switch (type) {
case "docUpdate": {
Y.applyUpdate(yDoc, fromBase64ToUint8Array(data))
break
}
The underlying data gets synced this way, but the peer doesn’t know what “action” caused the data to change.
Is there any way to pass event data with customer properties as part of the transaction?
From the docs I can see that transaction takes in an origin property of any type so I thought i could potentioally do
const toggleSharing = () => {
yDoc.transact(() => {
yDoc.getMap().set("sharing", !doc().sharing)
if (doc().sharing && !doc().roomId) {
yDoc.getMap().set("roomId", crypto.randomUUID())
}
}, {author: user.id || 'server', event: 'toggle on sharing', ...anyOtherData})
}
And in the update listener
yDoc.on("update", (update, _, __, tr) => {
console.log('update', tr.local, tr.origin)
const {author, event, ...props} = tr.origin
if (tr.local) {
// change made by current user, send to peers
const base64Update = fromUint8ArrayToBase64(update)
const message = {type: 'docUpdate', data: base64Update, event, ...props}
sendMessage(message)
}
// update local doc
setDoc(yDoc.getMap().toJSON() as any)
})
And on the peer side
const {type, data, event, otherProps} = message
switch (type) {
case "docUpdate": {
Y.applyUpdate(yDoc, fromBase64ToUint8Array(data))
if (event === 'toggle on sharing') {
// Do something, like show a toast, etc
}
break
}
Is this way of passing metadata as part of origin ok or is there another recommended way of doing so?