@@ -157,7 +157,11 @@ struct StreamDetailView: View {
158 .padding()
158 .padding()
160+ // Key on the connection too: switching to a different server that
161+ // exposes a same-named stream leaves `stream` unchanged, so without
162+ // the connection id the task wouldn't refire and the old server's
163+ // data would linger.
160− .task(id: stream) {
164+ .task(id: "\(appState.activeConnection?.id.uuidString ?? "")|\(stream)") {
161 await loadData(stream: stream)
165 await loadData(stream: stream)
@@ -172,6 +176,11 @@ struct StreamDetailView: View {
173 private func loadData(stream: String) async {
177 private func loadData(stream: String) async {
174 guard let client = appState.client else { return }
178 guard let client = appState.client else { return }
179+ // Capture the connection this fetch belongs to. Two servers can expose a
180+ // same-named stream, so guarding on the stream name alone would let a
181+ // slow fetch write the previous server's data under the new server's
182+ // stream after a server switch.
183+ let connID = appState.activeConnection?.id
175 isLoading = true
184 isLoading = true
176 errorMessage = nil
185 errorMessage = nil
177 // Clear previous stream's data so it isn't shown under the new header
186 // Clear previous stream's data so it isn't shown under the new header
@@ -205,8 +214,13 @@ struct StreamDetailView: View {
205 // The manual Refresh/Retry buttons spawn detached Tasks that aren't tied to
214 // The manual Refresh/Retry buttons spawn detached Tasks that aren't tied to
206 // `.task(id: stream)` cancellation, so a slow refresh for the old stream can
215 // `.task(id: stream)` cancellation, so a slow refresh for the old stream can
207 // resolve after the user switched. Drop stale results instead of writing
216 // resolve after the user switched. Drop stale results instead of writing
208− // them under the new stream's header.
217+ // them under the new stream's header. Also check the connection so a
218+ // same-named stream on a different server doesn't accept the old server's
219+ // data. Reset `isLoading` on the stale path or the spinner wedges forever.
209− guard stream == appState.selectedStream else { return }
220+ guard stream == appState.selectedStream, connID == appState.activeConnection?.id else {
211 schema = newSchema
225 schema = newSchema
212 stats = newStats
226 stats = newStats