git.iko.soy/parseable-macos
on master help sign in
Fix 3 bugs: shared JSONDecoder data race, stale selectedLogEntry after re-query, unreachable connection edit
commit129bc9959a32e196126d934e03d51d64920423ee authoriko <mail@iko.soy> dateMon 22 Jun 2026, 02:21 (3 months ago) parentf47f680
3 files changed+17−1
ParseableViewer/Services/ParseableClient.swift+4−1 ParseableViewer/ViewModels/QueryViewModel.swift+4 ParseableViewer/Views/SettingsView.swift+9
ParseableViewer/Services/ParseableClient.swift+4−1
@@ -96,7 +96,10 @@ final class ParseableClient: Sendable {
9696 private let authHeader: String
9797 private let cache = ResponseCache()
9898
99− private static nonisolated(unsafe) let jsonDecoder = JSONDecoder()
99+ // A fresh decoder per call. JSONDecoder.decode isn't documented as thread-safe,
100+ // and these methods run concurrently (e.g. schema/stats/info fetched in parallel),
101+ // so a single shared instance would be a data race. Constructing one is cheap.
102+ private static var jsonDecoder: JSONDecoder { JSONDecoder() }
100103
101104 private static nonisolated(unsafe) let isoFormatter: ISO8601DateFormatter = {
102105 let f = ISO8601DateFormatter()
ParseableViewer/ViewModels/QueryViewModel.swift+4
@@ -402,6 +402,10 @@ final class QueryViewModel {
402402 guard !Task.isCancelled else { return }
403403
404404 results = queryResults
405+ // Drop any prior row selection: the new result set reassigns row
406+ // identities, so a retained selectedLogEntry would either dangle or
407+ // value-match an unrelated row, leaving a stale detail inspector.
408+ selectedLogEntry = nil
405409 queryDuration = CFAbsoluteTimeGetCurrent() - startTime
406410 resultCount = results.count
407411
ParseableViewer/Views/SettingsView.swift+9
@@ -76,11 +76,20 @@ struct SettingsView: View {
7676 .clipShape(RoundedRectangle(cornerRadius: 4))
7777 }
7878
79+ Button {
80+ appState.editingConnection = connection
81+ appState.showConnectionSheet = true
82+ } label: {
83+ Image(systemName: "pencil")
84+ }
85+ .help("Edit connection")
86+
7987 Button(role: .destructive) {
8088 appState.removeConnection(connection)
8189 } label: {
8290 Image(systemName: "trash")
8391 }
92+ .help("Delete connection")
8493 }
8594 .padding(.vertical, 4)
8695 }