Skip to content

Commit d5a12f1

Browse files
fix(tables): flush layout buffered during load when the owner settles to All
Suppressing the write while the views query was in flight stopped All from being corrupted, but nothing resolved the buffer afterwards, so a resize during load looked applied and vanished on refresh. Settling on All re-seeds nothing (viewLayoutKey never changed), so the gesture is still on screen and is now persisted to shared metadata. Adopting a view re-seeds the grid from that view and has already replaced the gesture on screen, so the buffer is dropped to match.
1 parent 429d0e2 commit d5a12f1

1 file changed

Lines changed: 32 additions & 2 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/tables/[tableId]

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
useRenameTable,
4545
useRunColumn,
4646
useTableViews,
47+
useUpdateTableMetadata,
4748
useUpdateTableView,
4849
} from '@/hooks/queries/tables'
4950
import { useInlineRename } from '@/hooks/use-inline-rename'
@@ -386,6 +387,7 @@ export function Table({
386387
})
387388
const createViewMutation = useCreateTableView({ workspaceId, tableId })
388389
const updateViewMutation = useUpdateTableView({ workspaceId, tableId })
390+
const updateMetadataMutation = useUpdateTableMetadata({ workspaceId, tableId })
389391
const deleteViewMutation = useDeleteTableView({ workspaceId, tableId })
390392

391393
/** The selected view, or `null` for the built-in "All" state. A view id that no
@@ -587,6 +589,28 @@ export function Table({
587589
liveLayoutRef.current = {}
588590
}, [activeView?.id])
589591

592+
/** Layout captured before the views query settled, when no owner was known. */
593+
const pendingLayoutRef = useRef<TableMetadata>({})
594+
595+
/**
596+
* Resolves that buffer once the owner is known.
597+
*
598+
* Settling on All re-seeds nothing — `viewLayoutKey` never changed — so the
599+
* user's resize is still on screen and has to be persisted or it silently
600+
* disappears on refresh. Adopting a view instead re-seeds the grid from that
601+
* view's config, which already replaced the gesture on screen, so the buffer is
602+
* dropped to match what the user is looking at.
603+
*/
604+
useEffect(() => {
605+
if (viewOwnerUnknown) return
606+
const pending = pendingLayoutRef.current
607+
pendingLayoutRef.current = {}
608+
if (activeView || !userPermissions.canEdit) return
609+
if (Object.keys(pending).length === 0) return
610+
updateMetadataMutation.mutate(pending)
611+
// `.mutate` is stable in TanStack Query v5, so it stays out of the deps.
612+
}, [viewOwnerUnknown, activeView, userPermissions.canEdit])
613+
590614
const currentViewConfig = useMemo<TableViewConfig>(
591615
() => ({
592616
// `liveLayoutRef` after the cached config for the same reason the blank-view
@@ -663,13 +687,19 @@ export function Table({
663687
// The resize grip and drag handles stay live for read-only members, so
664688
// without this a resize fires a write-gated PATCH and an error toast. Local
665689
// layout still updates — only the persist is suppressed.
666-
if (!activeView || !userPermissions.canEdit) return
690+
if (!userPermissions.canEdit) return
691+
// Owner not known yet — hold the patch until the views query settles.
692+
if (viewOwnerUnknown) {
693+
pendingLayoutRef.current = { ...pendingLayoutRef.current, ...patch }
694+
return
695+
}
696+
if (!activeView) return
667697
updateViewMutation.mutate(
668698
{ viewId: activeView.id, configPatch: patch },
669699
{ onError: (error) => toast.error(getErrorMessage(error, 'Failed to save layout')) }
670700
)
671701
},
672-
[activeView, userPermissions.canEdit]
702+
[activeView, userPermissions.canEdit, viewOwnerUnknown]
673703
)
674704

675705
const handleSaveView = () => {

0 commit comments

Comments
 (0)