git.iko.soy/parseable-macos
on master help sign in
Fix 4 bugs: double reconnect on active connection edit, stale sidebar streams/filters, stale users list, validation state persistence
commitd4178194b560b76911644346bbbbe56a41ac6f04 authoriko <mail@iko.soy> dateSun 21 Jun 2026, 21:29 (3 months ago) parent5433a10
3 files changed+20−12
ParseableViewer/App/AppState.swift+15−12 ParseableViewer/Views/ConnectionSheet.swift+1 ParseableViewer/Views/UsersView.swift+4
ParseableViewer/App/AppState.swift+15−12
@@ -287,23 +287,26 @@ final class AppState {
287287 // If the active connection was edited, its URL or credentials may now point
288288 // at a different server, so swapping the client alone isn't enough — the
289289 // displayed streams/selection/server-info would be stale and queries would
290− // 404. Reconnect end to end (re-validate health, reload streams/filters/
291− // about). Clear the stream selection first so a now-missing stream doesn't
292− // keep driving detail-tab requests during the reconnect.
290+ // 404. The caller is responsible for the actual reconnect (re-validate
291+ // health, reload streams/filters/about); we only clear the now-possibly-
292+ // stale UI state here, since `performConnect` skips its own cleanup when the
293+ // connection id is unchanged. We must NOT also spawn a connect here: the
294+ // sole caller (ConnectionSheet.saveAndConnect) already connects right after,
295+ // and a second connect would run two full reconnects and flash the UI twice.
293296 if activeConnection?.id == connection.id {
294− // `performConnect` skips its stale-state cleanup because the id is
295− // unchanged, but the edited URL/credentials may point at a different
296− // server. Clear the stream-specific UI state here so a leftover sidebar
297− // search filter doesn't hide the new server's streams and a
298− // stream-specific tab doesn't linger with no valid selection.
297+ // Clear the stream-specific UI state so a leftover sidebar search filter
298+ // doesn't hide the new server's streams and a stream-specific tab
299+ // doesn't linger with no valid selection.
299300 selectedStream = nil
300301 streamSearchText = ""
301302 currentTab = .query
302− // Drop the previous server's cached `about` too — performConnect skips
303− // its own clear (id unchanged), so without this ServerInfoView keeps
304− // painting the old server's version/storage until the new /about lands.
303+ // Drop the previous server's cached `about`, stream list, and filters —
304+ // performConnect skips its own clear (id unchanged), so without this the
305+ // sidebar keeps rendering server A's streams/filters and ServerInfoView
306+ // paints the old version/storage until the new server's responses land.
305307 serverAbout = nil
306− Task { await connect(to: connection) }
308+ streams = []
309+ filters = []
307310 }
308311 }
309312
ParseableViewer/Views/ConnectionSheet.swift+1
@@ -43,6 +43,7 @@ struct ConnectionSheet: View {
4343 TextField("Name:", text: $name)
4444 .textFieldStyle(.roundedBorder)
4545 .accessibilityLabel("Connection name")
46+ .onChange(of: name) { _, _ in testResult = nil }
4647
4748 TextField("Server URL:", text: $url)
4849 .textFieldStyle(.roundedBorder)
ParseableViewer/Views/UsersView.swift+4
@@ -84,6 +84,10 @@ struct UsersView: View {
8484 let connID = appState.activeConnection?.id
8585 isLoading = true
8686 errorMessage = nil
87+ // Clear the previous server's list up front so it can't briefly show through
88+ // after a switch (e.g. on the stale-guard early-return below). Matches the
89+ // sibling views (AlertsView clears alertConfig, ServerInfoView clears about).
90+ users = []
8791
8892 let loaded: [UserInfo]?
8993 let loadError: String?