fix: broadcast full CRDT state on connect and when new user joins

CRDT broadcasts are fire-and-forget, so any updates missed during a
disconnection were permanently lost. Now when a client connects (or
reconnects), it broadcasts its full Yjs doc state. When an existing client
sees a new user join, it also broadcasts its full state. Yjs merges
handle deduplication automatically, so this converges all clients.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Gustavo Henrique Santos Souza de Miranda 2026-01-24 19:06:20 -03:00
parent 2d0c3b6df6
commit fa8437d03a
2 changed files with 15 additions and 0 deletions

View File

@ -605,6 +605,8 @@ function FlowchartEditorInner({ projectId, projectName, userId, userDisplayName,
...prev,
{ id: nanoid(), displayName: user.displayName, type: 'join', color: getUserColor(user.userId) },
])
// Send full CRDT state so the joining client gets caught up
crdtManager.broadcastFullState()
},
onPresenceLeave: (user) => {
setCollaborationNotifications((prev) => [

View File

@ -63,6 +63,19 @@ export class CRDTManager {
/** Connect to a Supabase Realtime channel for outbound broadcasts */
connectChannel(channel: RealtimeChannel): void {
this.channel = channel
// Broadcast full state so other clients merge any updates they missed
this.broadcastFullState()
}
/** Broadcast the full Yjs document state to sync all connected clients */
broadcastFullState(): void {
if (!this.channel || this.isDestroyed) return
const state = Y.encodeStateAsUpdate(this.doc)
this.channel.send({
type: 'broadcast',
event: BROADCAST_EVENT,
payload: { update: Array.from(state) },
})
}
/** Apply a remote CRDT update received via broadcast */