refactor(datagrid): name-based identifiers + native sort indicators#942
refactor(datagrid): name-based identifiers + native sort indicators#942
Conversation
… binding-mutation Task pattern
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3922ad5871
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
| saveColumnVisibilityToTab() | ||
| saveColumnLayoutForTable() | ||
| saveColumnVisibilityForActiveTable() |
There was a problem hiding this comment.
Persist outgoing table layout before tab context changes
Switching tabs no longer calls saveColumnLayoutForTable(), so layout writes now depend only on the debounced scheduleLayoutPersist() path in the grid coordinator. If the user resizes/reorders a column and switches tabs within the 500ms debounce window, the coordinator is rebound to the new tab before the task fires, so the outgoing tab’s latest layout can be lost (and the delayed write can target the wrong table context). This is a user-visible data-loss regression for column widths/order on quick tab switches.
Useful? React with 👍 / 👎.
…edundant calls, add coordinator + schema-shift tests
…t trigger rebuild path
…lacement, syncSortDescriptors state
…er on every sorted column
…rop SF Symbol fallback and highlightedTableColumn duplication
… not double-draw on primary
…awing duplicate chevron over custom cell
…ryLabelColor to match AppKit's subtle gray
…t so fill respects only image alpha
… subtle gray match
…ator to match modern AppKit native style
…d tertiary label color
…icator for pixel-perfect chevron rendering on every sorted column
…ve HIG-correct unsort UX
…3-state, SortableHeaderView only intercepts shift-click for multi-sort
…Cell to fix ARC crash on sort
… in offscreen context to avoid ARC crash on sort
…ew setIndicatorImage API to fix crash
…icators — pure native, no NSCell subclass
…raw duplicate chevron + bold title on primary
…dicator on primary sort column
…tIndicator to no-op — kills AppKit auto-indicator at source, no Swift property = no ARC crash
…eral col_0 identifier
Summary
highlightedTableColumn+setIndicatorImage(_:in:)) replace Unicode arrows embedded in column titles; FK/chevron button context resets on cell reuse; column reorder no longer scans the settled prefix per move;applyColumnOrderfix.DataGridView.columnIdentifier(for:)/dataColumnIndex(from:)helpers are gone, replaced by aColumnIdentitySchemavalue type owned by the coordinator.ColumnLayoutStoragesingleton replaced by aColumnLayoutPersistingprotocol with an injectableFileColumnLayoutPersisterdefault. The coordinator depends on the protocol, not the concrete class.MainContentCoordinator+ColumnLayoutand thehasUserResizedColumnsflag are deleted; layout save/restore now lives entirely in the data grid coordinator's lifecycle (load on column build, persist on resize/move/dismantle). TheTask-based@Bindingmutation insideupdateNSViewand theisWritingColumnLayoutre-entry guard are also gone.Why not
NSTableView.autosaveName: it would force positional column identifiers (the schema-shift bug returns), and depends on an undocumented UserDefaults format Apple can change between macOS releases. The principled native pattern isNSTableColumn.identifiersemantics — and we now use the column name as that identifier, which is robust to schema changes. The persister is custom because our domain (per-(connection, table), multi-tab, tab-state-restorable) doesn't fit the autosave abstraction.Test plan
SELECT a, b, a): no crash, columns render, identifier scheme falls back to positional.xcodebuild test— ColumnIdentitySchemaTests (8), FileColumnLayoutPersisterTests (6), ColumnLayoutStateTests, ColumnVisibilityManagerTests, SortStateTests all pass.swiftlint lint --strict— 0 violations.