Pārlūkot izejas kodu

Remove UI blocking sync animation for small SF symbol

Deniz Cengiz 1 gadu atpakaļ
vecāks
revīzija
b474a52466

+ 3 - 8
Trio Watch App Extension/Views/GlucoseTrendView.swift

@@ -3,6 +3,7 @@ import SwiftUI
 struct GlucoseTrendView: View {
     let state: WatchState
     let rotationDegrees: Double
+    let isWatchStateDated: Bool
 
     /// Determines the status color based on the time elapsed since the last loop
     /// - Parameter timeString: The time string representing minutes since last loop (format: "X min")
@@ -34,10 +35,6 @@ struct GlucoseTrendView: View {
         }
     }
 
-    var isWatchStateDated: Bool {
-        state.lastWatchStateUpdate ?? Date().timeIntervalSince1970 < Date().timeIntervalSince1970 - 15
-    }
-
     var circleSize: CGFloat {
         switch state.deviceType {
         case .watch40mm:
@@ -135,18 +132,16 @@ struct GlucoseTrendView: View {
                 .shadow(color: Color.black.opacity(0.5), radius: 5)
 
                 VStack(alignment: .center) {
-                    Text(state.currentGlucose)
+                    Text(isWatchStateDated ? "--" : state.currentGlucose)
                         .fontWeight(.semibold)
                         .font(currentGlucoseFontSize)
                         .foregroundStyle(isWatchStateDated ? Color.secondary : state.currentGlucoseColorString.toColor())
-                        .strikethrough(isWatchStateDated)
 
                     if let delta = state.delta {
-                        Text(delta)
+                        Text(isWatchStateDated ? "--" : delta)
                             .fontWeight(.semibold)
                             .font(.system(.caption))
                             .foregroundStyle(.secondary)
-                            .strikethrough(isWatchStateDated)
                     }
                 }
             }

+ 48 - 19
Trio Watch App Extension/Views/TrioMainWatchView.swift

@@ -1,5 +1,6 @@
 import Charts
 import SwiftUI
+import WatchKit
 
 struct TrioMainWatchView: View {
     @State private var state = WatchState()
@@ -19,6 +20,25 @@ struct TrioMainWatchView: View {
     // treatments
     @State private var selectedTreatment: TreatmentOption?
 
+    var isWatchStateDated: Bool {
+        // If `lastWatchStateUpdate` is nil, treat as "dated"
+        guard let lastUpdateTimestamp = state.lastWatchStateUpdate else {
+            return true
+        }
+        let now = Date().timeIntervalSince1970
+        let secondsSinceUpdate = now - lastUpdateTimestamp
+        // Return true if last update older than 15 min
+        return secondsSinceUpdate > 15 * 60
+    }
+
+    var isSessionUnreachable: Bool {
+        guard let session = state.session else {
+            return true // No session at all => unreachable
+        }
+        // Return true if not .activated OR not reachable
+        return session.activationState != .activated || !session.isReachable
+    }
+
     // Active adjustment indicator
     private func isAdjustmentActive<T>(for presets: [T], predicate: (T) -> Bool) -> Bool {
         let sortedPresets = presets.sorted { predicate($0) && !predicate($1) }
@@ -40,16 +60,34 @@ struct TrioMainWatchView: View {
     )
 
     var body: some View {
-        mainTabView
-    }
-
-    @ViewBuilder private var mainTabView: some View {
         NavigationStack(path: $navigationPath) {
             TabView(selection: $currentPage) {
                 // Page 1: Current glucose trend in "BG bobble"
-                GlucoseTrendView(state: state, rotationDegrees: rotationDegrees)
+                ZStack {
+                    GlucoseTrendView(
+                        state: state,
+                        rotationDegrees: rotationDegrees,
+                        isWatchStateDated: isWatchStateDated || isSessionUnreachable
+                    )
                     .tag(0)
 
+                    if state.showSyncingAnimation {
+                        Image(systemName: "iphone.radiowaves.left.and.right")
+                            .symbolRenderingMode(.palette)
+                            .foregroundStyle(Color.primary, Color.tabBar, Color.clear)
+                            .symbolEffect(
+                                .variableColor.iterative,
+                                options: .repeating,
+                                value: state.showSyncingAnimation
+                            )
+                            .position(
+                                x: 20,
+                                y: (WKInterfaceDevice.current().screenBounds.height / 4) -
+                                    7 // Font .body == 14, so half of default size for the SF Symbol image
+                            )
+                    }
+                }
+
                 // Page 2: Glucose chart
                 GlucoseChartView(glucoseValues: state.glucoseValues)
                     .tag(1)
@@ -68,15 +106,15 @@ struct TrioMainWatchView: View {
                         Image(systemName: "syringe.fill")
                             .foregroundStyle(Color.insulin)
 
-                        Text(state.iob ?? "--")
-                            .foregroundStyle(.white)
+                        Text(isWatchStateDated || isSessionUnreachable ? "--" : state.iob ?? "--")
+                            .foregroundStyle(isWatchStateDated ? Color.secondary : Color.white)
                     }.font(.caption2)
                 }
 
                 ToolbarItem(placement: .topBarTrailing) {
                     HStack {
-                        Text(state.cob ?? "--")
-                            .foregroundStyle(.white)
+                        Text(isWatchStateDated || isSessionUnreachable ? "--" : state.cob ?? "--")
+                            .foregroundStyle(isWatchStateDated || isSessionUnreachable ? Color.secondary : Color.white)
 
                         Image(systemName: "fork.knife")
                             .foregroundStyle(Color.orange)
@@ -170,6 +208,7 @@ struct TrioMainWatchView: View {
                 }
             }
         }
+        .ignoresSafeArea()
         .blur(radius: state.showBolusProgressOverlay ? 3 : 0)
         .overlay {
             if state.showBolusProgressOverlay {
@@ -179,16 +218,6 @@ struct TrioMainWatchView: View {
                 }.transition(.opacity)
             }
         }
-        .overlay {
-            if !state.showCommsAnimation, state.showSyncingAnimation {
-                trioBackgroundColor.ignoresSafeArea()
-
-                VStack {
-                    ProgressView("Syncing...")
-                    Spacer()
-                }
-            }
-        }
     }
 
     private func updateRotation(for trend: String?) {

+ 23 - 9
Trio Watch App Extension/WatchState.swift

@@ -140,18 +140,32 @@ import WatchConnectivity
             }
 
             // the order here is probably not perfect and needs to be re-arranged
-            if activationState == .activated,
-               self.lastWatchStateUpdate == nil || self.lastWatchStateUpdate! < Date().timeIntervalSince1970 - 15
-            {
-                self.showSyncingAnimation = true
-                self.requestWatchStateUpdate()
-            }
+            if activationState == .activated {
+                guard let lastUpdateTimestamp = self.lastWatchStateUpdate else {
+                    // nil => force update
+                    self.showSyncingAnimation = true
+                    self.requestWatchStateUpdate()
+                    return
+                }
+
+                let now = Date().timeIntervalSince1970
+                let secondsSinceUpdate = now - lastUpdateTimestamp
 
-            print("⌚️ Watch session activated with state: \(activationState.rawValue)")
+                // If more than 15 minutes in seconds
+                if secondsSinceUpdate > 15 * 60 {
+                    self.showSyncingAnimation = true
+                    self.requestWatchStateUpdate()
+                    return
+                }
+
+                // Otherwise do the rest...
 
-            self.isReachable = session.isReachable
+                print("⌚️ Watch session activated with state: \(activationState.rawValue)")
 
-            print("⌚️ Watch isReachable after activation: \(session.isReachable)")
+                self.isReachable = session.isReachable
+
+                print("⌚️ Watch isReachable after activation: \(session.isReachable)")
+            }
         }
     }