feat(refboard): incremental sync — stop full-scene broadcast on edits

Replace broadcastSceneNow() with incremental element:update for all
property-modifying operations (align, arrange, flip, resize, rotate,
normalize, frame color). Full scene sync now only fires via debounced
fallback (500ms) for structural changes (add/remove/paste/group).

Changes:
- onCanvasChange() accepts optional changedIds for incremental sync
- SelectionToolbar, context menu, shortcuts all pass item IDs
- TransformBox.onDragEnd passes item IDs instead of full scene
- ShortcutContext, MenuContext, hook interfaces updated

This dramatically reduces sync traffic during normal editing — only
the changed elements are sent instead of the entire board state.
This commit is contained in:
Hiren Kangad
2026-03-10 10:59:04 +05:30
parent 86024464c2
commit 21ee4b2601
8 changed files with 57 additions and 51 deletions
+4 -4
View File
@@ -40,7 +40,7 @@ interface CanvasSetupDeps {
undoRef: React.MutableRefObject<UndoManager | null>;
syncRef: React.MutableRefObject<SyncHandle | null>;
inboxZoneRef: React.MutableRefObject<InboxZone | null>;
onCanvasChange: () => void;
onCanvasChange: (changedIds?: string[]) => void;
showToast: (msg: string) => void;
setOnlineUsers: React.Dispatch<React.SetStateAction<OnlineUser[]>>;
setSelectedLayerIds: React.Dispatch<React.SetStateAction<string[]>>;
@@ -136,9 +136,9 @@ export function useCanvasSetup(deps: CanvasSetupDeps) {
selection.transformBox.onItemTransform = (item) => {
syncRef.current?.broadcastTransform(item);
};
selection.transformBox.onDragEnd = () => {
syncRef.current?.broadcastSceneNow();
onCanvasChange();
selection.transformBox.onDragEnd = (itemIds) => {
syncRef.current?.broadcastElements(itemIds);
onCanvasChange(itemIds);
};
socket.on('user:joined', (data: any) => {