Forráskód Böngészése

fix carbinputview animation + calculatingBolus animation being stuck, fix bolus progress bar from not showing up, fix canceling behaviour of boluses, reset carbs when navigating to bolusInputView

polscm32 aka Marvout 1 éve
szülő
commit
b49ca9cfda

+ 2 - 0
Trio Watch App Extension/Views/TrioMainWatchView.swift

@@ -206,6 +206,8 @@ struct TrioMainWatchView: View {
         case .meal:
             navigationPath.append(NavigationDestinations.carbsInput)
         case .bolus:
+            // Reset carbs amount when directly going to bolus input
+            state.carbsAmount = 0
             navigationPath.append(NavigationDestinations.bolusInput)
         case .mealBolusCombo:
             continueToBolus = true // Explicitely set subsequent view navigation

+ 95 - 60
Trio Watch App Extension/WatchState.swift

@@ -233,8 +233,8 @@ import WatchConnectivity
         guard let session = session, session.isReachable else { return }
 
         let message: [String: Any] = [
-            "requestBolusRecommendation": true,
-            "carbs": carbsAmount
+            WatchMessageKeys.requestBolusRecommendation: true,
+            WatchMessageKeys.carbs: carbsAmount
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
@@ -251,16 +251,16 @@ import WatchConnectivity
     func handleAcknowledgment(success: Bool, message: String, isFinal: Bool = true) {
         if success {
             print("⌚️ Acknowledgment received: \(message)")
-            showCommsAnimation = false // Hide progress animation
             acknowledgementStatus = .success
             acknowledgmentMessage = "\(message)"
         } else {
             print("⌚️ Acknowledgment failed: \(message)")
-            showCommsAnimation = false // Hide progress animation
             acknowledgementStatus = .failure
             acknowledgmentMessage = "\(message)"
         }
 
+        showCommsAnimation = false // Hide progress animation
+
         if isFinal {
             showAcknowledgmentBanner = true
             DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
@@ -271,6 +271,7 @@ import WatchConnectivity
 
     func requestWatchStateUpdate() {
         guard let session = session, session.activationState == .activated else {
+            print("⌚️ Session not activated, activating...")
             session?.activate()
             return
         }
@@ -278,65 +279,46 @@ import WatchConnectivity
         if session.isReachable {
             print("⌚️ Request an update for watch state from Trio iPhone app...")
 
-            session.sendMessage(["requestForWatchUpdate": "watchState"], replyHandler: nil) { error in
+            let message = [WatchMessageKeys.requestWatchUpdate: WatchMessageKeys.watchState]
+
+            session.sendMessage(message, replyHandler: nil) { error in
                 print("⌚️ Update request for fresh watch state data: \(error.localizedDescription)")
             }
+        } else {
+            print("⌚️ Phone not reachable for watch state update")
         }
     }
 
     private func processRawDataForWatchState(_ message: [String: Any]) {
-        if let acknowledged = message["acknowledged"] as? Bool,
-           let ackMessage = message["message"] as? String
-        {
-            switch ackMessage {
-            case "Saving carbs...":
-                isMealBolusCombo = true
-                mealBolusStep = .savingCarbs
-                showCommsAnimation = true
-                handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: false)
-            case "Enacting bolus...":
-                isMealBolusCombo = true
-                mealBolusStep = .enactingBolus
-                showCommsAnimation = true
-                handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: false)
-            case "Carbs and bolus logged successfully":
-                isMealBolusCombo = false
-                handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: true)
-            default:
-                isMealBolusCombo = false
-                handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: true)
-            }
-        }
-
-        if let currentGlucose = message["currentGlucose"] as? String {
+        if let currentGlucose = message[WatchMessageKeys.currentGlucose] as? String {
             self.currentGlucose = currentGlucose
         }
 
-        if let currentGlucoseColorString = message["currentGlucoseColorString"] as? String {
+        if let currentGlucoseColorString = message[WatchMessageKeys.currentGlucoseColorString] as? String {
             self.currentGlucoseColorString = currentGlucoseColorString
         }
 
-        if let trend = message["trend"] as? String {
+        if let trend = message[WatchMessageKeys.trend] as? String {
             self.trend = trend
         }
 
-        if let delta = message["delta"] as? String {
+        if let delta = message[WatchMessageKeys.delta] as? String {
             self.delta = delta
         }
 
-        if let iob = message["iob"] as? String {
+        if let iob = message[WatchMessageKeys.iob] as? String {
             self.iob = iob
         }
 
-        if let cob = message["cob"] as? String {
+        if let cob = message[WatchMessageKeys.cob] as? String {
             self.cob = cob
         }
 
-        if let lastLoopTime = message["lastLoopTime"] as? String {
+        if let lastLoopTime = message[WatchMessageKeys.lastLoopTime] as? String {
             self.lastLoopTime = lastLoopTime
         }
 
-        if let glucoseData = message["glucoseValues"] as? [[String: Any]] {
+        if let glucoseData = message[WatchMessageKeys.glucoseValues] as? [[String: Any]] {
             glucoseValues = glucoseData.compactMap { data in
                 guard let glucose = data["glucose"] as? Double,
                       let timestamp = data["date"] as? TimeInterval,
@@ -352,7 +334,7 @@ import WatchConnectivity
             .sorted { $0.date < $1.date }
         }
 
-        if let overrideData = message["overridePresets"] as? [[String: Any]] {
+        if let overrideData = message[WatchMessageKeys.overridePresets] as? [[String: Any]] {
             overridePresets = overrideData.compactMap { data in
                 guard let name = data["name"] as? String,
                       let isEnabled = data["isEnabled"] as? Bool
@@ -361,7 +343,7 @@ import WatchConnectivity
             }
         }
 
-        if let tempTargetData = message["tempTargetPresets"] as? [[String: Any]] {
+        if let tempTargetData = message[WatchMessageKeys.tempTargetPresets] as? [[String: Any]] {
             tempTargetPresets = tempTargetData.compactMap { data in
                 guard let name = data["name"] as? String,
                       let isEnabled = data["isEnabled"] as? Bool
@@ -370,20 +352,19 @@ import WatchConnectivity
             }
         }
 
-        if let bolusProgress = message["bolusProgress"] as? Double {
+        if let bolusProgress = message[WatchMessageKeys.bolusProgress] as? Double {
             if !isBolusCanceled {
                 self.bolusProgress = bolusProgress
             }
         }
 
-        if let bolusWasCanceled = message["bolusCanceled"] as? Bool, bolusWasCanceled {
+        if let bolusWasCanceled = message[WatchMessageKeys.bolusCanceled] as? Bool, bolusWasCanceled {
             bolusProgress = 0
             activeBolusAmount = 0
             return
         }
 
-        // Debug print für die Safety Limits
-        if let maxBolusValue = message["maxBolus"] {
+        if let maxBolusValue = message[WatchMessageKeys.maxBolus] {
             print("⌚️ Received maxBolus: \(maxBolusValue) of type \(type(of: maxBolusValue))")
             if let decimalValue = (maxBolusValue as? NSNumber)?.decimalValue {
                 maxBolus = decimalValue
@@ -391,46 +372,41 @@ import WatchConnectivity
             }
         }
 
-        if let maxCarbsValue = message["maxCarbs"] {
+        if let maxCarbsValue = message[WatchMessageKeys.maxCarbs] {
             if let decimalValue = (maxCarbsValue as? NSNumber)?.decimalValue {
                 maxCarbs = decimalValue
             }
         }
 
-        if let maxFatValue = message["maxFat"] {
+        if let maxFatValue = message[WatchMessageKeys.maxFat] {
             if let decimalValue = (maxFatValue as? NSNumber)?.decimalValue {
                 maxFat = decimalValue
             }
         }
 
-        if let maxProteinValue = message["maxProtein"] {
+        if let maxProteinValue = message[WatchMessageKeys.maxProtein] {
             if let decimalValue = (maxProteinValue as? NSNumber)?.decimalValue {
                 maxProtein = decimalValue
             }
         }
 
-        if let maxIOBValue = message["maxIOB"] {
+        if let maxIOBValue = message[WatchMessageKeys.maxIOB] {
             if let decimalValue = (maxIOBValue as? NSNumber)?.decimalValue {
                 maxIOB = decimalValue
             }
         }
 
-        if let maxCOBValue = message["maxCOB"] {
+        if let maxCOBValue = message[WatchMessageKeys.maxCOB] {
             if let decimalValue = (maxCOBValue as? NSNumber)?.decimalValue {
                 maxCOB = decimalValue
             }
         }
 
-        if let bolusIncrement = message["bolusIncrement"] {
+        if let bolusIncrement = message[WatchMessageKeys.bolusIncrement] {
             if let decimalValue = (bolusIncrement as? NSNumber)?.decimalValue {
                 self.bolusIncrement = decimalValue
             }
         }
-
-        if let recommendedBolus = message["recommendedBolus"] as? NSNumber {
-            self.recommendedBolus = recommendedBolus.decimalValue
-            showBolusCalculationProgress = false
-        }
     }
 
     // MARK: - WCSessionDelegate
@@ -462,20 +438,79 @@ import WatchConnectivity
     func session(_: WCSession, didReceiveMessage message: [String: Any]) {
         print("⌚️ Watch received data from message: \(message)")
 
-        let dataFromMessage = message["watchState"] as! [String: Any]
+        // The WatchState message does not contain the ackmessages
+        // We need to handle them separately and outside of an if condition that only treats watchState data like the if condition below
+        if let acknowledged = message[WatchMessageKeys.acknowledged] as? Bool,
+           let ackMessage = message[WatchMessageKeys.message] as? String
+        {
+            DispatchQueue.main.async {
+                switch ackMessage {
+                case "Saving carbs...":
+                    self.isMealBolusCombo = true
+                    self.mealBolusStep = .savingCarbs
+                    self.showCommsAnimation = true
+                    self.handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: false)
+                case "Enacting bolus...":
+                    self.isMealBolusCombo = true
+                    self.mealBolusStep = .enactingBolus
+                    self.showCommsAnimation = true
+                    self.handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: false)
+                case "Carbs and bolus logged successfully":
+                    self.isMealBolusCombo = false
+                    self.handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: true)
+                default:
+                    self.isMealBolusCombo = false
+                    self.handleAcknowledgment(success: acknowledged, message: ackMessage, isFinal: true)
+                }
+            }
+            return
+        }
 
-        DispatchQueue.main.async {
-            self.processRawDataForWatchState(dataFromMessage)
+        // Recommended bolus is also not part of the WatchState message, hence the extra condition here
+        if let recommendedBolus = message[WatchMessageKeys.recommendedBolus] as? NSNumber {
+            print("⌚️ Received recommended bolus: \(recommendedBolus)")
+            self.recommendedBolus = recommendedBolus.decimalValue
+            showBolusCalculationProgress = false
+            return
+        }
+
+        // Handle bolus progress updates
+        if let progress = message[WatchMessageKeys.bolusProgress] as? Double {
+            DispatchQueue.main.async {
+                if !self.isBolusCanceled {
+                    self.bolusProgress = progress
+                }
+            }
+            return
+        }
+
+        // Handle bolus cancellation
+        if message[WatchMessageKeys.bolusCanceled] as? Bool == true {
+            DispatchQueue.main.async {
+                self.bolusProgress = 0
+                self.activeBolusAmount = 0
+            }
+            return
+        }
+
+        if let dataFromMessage = message[WatchMessageKeys.watchState] as? [String: Any] {
+            DispatchQueue.main.async {
+                self.processRawDataForWatchState(dataFromMessage)
+            }
+        } else {
+            print("⌚️ Received message without valid state or ack data: \(message)")
         }
     }
 
     func session(_: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) {
         print("⌚️ Watch received data from userInfo: \(userInfo)")
 
-        let dataFromUserInfo = userInfo["watchState"] as! [String: Any]
-
-        DispatchQueue.main.async {
-            self.processRawDataForWatchState(dataFromUserInfo)
+        if let dataFromUserInfo = userInfo["watchState"] as? [String: Any] {
+            DispatchQueue.main.async {
+                self.processRawDataForWatchState(dataFromUserInfo)
+            }
+        } else {
+            print("⌚️ Warning: Received userInfo without valid watchState data")
         }
     }
 

+ 6 - 0
Trio.xcodeproj/project.pbxproj

@@ -293,6 +293,8 @@
 		BD2FF1A02AE29D43005D1C5D /* CheckboxToggleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD2FF19F2AE29D43005D1C5D /* CheckboxToggleStyle.swift */; };
 		BD3CC0722B0B89D50013189E /* MainChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD3CC0712B0B89D50013189E /* MainChartView.swift */; };
 		BD4064D12C4ED26900582F43 /* CoreDataObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4064D02C4ED26900582F43 /* CoreDataObserver.swift */; };
+		BD432CA12D2F4E3600D1EB79 /* WatchMessageKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD432CA02D2F4E3300D1EB79 /* WatchMessageKeys.swift */; };
+		BD432CA22D2F4E4000D1EB79 /* WatchMessageKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD432CA02D2F4E3300D1EB79 /* WatchMessageKeys.swift */; };
 		BD4ED4FD2CF9D5E8000EDC9C /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD4ED4FC2CF9D5E8000EDC9C /* AppState.swift */; };
 		BD54A9592D27FB7800F9C1EE /* OverridePresetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD54A9582D27FB6A00F9C1EE /* OverridePresetsView.swift */; };
 		BD54A95B2D28087C00F9C1EE /* OverridePresetWatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD54A95A2D28087700F9C1EE /* OverridePresetWatch.swift */; };
@@ -1009,6 +1011,7 @@
 		BD2FF19F2AE29D43005D1C5D /* CheckboxToggleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxToggleStyle.swift; sourceTree = "<group>"; };
 		BD3CC0712B0B89D50013189E /* MainChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainChartView.swift; sourceTree = "<group>"; };
 		BD4064D02C4ED26900582F43 /* CoreDataObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataObserver.swift; sourceTree = "<group>"; };
+		BD432CA02D2F4E3300D1EB79 /* WatchMessageKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchMessageKeys.swift; sourceTree = "<group>"; };
 		BD4ED4FC2CF9D5E8000EDC9C /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; };
 		BD54A9582D27FB6A00F9C1EE /* OverridePresetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridePresetsView.swift; sourceTree = "<group>"; };
 		BD54A95A2D28087700F9C1EE /* OverridePresetWatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridePresetWatch.swift; sourceTree = "<group>"; };
@@ -2033,6 +2036,7 @@
 		388E5A5925B6F0250019842D /* Models */ = {
 			isa = PBXGroup;
 			children = (
+				BD432CA02D2F4E3300D1EB79 /* WatchMessageKeys.swift */,
 				BD54A9722D281A9C00F9C1EE /* TempTargetPresetWatch.swift */,
 				BD54A95A2D28087700F9C1EE /* OverridePresetWatch.swift */,
 				BDA25EFC2D261BF200035F34 /* WatchState.swift */,
@@ -3659,6 +3663,7 @@
 				E592A3702CEEC01E009A472C /* ContactTrickEntry.swift in Sources */,
 				DD6D67E42C9C253500660C9B /* ColorSchemeOption.swift in Sources */,
 				582DF9752C8CDB92001F516D /* GlucoseChartView.swift in Sources */,
+				BD432CA12D2F4E3600D1EB79 /* WatchMessageKeys.swift in Sources */,
 				58A3D53A2C96D4DE003F90FC /* AddTempTargetForm.swift in Sources */,
 				DD1745302C55AE5300211FAC /* TargetBehaviorProvider.swift in Sources */,
 				58D08B382C8DFB6000AA37D3 /* BasalChart.swift in Sources */,
@@ -4045,6 +4050,7 @@
 				DD6F63CC2D27F615007D94CF /* TreatmentMenuView.swift in Sources */,
 				DD3A3CE72D29C93F00AE478E /* Helper+Extensions.swift in Sources */,
 				DD246F062D2836AA0027DDE0 /* GlucoseTrendView.swift in Sources */,
+				BD432CA22D2F4E4000D1EB79 /* WatchMessageKeys.swift in Sources */,
 				DD8262CB2D289297009F6F62 /* BolusConfirmationView.swift in Sources */,
 				BD54A9712D281A8100F9C1EE /* TempTargetPresetsView.swift in Sources */,
 				DD3A3CE92D29C97800AE478E /* Helper+ButtonStyles.swift in Sources */,

+ 48 - 0
Trio/Sources/Models/WatchMessageKeys.swift

@@ -0,0 +1,48 @@
+enum WatchMessageKeys {
+    // Request/Response Keys
+    static let requestWatchUpdate = "requestWatchUpdate"
+    static let watchState = "watchState"
+    static let acknowledged = "acknowledged"
+    static let message = "message"
+
+    // 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"
+
+    // Recommendation Keys
+    static let requestBolusRecommendation = "requestBolusRecommendation"
+    static let recommendedBolus = "recommendedBolus"
+
+    // Override Keys
+    static let cancelOverride = "cancelOverride"
+    static let activateOverride = "activateOverride"
+
+    // Temp Target Keys
+    static let cancelTempTarget = "cancelTempTarget"
+    static let activateTempTarget = "activateTempTarget"
+
+    // Watch State Data Keys
+    static let currentGlucose = "currentGlucose"
+    static let currentGlucoseColorString = "currentGlucoseColorString"
+    static let trend = "trend"
+    static let delta = "delta"
+    static let iob = "iob"
+    static let cob = "cob"
+    static let lastLoopTime = "lastLoopTime"
+    static let glucoseValues = "glucoseValues"
+    static let overridePresets = "overridePresets"
+    static let tempTargetPresets = "tempTargetPresets"
+
+    // Limits and Settings Keys
+    static let maxBolus = "maxBolus"
+    static let maxCarbs = "maxCarbs"
+    static let maxFat = "maxFat"
+    static let maxProtein = "maxProtein"
+    static let maxIOB = "maxIOB"
+    static let maxCOB = "maxCOB"
+    static let bolusIncrement = "bolusIncrement"
+}

+ 50 - 68
Trio/Sources/Services/WatchManager/AppleWatchManager.swift

@@ -327,68 +327,50 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
             return
         }
 
-//        var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
-//        backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Watch Data Upload") {
-//            guard backgroundTaskID != .invalid else { return }
-//            Task {
-//                UIApplication.shared.endBackgroundTask(backgroundTaskID)
-//            }
-//            backgroundTaskID = .invalid
-//        }
-//
-//        defer {
-//            if backgroundTaskID != .invalid {
-//                Task {
-//                    UIApplication.shared.endBackgroundTask(backgroundTaskID)
-//                }
-//                backgroundTaskID = .invalid
-//            }
-//        }
-
         let message: [String: Any] = [
-            "currentGlucose": state.currentGlucose ?? "--",
-            "currentGlucoseColorString": state.currentGlucoseColorString ?? "#ffffff",
-            "trend": state.trend ?? "",
-            "delta": state.delta ?? "",
-            "iob": state.iob ?? "",
-            "cob": state.cob ?? "",
-            "lastLoopTime": state.lastLoopTime ?? "",
-            "glucoseValues": state.glucoseValues.map { value in
+            WatchMessageKeys.currentGlucose: state.currentGlucose ?? "--",
+            WatchMessageKeys.currentGlucoseColorString: state.currentGlucoseColorString ?? "#ffffff",
+            WatchMessageKeys.trend: state.trend ?? "",
+            WatchMessageKeys.delta: state.delta ?? "",
+            WatchMessageKeys.iob: state.iob ?? "",
+            WatchMessageKeys.cob: state.cob ?? "",
+            WatchMessageKeys.lastLoopTime: state.lastLoopTime ?? "",
+            WatchMessageKeys.glucoseValues: state.glucoseValues.map { value in
                 [
                     "glucose": value.glucose,
                     "date": value.date.timeIntervalSince1970,
                     "color": value.color
                 ]
             },
-            "overridePresets": state.overridePresets.map { preset in
+            WatchMessageKeys.overridePresets: state.overridePresets.map { preset in
                 [
                     "name": preset.name,
                     "isEnabled": preset.isEnabled
                 ]
             },
-            "tempTargetPresets": state.tempTargetPresets.map { preset in
+            WatchMessageKeys.tempTargetPresets: state.tempTargetPresets.map { preset in
                 [
                     "name": preset.name,
                     "isEnabled": preset.isEnabled
                 ]
             },
-            "maxBolus": state.maxBolus,
-            "maxCarbs": state.maxCarbs,
-            "maxFat": state.maxFat,
-            "maxProtein": state.maxProtein,
-            "maxIOB": state.maxIOB,
-            "maxCOB": state.maxCOB,
-            "bolusIncrement": state.bolusIncrement
+            WatchMessageKeys.maxBolus: state.maxBolus,
+            WatchMessageKeys.maxCarbs: state.maxCarbs,
+            WatchMessageKeys.maxFat: state.maxFat,
+            WatchMessageKeys.maxProtein: state.maxProtein,
+            WatchMessageKeys.maxIOB: state.maxIOB,
+            WatchMessageKeys.maxCOB: state.maxCOB,
+            WatchMessageKeys.bolusIncrement: state.bolusIncrement
         ]
 
         // if session is reachable, it means watch App is in the foreground -> send watchState as message
         // if session is not reachable, it means it's in background -> send watchState as userInfo
         if session.isReachable {
-            session.sendMessage(["watchState": message], replyHandler: nil, errorHandler: { (error) -> Void in
-                debug(.watchManager, "❌ Error sending watch state as message: \(error.localizedDescription)")
-            })
+            session.sendMessage([WatchMessageKeys.watchState: message], replyHandler: nil) { error in
+                debug(.watchManager, "❌ Error sending watch state: \(error.localizedDescription)")
+            }
         } else {
-            session.transferUserInfo(["watchState": message])
+            session.transferUserInfo([WatchMessageKeys.watchState: message])
         }
     }
 
@@ -399,8 +381,8 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
         }
 
         let ackMessage: [String: Any] = [
-            "acknowledged": success,
-            "message": message
+            WatchMessageKeys.acknowledged: success,
+            WatchMessageKeys.message: message
         ]
 
         session.sendMessage(ackMessage, replyHandler: nil) { error in
@@ -428,36 +410,36 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
 
     func session(_: WCSession, didReceiveMessage message: [String: Any]) {
         DispatchQueue.main.async { [weak self] in
-
-            // watch requested for FRESH watchState data!
-            if let requestWatchUpdate = message["requestWatchUpdate"] as? String,
-               requestWatchUpdate == "watchState"
+            // Prüfe zuerst auf Watch State Update Request
+            if let requestWatchUpdate = message[WatchMessageKeys.requestWatchUpdate] as? String,
+               requestWatchUpdate == WatchMessageKeys.watchState
             {
                 debug(.watchManager, "📱 Watch requested watch state data update.")
-                if let self = self {
-                    Task {
-                        let state = await self.setupWatchState()
-                        await self.sendDataToWatch(state)
-                    }
+                guard let self = self else { return }
+
+                Task {
+                    let state = await self.setupWatchState()
+                    await self.sendDataToWatch(state)
                 }
+                return
             }
 
-            if let bolusAmount = message["bolus"] as? Double,
-               message["carbs"] == nil,
-               message["date"] == nil
+            if let bolusAmount = message[WatchMessageKeys.bolus] as? Double,
+               message[WatchMessageKeys.carbs] == nil,
+               message[WatchMessageKeys.date] == nil
             {
                 debug(.watchManager, "📱 Received bolus request from watch: \(bolusAmount)U")
                 self?.handleBolusRequest(Decimal(bolusAmount))
-            } else if let carbsAmount = message["carbs"] as? Int,
-                      let timestamp = message["date"] as? TimeInterval,
-                      message["bolus"] == nil
+            } else if let carbsAmount = message[WatchMessageKeys.carbs] as? Int,
+                      let timestamp = message[WatchMessageKeys.date] as? TimeInterval,
+                      message[WatchMessageKeys.bolus] == nil
             {
                 let date = Date(timeIntervalSince1970: timestamp)
                 debug(.watchManager, "📱 Received carbs request from watch: \(carbsAmount)g at \(date)")
                 self?.handleCarbsRequest(carbsAmount, date)
-            } else if let bolusAmount = message["bolus"] as? Double,
-                      let carbsAmount = message["carbs"] as? Int,
-                      let timestamp = message["date"] as? TimeInterval
+            } else if let bolusAmount = message[WatchMessageKeys.bolus] as? Double,
+                      let carbsAmount = message[WatchMessageKeys.carbs] as? Int,
+                      let timestamp = message[WatchMessageKeys.date] as? TimeInterval
             {
                 let date = Date(timeIntervalSince1970: timestamp)
                 debug(
@@ -469,28 +451,28 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
                 debug(.watchManager, "📱 Invalid or incomplete data received from watch. Received:  \(message)")
             }
 
-            if message["cancelOverride"] as? Bool == true {
+            if message[WatchMessageKeys.cancelOverride] as? Bool == true {
                 debug(.watchManager, "📱 Received cancel override request from watch")
                 self?.handleCancelOverride()
             }
 
-            if let presetName = message["activateOverride"] as? String {
+            if let presetName = message[WatchMessageKeys.activateOverride] as? String {
                 debug(.watchManager, "📱 Received activate override request from watch for preset: \(presetName)")
                 self?.handleActivateOverride(presetName)
             }
 
-            if let presetName = message["activateTempTarget"] as? String {
+            if let presetName = message[WatchMessageKeys.activateTempTarget] as? String {
                 debug(.watchManager, "📱 Received activate temp target request from watch for preset: \(presetName)")
                 self?.handleActivateTempTarget(presetName)
             }
 
-            if message["cancelTempTarget"] as? Bool == true {
+            if message[WatchMessageKeys.cancelTempTarget] as? Bool == true {
                 debug(.watchManager, "📱 Received cancel temp target request from watch")
                 self?.handleCancelTempTarget()
             }
 
             // Handle bolus cancellation
-            if message["cancelBolus"] as? Bool == true {
+            if message[WatchMessageKeys.cancelBolus] as? Bool == true {
                 Task {
                     await self?.apsManager.cancelBolus { [self] success, message in
                         // Acknowledge success or error of bolus
@@ -503,8 +485,8 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
                 }
             }
 
-            if message["requestBolusRecommendation"] as? Bool == true {
-                let carbs = message["carbs"] as? Int ?? 0
+            if message[WatchMessageKeys.requestBolusRecommendation] as? Bool == true {
+                let carbs = message[WatchMessageKeys.carbs] as? Int ?? 0
 
                 Task { [weak self] in
                     guard let self = self else { return }
@@ -518,7 +500,7 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
 
                     // Send recommendation back to watch
                     let recommendationMessage: [String: Any] = [
-                        "recommendedBolus": NSDecimalNumber(decimal: result.insulinCalculated)
+                        WatchMessageKeys.recommendedBolus: NSDecimalNumber(decimal: result.insulinCalculated)
                     ]
 
                     if let session = self.session, session.isReachable {
@@ -875,7 +857,7 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
     private func sendBolusProgressToWatch(progress: Decimal?) {
         guard let session = session, session.isReachable, let progress = progress else { return }
 
-        let message: [String: Any] = ["bolusProgress": Double(truncating: progress as NSNumber)]
+        let message: [String: Any] = [WatchMessageKeys.bolusProgress: Double(truncating: progress as NSNumber)]
 
         session.sendMessage(message, replyHandler: nil) { error in
             debug(.watchManager, "❌ Error sending bolus progress: \(error.localizedDescription)")