@@ -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( |
@@ -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 |