Skip to content

Commit 2212892

Browse files
authored
fix(datagrid): show data after Data/Structure/JSON view-mode toggle (#981)
1 parent 56cacc8 commit 2212892

4 files changed

Lines changed: 23 additions & 4 deletions

File tree

TablePro/Models/Query/TabSessionRegistry.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,11 @@ final class TabSessionRegistry {
6565
sessions[tabId]?.isEvicted ?? false
6666
}
6767

68-
/// Evict row data for a tab. Sets `isEvicted = true` and bumps `loadEpoch`
69-
/// so SwiftUI's `.task(id:)` lazy-load re-fires.
68+
/// Evict row data for a tab. Sets `isEvicted = true`, clears rows, and
69+
/// bumps the session's `loadEpoch`. Note that SwiftUI's `.task(id:)` keys
70+
/// on `QueryTab.loadEpoch` (the value-type tab in `tabManager.tabs`), not
71+
/// on `TabSession.loadEpoch` — so callers that need lazy-load to re-fire
72+
/// must also bump `tabManager.tabs[i].loadEpoch` separately.
7073
///
7174
/// Returns early if the session has no rows to evict — calling `evict` on
7275
/// a tab with empty rows is a no-op (no `isEvicted` change, no epoch bump),

TablePro/Views/Main/Extensions/MainContentCoordinator+TabSwitch.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ extension MainContentCoordinator {
150150

151151
for entry in toEvict {
152152
tabSessionRegistry.evict(for: entry.tab.id)
153+
if let index = tabManager.tabs.firstIndex(where: { $0.id == entry.tab.id }) {
154+
// Bump QueryTab.loadEpoch to invalidate the `.task(id:)` key in
155+
// MainEditorContentView, so the next selection of this tab
156+
// triggers lazy-load. The session-side bump is not observed.
157+
tabManager.tabs[index].loadEpoch &+= 1
158+
}
153159
}
154160
Self.lifecycleLogger.debug(
155161
"[switch] evictInactiveTabs evicted=\(toEvict.count) keptInactive=\(maxInactiveLoaded) elapsedMs=\(Int(Date().timeIntervalSince(start) * 1_000))"

TablePro/Views/Main/MainContentCoordinator.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,13 @@ final class MainContentCoordinator {
290290
/// Background tabs are re-fetched automatically when selected.
291291
func evictInactiveRowData() {
292292
let selectedId = tabManager.selectedTabId
293-
for tab in tabManager.tabs where tab.id != selectedId && !tab.pendingChanges.hasChanges {
293+
for (index, tab) in tabManager.tabs.enumerated()
294+
where tab.id != selectedId && !tab.pendingChanges.hasChanges {
294295
tabSessionRegistry.evict(for: tab.id)
296+
// Mirror the session's epoch bump back to the QueryTab so the
297+
// `.task(id:)` in MainEditorContentView re-fires lazy-load on
298+
// re-selection. The session bump alone is not observed by SwiftUI.
299+
tabManager.tabs[index].loadEpoch &+= 1
295300
}
296301
}
297302

TablePro/Views/Results/DataGridView.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ struct DataGridView: NSViewRepresentable {
110110
context.coordinator.tableRowsProvider = tableRowsProvider
111111
context.coordinator.tableRowsMutator = tableRowsMutator
112112
context.coordinator.sortedIDs = sortedIDs
113-
context.coordinator.updateCache()
113+
// Intentionally do not prime cachedRowCount/cachedColumnCount here.
114+
// They represent what NSTableView has actually rendered. Leaving them
115+
// at 0 ensures the first `updateNSView` detects a structure change
116+
// and triggers `reloadData()` — without this, a recreated grid (e.g.
117+
// after a Structure/JSON tab toggle) finds the cache already matching
118+
// the registry rows and skips the reload, leaving the table empty.
114119
context.coordinator.syncDisplayFormats(displayFormats)
115120
context.coordinator.delegate = delegate
116121
delegate?.dataGridAttach(tableViewCoordinator: context.coordinator)

0 commit comments

Comments
 (0)