Skip to content

fix(datagrid): reload the structure grid on filter and sort instead of showing stale rows#1840

Merged
datlechin merged 2 commits into
mainfrom
fix/structure-filter-stale-rows
Jul 9, 2026
Merged

fix(datagrid): reload the structure grid on filter and sort instead of showing stale rows#1840
datlechin merged 2 commits into
mainfrom
fix/structure-filter-stale-rows

Conversation

@datlechin

Copy link
Copy Markdown
Member

Problem

The Structure tab's Filter field and column sort showed stale rows. Typing in the filter changed the visible row count but the cell text stayed wrong, and sorting a column often did nothing.

Root cause

The Structure grid rebuilds its rows on every filter/sort with positional row IDs. The grid only reloads when its DataGridUpdateSnapshot changes, and that snapshot tracks row count, columns, and reloadVersion, not which rows are shown. The display cache is keyed by row ID and is only cleared on a reloadVersion bump. A filter or sort bumps neither, so reloadData() was skipped whenever the row count stayed the same, and the cache returned the previous rows' text for the reused positional IDs.

Fix

Thread the Structure view's existing content counter (displayVersion) into the grid as a generic contentRevision. A change in it counts as a content change, which already drives both display-cache invalidation and reloadData(). This runs on one deterministic path in updateNSView and fixes filter and sort at any row count. The other grids (data tab, inspector, create table) pass the default 0 and are unaffected.

Behavior stays as documented: live, name-only filtering and header-click sort. This matches Apple's contract that visible cells only reflect new data after reloadData() / reloadData(forRowIndexes:), and the data tab's own content-replace pattern (invalidate the cache, then reload).

Tests

  • The reload gate reacts to a contentRevision change at a constant row count.
  • The display cache serves stale content for a reused row ID until it is invalidated.
  • StructureRowProvider filters by name (case-insensitive) and keeps filteredToSourceMap aligned across filter and sort.

Notes

  • Structure keeps displayIDs == nil, so the edit/delete/copy index translation and the "selection indices are display positions" invariant are untouched.
  • swiftlint --strict clean on the changed files.

@datlechin datlechin merged commit a64d5dd into main Jul 9, 2026
@datlechin datlechin deleted the fix/structure-filter-stale-rows branch July 9, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant