mirror of
https://github.com/simstudioai/sim.git
synced 2026-10-25 09:34:44 +08:00
fix(tables): re-broadcast selection when a peer's row change shifts it
End-to-end lifecycle audit (Low-Med): the selection emit resolved the stable (rowId, columnId) only on selection/editing change, not when a live edit/schema refetch inserted/deleted/reordered rows. The index-based local selection then sat on a different logical row than the rowId peers held, so your outline showed on the old row until you moved. Re-run the emit on rows/displayColumns change and dedup an unchanged result (also drops the redundant null-on-open emit) so the broadcast stays consistent with the local highlight.
This commit is contained in:
+7
-8
@@ -836,16 +836,15 @@ export function TableGrid({
|
||||
: null
|
||||
|
||||
// Broadcast the local viewer's cell selection to the presence room. Resolves the
|
||||
// index-based selection to stable (rowId, columnId) through refs so it re-emits only
|
||||
// on a real selection/editing change, not on every data update. `editing` marks the
|
||||
// active cell so peers darken it (the "someone is typing here" signal).
|
||||
// index-based selection to stable (rowId, columnId), re-running on `rows`/`displayColumns`
|
||||
// too so a peer's row insert/delete/reorder re-broadcasts the shifted id under the same
|
||||
// index (the emitter dedups an unchanged result). `editing` marks the active cell so
|
||||
// peers darken it (the "someone is typing here" signal).
|
||||
useEffect(() => {
|
||||
const currentRows = rowsRef.current
|
||||
const currentCols = columnsRef.current
|
||||
const resolve = (coord: CellCoord | null) => {
|
||||
if (!coord) return null
|
||||
const rowId = currentRows[coord.rowIndex]?.id
|
||||
const columnId = currentCols[coord.colIndex]?.key
|
||||
const rowId = rows[coord.rowIndex]?.id
|
||||
const columnId = displayColumns[coord.colIndex]?.key
|
||||
return rowId && columnId ? { rowId, columnId } : null
|
||||
}
|
||||
const anchor = resolve(selectionAnchor)
|
||||
@@ -858,7 +857,7 @@ export function TableGrid({
|
||||
// most common selection would never broadcast and would clear the prior outline.
|
||||
const focus = resolve(selectionFocus) ?? anchor
|
||||
emitCellSelection({ anchor, focus, editing: editingCell !== null })
|
||||
}, [selectionAnchor, selectionFocus, editingCell, emitCellSelection])
|
||||
}, [selectionAnchor, selectionFocus, editingCell, rows, displayColumns, emitCellSelection])
|
||||
|
||||
const { data: findData, isFetching: isFindFetching } = useFindTableRows({
|
||||
workspaceId,
|
||||
|
||||
@@ -150,6 +150,8 @@ export function useTableRoom(tableId: string): UseTableRoomResult {
|
||||
const lastEmitRef = useRef(0)
|
||||
const trailingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const pendingCellRef = useRef<TableCellSelection>(null)
|
||||
/** Key of the last selection sent, to skip re-emitting an unchanged selection. */
|
||||
const lastSentKeyRef = useRef<string | null>(null)
|
||||
|
||||
// Reset the throttle when the table changes (or on unmount): a pending selection for
|
||||
// the table we're leaving must not flush into the next table's room after a switch.
|
||||
@@ -161,12 +163,19 @@ export function useTableRoom(tableId: string): UseTableRoomResult {
|
||||
}
|
||||
pendingCellRef.current = null
|
||||
currentCellRef.current = null
|
||||
lastSentKeyRef.current = null
|
||||
lastEmitRef.current = 0
|
||||
},
|
||||
[tableId]
|
||||
)
|
||||
|
||||
const emitCellSelection = useCallback((cell: TableCellSelection) => {
|
||||
// Skip re-emitting an unchanged selection: the caller re-resolves on every data
|
||||
// refetch (so a peer's row insert re-broadcasts the shifted rowId), but most refetches
|
||||
// don't move the selection — dedup those, and the no-selection state on table open.
|
||||
const key = cell === null ? 'null' : JSON.stringify(cell)
|
||||
if (key === lastSentKeyRef.current) return
|
||||
lastSentKeyRef.current = key
|
||||
currentCellRef.current = cell
|
||||
pendingCellRef.current = cell
|
||||
const flush = () => {
|
||||
|
||||
Reference in New Issue
Block a user