Showing 2 changed files with 27 additions and 4 deletions
+23 -4
HealthProbe/Services/HealthKitService.swift
@@ -86,6 +86,7 @@ struct LegacySnapshotCaptureResult: Sendable {
86 86
 enum LegacySwiftDataBridge {
87 87
     private static var container: ModelContainer?
88 88
     private static var context: ModelContext?
89
+    private static var pendingSnapshots: [UUID: HealthSnapshot] = [:]
89 90
 
90 91
     static func configure(container: ModelContainer) {
91 92
         self.container = container
@@ -117,7 +118,10 @@ enum LegacySwiftDataBridge {
117 118
             ? ambiguousDisappearedMetrics(for: snapshot)
118 119
             : []
119 120
 
120
-        if snapshot.snapshotQuality == .complete, try !snapshotExists(id: snapshot.id) {
121
+        let shouldKeepPending = snapshot.snapshotQuality != .complete || !ambiguousDisappearedMetrics.isEmpty
122
+        if shouldKeepPending {
123
+            pendingSnapshots[snapshot.id] = snapshot
124
+        } else if try !snapshotExists(id: snapshot.id) {
121 125
             throw LegacySwiftDataBridgeError.snapshotNotSaved
122 126
         }
123 127
 
@@ -134,10 +138,11 @@ enum LegacySwiftDataBridge {
134 138
         id snapshotID: UUID,
135 139
         using healthKit: HealthKitService
136 140
     ) async throws -> LegacySnapshotOutcome {
137
-        guard let snapshot = try fetchSnapshot(id: snapshotID) else {
141
+        guard let snapshot = try resolveSnapshot(id: snapshotID) else {
138 142
             throw LegacySwiftDataBridgeError.snapshotNotSaved
139 143
         }
140 144
         let saved = try await healthKit.savePartialSnapshot(snapshot, in: modelContext())
145
+        pendingSnapshots.removeValue(forKey: snapshotID)
141 146
         return snapshotOutcome(from: saved)
142 147
     }
143 148
 
@@ -145,10 +150,11 @@ enum LegacySwiftDataBridge {
145 150
         id snapshotID: UUID,
146 151
         using healthKit: HealthKitService
147 152
     ) async throws -> LegacySnapshotOutcome {
148
-        guard let snapshot = try fetchSnapshot(id: snapshotID) else {
153
+        guard let snapshot = try resolveSnapshot(id: snapshotID) else {
149 154
             throw LegacySwiftDataBridgeError.snapshotNotSaved
150 155
         }
151 156
         let saved = try await healthKit.saveReviewedCompleteSnapshot(snapshot, in: modelContext())
157
+        pendingSnapshots.removeValue(forKey: snapshotID)
152 158
         return snapshotOutcome(from: saved)
153 159
     }
154 160
 
@@ -157,7 +163,7 @@ enum LegacySwiftDataBridge {
157 163
         typeIdentifiers: Set<String>,
158 164
         using healthKit: HealthKitService
159 165
     ) async throws -> LegacySnapshotOutcome {
160
-        guard let snapshot = try fetchSnapshot(id: snapshotID) else {
166
+        guard let snapshot = try resolveSnapshot(id: snapshotID) else {
161 167
             throw LegacySwiftDataBridgeError.snapshotNotSaved
162 168
         }
163 169
 
@@ -172,6 +178,7 @@ enum LegacySwiftDataBridge {
172 178
         snapshot.snapshotQuality = healthKit.deriveSnapshotQuality(from: snapshot.typeCounts ?? [])
173 179
 
174 180
         let saved = try await healthKit.savePartialSnapshot(snapshot, in: modelContext())
181
+        pendingSnapshots.removeValue(forKey: snapshotID)
175 182
         return snapshotOutcome(from: saved)
176 183
     }
177 184
 
@@ -192,6 +199,7 @@ enum LegacySwiftDataBridge {
192 199
     }
193 200
 
194 201
     static func deleteSnapshot(id: UUID) throws {
202
+        pendingSnapshots.removeValue(forKey: id)
195 203
         let context = try modelContext()
196 204
         var descriptor = FetchDescriptor<HealthSnapshot>(
197 205
             predicate: #Predicate<HealthSnapshot> { $0.id == id }
@@ -202,6 +210,10 @@ enum LegacySwiftDataBridge {
202 210
         }
203 211
     }
204 212
 
213
+    static func discardPendingSnapshot(id: UUID) {
214
+        pendingSnapshots.removeValue(forKey: id)
215
+    }
216
+
205 217
     private static func fetchSnapshot(id: UUID) throws -> HealthSnapshot? {
206 218
         let context = try modelContext()
207 219
         var descriptor = FetchDescriptor<HealthSnapshot>(
@@ -211,6 +223,13 @@ enum LegacySwiftDataBridge {
211 223
         return try context.fetch(descriptor).first
212 224
     }
213 225
 
226
+    private static func resolveSnapshot(id: UUID) throws -> HealthSnapshot? {
227
+        if let pending = pendingSnapshots[id] {
228
+            return pending
229
+        }
230
+        return try fetchSnapshot(id: id)
231
+    }
232
+
214 233
     private static func ambiguousDisappearedMetrics(for snapshot: HealthSnapshot) -> [AmbiguousDisappearedMetric] {
215 234
         guard let previous = previousSnapshot(for: snapshot) else { return [] }
216 235
         let previousByType = Dictionary(
+4 -0
HealthProbe/ViewModels/DashboardViewModel.swift
@@ -54,6 +54,10 @@ final class DashboardViewModel {
54 54
             return
55 55
         }
56 56
 
57
+        [pendingPartialSnapshotID, pendingAmbiguousSnapshotID, completedSnapshotID]
58
+            .compactMap { $0 }
59
+            .forEach(LegacySwiftDataBridge.discardPendingSnapshot(id:))
60
+
57 61
         isCreatingSnapshot = true
58 62
         snapshotError = nil
59 63
         snapshotProgress = .fetching