Просмотр исходного кода

Improve batch processing by date limitation WIP

Co-Authored-By: polscm32 <polscm32@users.noreply.github.com>
Deniz Cengiz 1 год назад
Родитель
Сommit
53c6684731

+ 11 - 12
Trio Watch App Extension/Views/TrioMainWatchView.swift

@@ -40,18 +40,7 @@ struct TrioMainWatchView: View {
     )
 
     var body: some View {
-        ZStack {
-            if !state.showSyncingAnimation {
-                mainTabView
-            } else {
-                trioBackgroundColor.ignoresSafeArea()
-
-                VStack {
-                    ProgressView("Syncing...")
-                    Spacer()
-                }
-            }
-        }
+        mainTabView
     }
 
     @ViewBuilder private var mainTabView: some View {
@@ -190,6 +179,16 @@ struct TrioMainWatchView: View {
                 }.transition(.opacity)
             }
         }
+        .overlay {
+            if !state.showCommsAnimation, state.showSyncingAnimation {
+                trioBackgroundColor.ignoresSafeArea()
+
+                VStack {
+                    ProgressView("Syncing...")
+                    Spacer()
+                }
+            }
+        }
     }
 
     private func updateRotation(for trend: String?) {

+ 103 - 40
Trio Watch App Extension/WatchState.swift

@@ -270,12 +270,16 @@ import WatchConnectivity
             acknowledgmentMessage = "\(message)"
         }
 
-        showCommsAnimation = false // Hide progress animation
+        DispatchQueue.main.async {
+            self.showCommsAnimation = false // Hide progress animation
+            self.showSyncingAnimation = false // Just ensure this is 100% set to false
+        }
 
         if isFinal {
             showAcknowledgmentBanner = true
             DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                 self.showAcknowledgmentBanner = false
+                self.showSyncingAnimation = false // Just ensure this is 100% set to false
             }
         }
     }
@@ -447,19 +451,95 @@ import WatchConnectivity
     /// Handles incoming messages from the paired iPhone
     /// Updates local glucose data, trend, and delta information
     func session(_: WCSession, didReceiveMessage message: [String: Any]) {
-        print("⌚️ Watch received data from message: \(message)")
-        processWatchMessage(message)
+        print("⌚️ Watch received data: \(message)")
+
+        // If the message has a nested "watchState" dictionary with date as TimeInterval
+        if let watchStateDict = message[WatchMessageKeys.watchState] as? [String: Any],
+           let timestamp = watchStateDict[WatchMessageKeys.date] as? TimeInterval
+        {
+            let date = Date(timeIntervalSince1970: timestamp)
+
+            // Check if it's not older than 15 min
+            if date >= Date().addingTimeInterval(-15 * 60) {
+                print("⌚️ Handling watchState from \(date)")
+                processWatchMessage(message)
+            } else {
+                print("⌚️ Received outdated watchState data (\(date))")
+                DispatchQueue.main.async {
+                    self.showSyncingAnimation = false
+                }
+            }
+        }
+
+        // Else if the message is an "ack" at the top level
+        // e.g. { "acknowledged": true, "message": "Started Temp Target...", "date": Date(...) }
+        else if
+            let acknowledged = message[WatchMessageKeys.acknowledged] as? Bool,
+            let ackMessage = message[WatchMessageKeys.message] as? String
+        {
+            print("⌚️ Handling ack with message: \(ackMessage), success: \(acknowledged)")
+            DispatchQueue.main.async {
+                // For ack messages, we do NOT show “Syncing...”
+                self.showSyncingAnimation = false
+            }
+            processWatchMessage(message)
+
+        } else {
+            print("⌚️ Faulty data. Skipping...")
+            DispatchQueue.main.async {
+                self.showSyncingAnimation = false
+            }
+        }
     }
 
     func session(_: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) {
-        print("⌚️ Watch received data from userInfo: \(userInfo)")
-        processWatchMessage(userInfo)
+        print("⌚️ Watch received data: \(userInfo)")
+
+        // If the message has a nested "watchState" dictionary with date as TimeInterval
+        if let watchStateDict = userInfo[WatchMessageKeys.watchState] as? [String: Any],
+           let timestamp = watchStateDict[WatchMessageKeys.date] as? TimeInterval
+        {
+            let date = Date(timeIntervalSince1970: timestamp)
+
+            // Check if it's not older than 15 min
+            if date >= Date().addingTimeInterval(-15 * 60) {
+                print("⌚️ Handling watchState from \(date)")
+                processWatchMessage(userInfo)
+            } else {
+                print("⌚️ Received outdated watchState data (\(date))")
+                DispatchQueue.main.async {
+                    self.showSyncingAnimation = false
+                }
+            }
+        }
+
+        // Else if the message is an "ack" at the top level
+        // e.g. { "acknowledged": true, "message": "Started Temp Target...", "date": Date(...) }
+        else if
+            let acknowledged = userInfo[WatchMessageKeys.acknowledged] as? Bool,
+            let ackMessage = userInfo[WatchMessageKeys.message] as? String
+        {
+            print("⌚️ Handling ack with message: \(ackMessage), success: \(acknowledged)")
+            DispatchQueue.main.async {
+                // For ack messages, we do NOT show “Syncing...”
+                self.showSyncingAnimation = false
+            }
+            processWatchMessage(userInfo)
+
+        } else {
+            print("⌚️ Faulty data. Skipping...")
+            DispatchQueue.main.async {
+                self.showSyncingAnimation = false
+            }
+        }
     }
 
     /// Accumulate new data, set isSyncing, and debounce final update
     private func scheduleUIUpdate(with newData: [String: Any]) {
         // 1) Mark as syncing
-        showSyncingAnimation = true
+        DispatchQueue.main.async {
+            self.showSyncingAnimation = true
+        }
 
         // 2) Merge data into our pendingData
         pendingData.merge(newData) { _, newVal in newVal }
@@ -472,16 +552,16 @@ import WatchConnectivity
             self.finalizePendingData()
         }
         finalizeWorkItem = workItem
-
-        // e.g. 0.3 seconds after last message
-        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: workItem)
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: workItem)
     }
 
     /// Applies all pending data to the watch state in one shot
     private func finalizePendingData() {
         guard !pendingData.isEmpty else {
             // If we have no actual data, just end syncing
-            showSyncingAnimation = false
+            DispatchQueue.main.async {
+                self.showSyncingAnimation = false
+            }
             return
         }
 
@@ -494,7 +574,7 @@ import WatchConnectivity
         pendingData.removeAll()
 
         // Done - but ensure this runs at least 2 sec, to avoid flickering
-        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+        DispatchQueue.main.async {
             self.showSyncingAnimation = false
         }
     }
@@ -505,8 +585,9 @@ import WatchConnectivity
             if let acknowledged = message[WatchMessageKeys.acknowledged] as? Bool,
                let ackMessage = message[WatchMessageKeys.message] as? String
             {
-                self.handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: false)
-                self.showSyncingAnimation = false
+                DispatchQueue.main.async {
+                    self.showSyncingAnimation = false
+                }
 
                 print("⌚️ Received acknowledgment: \(ackMessage), success: \(acknowledged)")
 
@@ -535,50 +616,32 @@ import WatchConnectivity
                 if !self.isBolusCanceled {
                     self.bolusProgress = progress
                 }
-                self.showSyncingAnimation = false
+                DispatchQueue.main.async {
+                    self.showSyncingAnimation = false
+                }
             }
 
             // 3) Bolus cancellation
             if message[WatchMessageKeys.bolusCanceled] as? Bool == true {
                 self.bolusProgress = 0
                 self.activeBolusAmount = 0
-                self.showSyncingAnimation = false
+                DispatchQueue.main.async {
+                    self.showSyncingAnimation = false
+                }
             }
 
             // 4) Recommended bolus
             if let recommendedBolus = message[WatchMessageKeys.recommendedBolus] as? NSNumber {
                 self.recommendedBolus = recommendedBolus.decimalValue
                 self.showBolusCalculationProgress = false
-                self.showSyncingAnimation = false
+                DispatchQueue.main.async {
+                    self.showSyncingAnimation = false
+                }
             }
 
             // 5) Raw watchState data
             if let watchStateData = message[WatchMessageKeys.watchState] as? [String: Any] {
                 self.scheduleUIUpdate(with: watchStateData)
-            } else {
-                // Or if your phone sends these UI keys individually:
-                let possibleUIKeys = [
-                    WatchMessageKeys.currentGlucose,
-                    WatchMessageKeys.trend,
-                    WatchMessageKeys.iob,
-                    WatchMessageKeys.cob,
-                    WatchMessageKeys.lastLoopTime,
-                    WatchMessageKeys.glucoseValues,
-                    WatchMessageKeys.overridePresets,
-                    WatchMessageKeys.tempTargetPresets,
-                    WatchMessageKeys.maxBolus,
-                    WatchMessageKeys.maxCarbs,
-                    WatchMessageKeys.maxFat,
-                    WatchMessageKeys.maxProtein,
-                    WatchMessageKeys.maxIOB,
-                    WatchMessageKeys.maxCOB,
-                    WatchMessageKeys.bolusIncrement
-                ]
-
-                let hasUIData = message.keys.contains { possibleUIKeys.contains($0) }
-                if hasUIData {
-                    self.scheduleUIUpdate(with: message)
-                }
             }
         }
     }

+ 1 - 1
Trio/Sources/Models/WatchMessageKeys.swift

@@ -1,5 +1,6 @@
 enum WatchMessageKeys {
     // Request/Response Keys
+    static let date = "date"
     static let requestWatchUpdate = "requestWatchUpdate"
     static let watchState = "watchState"
     static let acknowledged = "acknowledged"
@@ -8,7 +9,6 @@ enum WatchMessageKeys {
     // Treatment Keys
     static let bolus = "bolus"
     static let carbs = "carbs"
-    static let date = "date"
     static let cancelBolus = "cancelBolus"
     static let bolusCanceled = "bolusCanceled"
     static let bolusProgress = "bolusProgress"

+ 4 - 1
Trio/Sources/Models/WatchState.swift

@@ -2,6 +2,7 @@ import Foundation
 import SwiftUI
 
 struct WatchState: Hashable, Equatable, Sendable {
+    var date: Date
     var currentGlucose: String?
     var currentGlucoseColorString: String?
     var trend: String?
@@ -26,7 +27,8 @@ struct WatchState: Hashable, Equatable, Sendable {
     var bolusIncrement: Decimal = 0.05
 
     static func == (lhs: WatchState, rhs: WatchState) -> Bool {
-        lhs.currentGlucose == rhs.currentGlucose &&
+        lhs.date == rhs.date &&
+            lhs.currentGlucose == rhs.currentGlucose &&
             lhs.trend == rhs.trend &&
             lhs.delta == rhs.delta &&
             lhs.glucoseValues.count == rhs.glucoseValues.count &&
@@ -49,6 +51,7 @@ struct WatchState: Hashable, Equatable, Sendable {
     }
 
     func hash(into hasher: inout Hasher) {
+        hasher.combine(date)
         hasher.combine(currentGlucose)
         hasher.combine(trend)
         hasher.combine(delta)

+ 2 - 1
Trio/Sources/Services/WatchManager/AppleWatchManager.swift

@@ -159,7 +159,7 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
             .getNSManagedObject(with: tempTargetPresetIds, context: backgroundContext)
 
         return await backgroundContext.perform {
-            var watchState = WatchState()
+            var watchState = WatchState(date: Date())
 
             // Set lastLoopDate
             let lastLoopMinutes = Int((Date().timeIntervalSince(self.apsManager.lastLoopDate) - 30) / 60) + 1
@@ -328,6 +328,7 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
         }
 
         let message: [String: Any] = [
+            WatchMessageKeys.date: Date().timeIntervalSince1970,
             WatchMessageKeys.currentGlucose: state.currentGlucose ?? "--",
             WatchMessageKeys.currentGlucoseColorString: state.currentGlucoseColorString ?? "#ffffff",
             WatchMessageKeys.trend: state.trend ?? "",