Explorar el Código

Refactoring + set target in main chart via setting

Deniz Cengiz hace 1 año
padre
commit
573e235d17

+ 6 - 6
FreeAPS.xcodeproj/project.pbxproj

@@ -17,8 +17,8 @@
 		110AEDEC2C51A0AE00615CC9 /* ShortcutsConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110AEDE72C51A0AE00615CC9 /* ShortcutsConfigDataFlow.swift */; };
 		110AEDED2C51A0AE00615CC9 /* ShortcutsConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110AEDE82C51A0AE00615CC9 /* ShortcutsConfigProvider.swift */; };
 		110AEDEE2C51A0AE00615CC9 /* ShortcutsConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110AEDE92C51A0AE00615CC9 /* ShortcutsConfigStateModel.swift */; };
-		11E79B132C5F2585007893C2 /* BGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E79B122C5F2585007893C2 /* BGColor.swift */; };
-		11E79B142C5F2585007893C2 /* BGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E79B122C5F2585007893C2 /* BGColor.swift */; };
+		11E79B132C5F2585007893C2 /* DynamicGlucoseColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E79B122C5F2585007893C2 /* DynamicGlucoseColor.swift */; };
+		11E79B142C5F2585007893C2 /* DynamicGlucoseColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E79B122C5F2585007893C2 /* DynamicGlucoseColor.swift */; };
 		17A9D0899046B45E87834820 /* CREditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C8D5F457B5AFF763F8CF3DF /* CREditorProvider.swift */; };
 		19012CDC291D2CB900FB8210 /* LoopStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19012CDB291D2CB900FB8210 /* LoopStats.swift */; };
 		190EBCC429FF136900BA767D /* StatConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EBCC329FF136900BA767D /* StatConfigDataFlow.swift */; };
@@ -562,7 +562,7 @@
 		110AEDE72C51A0AE00615CC9 /* ShortcutsConfigDataFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConfigDataFlow.swift; sourceTree = "<group>"; };
 		110AEDE82C51A0AE00615CC9 /* ShortcutsConfigProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConfigProvider.swift; sourceTree = "<group>"; };
 		110AEDE92C51A0AE00615CC9 /* ShortcutsConfigStateModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConfigStateModel.swift; sourceTree = "<group>"; };
-		11E79B122C5F2585007893C2 /* BGColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGColor.swift; sourceTree = "<group>"; };
+		11E79B122C5F2585007893C2 /* DynamicGlucoseColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicGlucoseColor.swift; sourceTree = "<group>"; };
 		12204445D7632AF09264A979 /* PreferencesEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PreferencesEditorDataFlow.swift; sourceTree = "<group>"; };
 		19012CDB291D2CB900FB8210 /* LoopStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopStats.swift; sourceTree = "<group>"; };
 		190EBCC329FF136900BA767D /* StatConfigDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatConfigDataFlow.swift; sourceTree = "<group>"; };
@@ -1847,7 +1847,7 @@
 				BD1661302B82ADAB00256551 /* CustomProgressView.swift */,
 				581516A32BCED84A00BF67D7 /* DebuggingIdentifiers.swift */,
 				DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */,
-				11E79B122C5F2585007893C2 /* BGColor.swift */,
+				11E79B122C5F2585007893C2 /* DynamicGlucoseColor.swift */,
 				C20BC6CD2C66FBFD002BC1C6 /* Rounding.swift */,
 			);
 			path = Helpers;
@@ -3074,7 +3074,7 @@
 				3811DEA925C9D88300A708ED /* AppearanceManager.swift in Sources */,
 				CE7950242997D81700FA576E /* CGMSettingsView.swift in Sources */,
 				58237D9E2BCF0A6B00A47A79 /* PopupView.swift in Sources */,
-				11E79B132C5F2585007893C2 /* BGColor.swift in Sources */,
+				11E79B132C5F2585007893C2 /* DynamicGlucoseColor.swift in Sources */,
 				38D0B3D925EC07C400CB6E88 /* CarbsEntry.swift in Sources */,
 				38A9260525F012D8009E3739 /* CarbRatios.swift in Sources */,
 				38FCF3D625E8FDF40078B0D1 /* MD5.swift in Sources */,
@@ -3330,7 +3330,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				11E79B142C5F2585007893C2 /* BGColor.swift in Sources */,
+				11E79B142C5F2585007893C2 /* DynamicGlucoseColor.swift in Sources */,
 				6BCF84DE2B16843A003AD46E /* LiveActitiyAttributes.swift in Sources */,
 				6BCF84DE2B16843A003AD46E /* LiveActitiyAttributes.swift in Sources */,
 				6B1A8D1E2B14D91600E76752 /* LiveActivityBundle.swift in Sources */,

+ 1 - 1
FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json

@@ -39,7 +39,7 @@
   "high" : 180,
   "low" : 70,
   "hours" : 6,
-  "dynamicBGColor" : false,
+  "dynamicGlucoseColor" : false,
   "xGridLines" : true,
   "yGridLines" : true,
   "oneDimensionalGraph" : false,

+ 0 - 63
FreeAPS/Sources/Helpers/BGColor.swift

@@ -1,63 +0,0 @@
-import CoreData
-import Foundation
-import SwiftUI
-
-// Helper function to decide how to pick the BG color
-public func setBGColor(bgValue: Int, highBGColorValue: Decimal, lowBGColorValue: Decimal, dynamicBGColor: Bool) -> Color {
-    // Auggie - injected fails here
-    // Convert Decimal to Int for high and low glucose values
-    let lowGlucose = NSDecimalNumber(decimal: lowBGColorValue).intValue - 20
-    let highGlucose = NSDecimalNumber(decimal: highBGColorValue).intValue + 20
-    let targetGlucose = 90
-
-    // TODO:
-    // Only use setDynamicBGColor if the setting is enabled in preferences
-    if dynamicBGColor {
-        return setDynamicBGColor(
-            bgValue: bgValue,
-            highGlucose: Int(highGlucose),
-            lowGlucose: Int(lowGlucose),
-            targetGlucose: targetGlucose
-        )
-    }
-    // Otheriwse, use static (orange = high, red = low, green = range)
-    else {
-        if bgValue > Int(highGlucose) {
-            return Color.orange
-        } else if bgValue < Int(lowGlucose) {
-            return Color.red
-        } else {
-            return Color.green
-        }
-    }
-}
-
-// Dynamic color - Define the hue values for the key points
-// We'll shift color gradually one BG point at a time
-// We'll shift through the rainbow colors of ROY-G-BIV from low to high
-// Start at red for lowGlucose, green for targetGlucose, and violet for highGlucose
-public func setDynamicBGColor(bgValue: Int, highGlucose: Int, lowGlucose: Int, targetGlucose: Int) -> Color {
-    let redHue: CGFloat = 0.0 / 360.0 // 0 degrees
-    let greenHue: CGFloat = 120.0 / 360.0 // 120 degrees
-    let purpleHue: CGFloat = 270.0 / 360.0 // 270 degrees
-
-    // Calculate the hue based on the bgLevel
-    var hue: CGFloat
-    if bgValue <= lowGlucose {
-        hue = redHue
-    } else if bgValue >= highGlucose {
-        hue = purpleHue
-    } else if bgValue <= targetGlucose {
-        // Interpolate between red and green
-        let ratio = CGFloat(bgValue - lowGlucose) / CGFloat(targetGlucose - lowGlucose)
-        hue = redHue + ratio * (greenHue - redHue)
-    } else {
-        // Interpolate between green and purple
-        let ratio = CGFloat(bgValue - targetGlucose) / CGFloat(highGlucose - targetGlucose)
-        hue = greenHue + ratio * (purpleHue - greenHue)
-    }
-
-    // Return the color with full saturation and brightness
-    let color = Color(hue: hue, saturation: 0.6, brightness: 0.9)
-    return color
-}

+ 73 - 0
FreeAPS/Sources/Helpers/DynamicGlucoseColor.swift

@@ -0,0 +1,73 @@
+import CoreData
+import Foundation
+import SwiftUI
+
+// Helper function to decide how to pick the glucose color
+public func getDynamicGlucoseColor(
+    glucoseValue: Decimal,
+    highGlucoseColorValue: Decimal,
+    lowGlucoseColorValue: Decimal,
+    targetGlucose: Decimal,
+    dynamicGlucoseColor: Bool,
+    offset: Decimal
+) -> Color {
+    // Convert Decimal to Int for high and low glucose values
+    let lowGlucose = lowGlucoseColorValue - offset
+    let highGlucose = highGlucoseColorValue + offset
+    let targetGlucose = targetGlucose
+
+    // Only use calculateHueBasedGlucoseColor if the setting is enabled in preferences
+    if dynamicGlucoseColor {
+        return calculateHueBasedGlucoseColor(
+            glucoseValue: glucoseValue,
+            highGlucose: highGlucose,
+            lowGlucose: lowGlucose,
+            targetGlucose: targetGlucose
+        )
+    }
+    // Otheriwse, use static (orange = high, red = low, green = range)
+    else {
+        if glucoseValue > highGlucose {
+            return Color.orange
+        } else if glucoseValue < lowGlucose {
+            return Color.red
+        } else {
+            return Color.green
+        }
+    }
+}
+
+// Dynamic color - Define the hue values for the key points
+// We'll shift color gradually one glucose point at a time
+// We'll shift through the rainbow colors of ROY-G-BIV from low to high
+// Start at red for lowGlucose, green for targetGlucose, and violet for highGlucose
+public func calculateHueBasedGlucoseColor(
+    glucoseValue: Decimal,
+    highGlucose: Decimal,
+    lowGlucose: Decimal,
+    targetGlucose: Decimal
+) -> Color {
+    let redHue: CGFloat = 0.0 / 360.0 // 0 degrees
+    let greenHue: CGFloat = 120.0 / 360.0 // 120 degrees
+    let purpleHue: CGFloat = 270.0 / 360.0 // 270 degrees
+
+    // Calculate the hue based on the bgLevel
+    var hue: CGFloat
+    if glucoseValue <= lowGlucose {
+        hue = redHue
+    } else if glucoseValue >= highGlucose {
+        hue = purpleHue
+    } else if glucoseValue <= targetGlucose {
+        // Interpolate between red and green
+        let ratio = CGFloat(truncating: (glucoseValue - lowGlucose) / (targetGlucose - lowGlucose) as NSNumber)
+
+        hue = redHue + ratio * (greenHue - redHue)
+    } else {
+        // Interpolate between green and purple
+        let ratio = CGFloat(truncating: (glucoseValue - targetGlucose) / (highGlucose - targetGlucose) as NSNumber)
+        hue = greenHue + ratio * (purpleHue - greenHue)
+    }
+    // Return the color with full saturation and brightness
+    let color = Color(hue: hue, saturation: 0.6, brightness: 0.9)
+    return color
+}

+ 3 - 3
FreeAPS/Sources/Models/FreeAPSSettings.swift

@@ -55,7 +55,7 @@ struct FreeAPSSettings: JSON, Equatable {
     var high: Decimal = 180
     var low: Decimal = 70
     var hours: Int = 6
-    var dynamicBGColor: Bool = false
+    var dynamicGlucoseColor: Bool = false
     var xGridLines: Bool = true
     var yGridLines: Bool = true
     var oneDimensionalGraph: Bool = false
@@ -267,8 +267,8 @@ extension FreeAPSSettings: Decodable {
             settings.hours = hours
         }
 
-        if let dynamicBGColor = try? container.decode(Bool.self, forKey: .dynamicBGColor) {
-            settings.dynamicBGColor = dynamicBGColor
+        if let dynamicGlucoseColor = try? container.decode(Bool.self, forKey: .dynamicGlucoseColor) {
+            settings.dynamicGlucoseColor = dynamicGlucoseColor
         }
 
         if let xGridLines = try? container.decode(Bool.self, forKey: .xGridLines) {

+ 6 - 0
FreeAPS/Sources/Modules/Home/HomeProvider.swift

@@ -53,5 +53,11 @@ extension Home {
             storage.retrieve(OpenAPS.Settings.pumpProfile, as: Autotune.self)?.basalProfile
                 ?? [BasalProfileEntry(start: "00:00", minutes: 0, rate: 1)]
         }
+
+        func getBGTarget() async -> BGTargets {
+            await storage.retrieveAsync(OpenAPS.Settings.bgTargets, as: BGTargets.self)
+                ?? BGTargets(from: OpenAPS.defaults(for: OpenAPS.Settings.bgTargets))
+                ?? BGTargets(units: .mgdL, userPrefferedUnits: .mgdL, targets: [])
+        }
     }
 }

+ 58 - 3
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -49,8 +49,9 @@ extension Home {
         @Published var maxValue: Decimal = 1.2
         @Published var lowGlucose: Decimal = 70
         @Published var highGlucose: Decimal = 180
+        @Published var currentGlucoseTarget: Decimal = 100
         @Published var overrideUnit: Bool = false
-        @Published var dynamicBGColor: Bool = false
+        @Published var dynamicGlucoseColor: Bool = false
         @Published var displayXgridLines: Bool = false
         @Published var displayYgridLines: Bool = false
         @Published var thresholdLines: Bool = false
@@ -129,8 +130,11 @@ extension Home {
             maxValue = settingsManager.preferences.autosensMax
             lowGlucose = units == .mgdL ? settingsManager.settings.low : settingsManager.settings.low.asMmolL
             highGlucose = units == .mgdL ? settingsManager.settings.high : settingsManager.settings.high.asMmolL
+            Task {
+                await self.getCurrentGlucoseTarget()
+            }
             overrideUnit = settingsManager.settings.overrideHbA1cUnit
-            dynamicBGColor = settingsManager.settings.dynamicBGColor
+            dynamicGlucoseColor = settingsManager.settings.dynamicGlucoseColor
             displayXgridLines = settingsManager.settings.xGridLines
             displayYgridLines = settingsManager.settings.yGridLines
             thresholdLines = settingsManager.settings.rulerMarks
@@ -423,6 +427,54 @@ extension Home {
             }
         }
 
+        private func getCurrentGlucoseTarget() async {
+            let now = Date()
+            let calendar = Calendar.current
+            let dateFormatter = DateFormatter()
+            dateFormatter.dateFormat = "HH:mm:ss"
+            dateFormatter.timeZone = TimeZone.current
+
+            let bgTargets = await provider.getBGTarget()
+            let entries: [(start: String, value: Decimal)] = bgTargets.targets.map { ($0.start, $0.low) }
+
+            for (index, entry) in entries.enumerated() {
+                guard let entryTime = dateFormatter.date(from: entry.start) else {
+                    print("Invalid entry start time: \(entry.start)")
+                    continue
+                }
+
+                let entryComponents = calendar.dateComponents([.hour, .minute, .second], from: entryTime)
+                let entryStartTime = calendar.date(
+                    bySettingHour: entryComponents.hour!,
+                    minute: entryComponents.minute!,
+                    second: entryComponents.second!,
+                    of: now
+                )!
+
+                let entryEndTime: Date
+                if index < entries.count - 1,
+                   let nextEntryTime = dateFormatter.date(from: entries[index + 1].start)
+                {
+                    let nextEntryComponents = calendar.dateComponents([.hour, .minute, .second], from: nextEntryTime)
+                    entryEndTime = calendar.date(
+                        bySettingHour: nextEntryComponents.hour!,
+                        minute: nextEntryComponents.minute!,
+                        second: nextEntryComponents.second!,
+                        of: now
+                    )!
+                } else {
+                    entryEndTime = calendar.date(byAdding: .day, value: 1, to: entryStartTime)!
+                }
+
+                if now >= entryStartTime, now < entryEndTime {
+                    await MainActor.run {
+                        currentGlucoseTarget = units == .mgdL ? entry.value : entry.value.asMmolL
+                    }
+                    return
+                }
+            }
+        }
+
         func openCGM() {
             router.mainSecondaryModalView.send(router.view(for: .cgmDirect))
         }
@@ -467,8 +519,11 @@ extension Home.StateModel:
         smooth = settingsManager.settings.smoothGlucose
         lowGlucose = units == .mgdL ? settingsManager.settings.low : settingsManager.settings.low.asMmolL
         highGlucose = units == .mgdL ? settingsManager.settings.high : settingsManager.settings.high.asMmolL
+        Task {
+            await getCurrentGlucoseTarget()
+        }
         overrideUnit = settingsManager.settings.overrideHbA1cUnit
-        dynamicBGColor = settingsManager.settings.dynamicBGColor
+        dynamicGlucoseColor = settingsManager.settings.dynamicGlucoseColor
         displayXgridLines = settingsManager.settings.xGridLines
         displayYgridLines = settingsManager.settings.yGridLines
         thresholdLines = settingsManager.settings.rulerMarks

+ 33 - 26
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -46,8 +46,9 @@ struct MainChartView: View {
     @Binding var smooth: Bool
     @Binding var highGlucose: Decimal
     @Binding var lowGlucose: Decimal
+    @Binding var currentGlucoseTarget: Decimal
     @Binding var screenHours: Int16
-    @Binding var dynamicBGColor: Bool
+    @Binding var dynamicGlucoseColor: Bool
     @Binding var displayXgridLines: Bool
     @Binding var displayYgridLines: Bool
     @Binding var thresholdLines: Bool
@@ -248,22 +249,26 @@ extension MainChartView {
         Chart {
             /// high and low threshold lines
             if thresholdLines {
-              let lowColor = setBGColor(
-                bgValue: lowGlucose,
-                highBGColorValue: highGlucose,
-                lowBGColorValue: lowGlucose,
-                dynamicBGColor: dynamicBGColor
-              )
-              let highColor = setBGColor(
-                bgValue: highGlucose,
-                highBGColorValue: highGlucose,
-                lowBGColorValue: lowGlucose,
-                dynamicBGColor: dynamicBGColor
-              )
-              RuleMark(y: .value("High", highGlucose)).foregroundStyle(highColor)
-                  .lineStyle(.init(lineWidth: 1, dash: [5]))
-              RuleMark(y: .value("Low", lowGlucose)).foregroundStyle(lowColor)
-                  .lineStyle(.init(lineWidth: 1, dash: [5]))
+                let lowColor = FreeAPS.getDynamicGlucoseColor(
+                    glucoseValue: lowGlucose,
+                    highGlucoseColorValue: highGlucose,
+                    lowGlucoseColorValue: lowGlucose,
+                    targetGlucose: lowGlucose,
+                    dynamicGlucoseColor: dynamicGlucoseColor,
+                    offset: units == .mgdL ? 20 : 20.asMmolL
+                )
+                let highColor = FreeAPS.getDynamicGlucoseColor(
+                    glucoseValue: highGlucose,
+                    highGlucoseColorValue: highGlucose,
+                    lowGlucoseColorValue: highGlucose,
+                    targetGlucose: highGlucose,
+                    dynamicGlucoseColor: dynamicGlucoseColor,
+                    offset: units == .mgdL ? 20 : 20.asMmolL
+                )
+                RuleMark(y: .value("High", highGlucose)).foregroundStyle(highColor)
+                    .lineStyle(.init(lineWidth: 1, dash: [5]))
+                RuleMark(y: .value("Low", lowGlucose)).foregroundStyle(lowColor)
+                    .lineStyle(.init(lineWidth: 1, dash: [5]))
             }
         }
         .id("DummyMainChart")
@@ -608,7 +613,7 @@ extension MainChartView {
             .foregroundStyle(Color.brown)
         }
     }
-  
+
     private var stops: [Gradient.Stop] {
         let low = Double(lowGlucose)
         let high = Double(highGlucose)
@@ -641,17 +646,19 @@ extension MainChartView {
             Gradient.Stop(color: .orange, location: 1.0)
         ]
     }
-  
+
     private func drawGlucose(dummy _: Bool) -> some ChartContent {
         ForEach(state.glucoseFromPersistence) { item in
             let glucoseToDisplay = units == .mgdL ? Decimal(item.glucose) : Decimal(item.glucose).asMmolL
-            let color = setBGColor(
-                bgValue: glucoseLevel,
-                highBGColorValue: highGlucose,
-                lowBGColorValue: lowGlucose,
-                dynamicBGColor: dynamicBGColor
+            let dynamicColor = FreeAPS.getDynamicGlucoseColor(
+                glucoseValue: glucoseToDisplay,
+                highGlucoseColorValue: highGlucose,
+                lowGlucoseColorValue: lowGlucose,
+                targetGlucose: currentGlucoseTarget,
+                dynamicGlucoseColor: dynamicGlucoseColor,
+                offset: units == .mgdL ? 20 : 20.asMmolL
             )
-                                               
+
             if smooth {
                 LineMark(x: .value("Time", item.date ?? Date()), y: .value("Value", glucoseToDisplay))
                     .foregroundStyle(
@@ -662,7 +669,7 @@ extension MainChartView {
                 PointMark(
                     x: .value("Time", item.date ?? Date(), unit: .second),
                     y: .value("Value", glucoseToDisplay)
-                ).foregroundStyle(color).symbolSize(20)
+                ).foregroundStyle(dynamicColor).symbolSize(20)
             }
         }
     }

+ 2 - 1
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -372,8 +372,9 @@ extension Home {
                     smooth: $state.smooth,
                     highGlucose: $state.highGlucose,
                     lowGlucose: $state.lowGlucose,
+                    currentGlucoseTarget: $state.currentGlucoseTarget,
                     screenHours: $state.hours,
-                    dynamicBGColor: $state.dynamicBGColor,
+                    dynamicGlucoseColor: $state.dynamicGlucoseColor,
                     displayXgridLines: $state.displayXgridLines,
                     displayYgridLines: $state.displayYgridLines,
                     thresholdLines: $state.thresholdLines,

+ 2 - 2
FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift

@@ -12,7 +12,7 @@ extension StatConfig {
         @Published var low: Decimal = 70
         @Published var high: Decimal = 180
         @Published var hours: Decimal = 6
-        @Published var dynamicBGColor = false
+        @Published var dynamicGlucoseColor = false
         @Published var xGridLines = false
         @Published var yGridLines: Bool = false
         @Published var oneDimensionalGraph = false
@@ -26,7 +26,7 @@ extension StatConfig {
             self.units = units
 
             subscribeSetting(\.overrideHbA1cUnit, on: $overrideHbA1cUnit) { overrideHbA1cUnit = $0 }
-            subscribeSetting(\.dynamicBGColor, on: $dynamicBGColor) { dynamicBGColor = $0 }
+            subscribeSetting(\.dynamicGlucoseColor, on: $dynamicGlucoseColor) { dynamicGlucoseColor = $0 }
             subscribeSetting(\.xGridLines, on: $xGridLines) { xGridLines = $0 }
             subscribeSetting(\.yGridLines, on: $yGridLines) { yGridLines = $0 }
             subscribeSetting(\.rulerMarks, on: $rulerMarks) { rulerMarks = $0 }

+ 1 - 1
FreeAPS/Sources/Modules/StatConfig/View/StatConfigRootView.swift

@@ -45,7 +45,7 @@ extension StatConfig {
         var body: some View {
             Form {
                 Section {
-                    Toggle("Use Dynamic BG Color", isOn: $state.dynamicBGColor)
+                    Toggle("Use Dynamic BG Color", isOn: $state.dynamicGlucoseColor)
                     Toggle("Display Chart X - Grid lines", isOn: $state.xGridLines)
                     Toggle("Display Chart Y - Grid lines", isOn: $state.yGridLines)
                     Toggle("Display Chart Threshold lines for Low and High", isOn: $state.rulerMarks)

+ 1 - 1
FreeAPS/Sources/Services/LiveActivity/LiveActitiyAttributes.swift

@@ -20,7 +20,7 @@ struct LiveActivityAttributes: ActivityAttributes {
         let rotationDegrees: Double
         let highGlucose: Decimal
         let lowGlucose: Decimal
-        let dynamicBGColor: Bool
+        let dynamicGlucoseColor: Bool
         let cob: Decimal
         let iob: Decimal
         let unit: String

+ 1 - 1
FreeAPS/Sources/Services/LiveActivity/LiveActivityAttributes+Helper.swift

@@ -89,7 +89,7 @@ extension LiveActivityAttributes.ContentState {
                 rotationDegrees: rotationDegrees,
                 highGlucose: settings.high,
                 lowGlucose: settings.low,
-                dynamicBGColor: settings.dynamicBGColor,
+                dynamicGlucoseColor: settings.dynamicGlucoseColor,
                 cob: Decimal(determination?.cob ?? 0),
                 iob: determination?.iob ?? 0 as Decimal,
                 unit: settings.units.rawValue,

+ 37 - 55
LiveActivity/LiveActivity.swift

@@ -179,7 +179,11 @@ struct LiveActivity: Widget {
         }
     }
 
-    private func bgAndTrend(context: ActivityViewContext<LiveActivityAttributes>, size: Size) -> (some View, Int) {
+    private func bgAndTrend(
+        context: ActivityViewContext<LiveActivityAttributes>,
+        size: Size,
+        dynamicColor _: Color
+    ) -> (some View, Int) {
         var characters = 0
 
         let bgText = context.state.bg
@@ -288,11 +292,13 @@ struct LiveActivity: Widget {
                         y: .value("Value", displayValue)
                     ).symbolSize(15)
 
-                    let color = setBGColor(
-                        bgValue: Int(currentValue),
-                        highBGColorValue: Decimal(additionalState.highGlucose),
-                        lowBGColorValue: Decimal(additionalState.lowGlucose),
-                        dynamicBGColor: additionalState.dynamicBGColor
+                    let color = getDynamicGlucoseColor(
+                        glucoseValue: currentValue,
+                        highGlucoseColorValue: additionalState.highGlucose,
+                        lowGlucoseColorValue: additionalState.lowGlucose,
+                        targetGlucose: 90,
+                        dynamicGlucoseColor: additionalState.dynamicGlucoseColor,
+                        offset: additionalState.unit == "mg/dL" ? 20 : 20.asMmolL
                     )
 
                     pointMark.foregroundStyle(color)
@@ -335,6 +341,15 @@ struct LiveActivity: Widget {
             .activityBackgroundTint(Color.black.opacity(0.8))
         } else {
             Group {
+                let glucoseColor = getDynamicGlucoseColor(
+                    glucoseValue: Decimal(string: context.state.bg) ?? 100,
+                    highGlucoseColorValue: context.state.detailedViewState?.highGlucose ?? 180,
+                    lowGlucoseColorValue: context.state.detailedViewState?.lowGlucose ?? 70,
+                    targetGlucose: 90,
+                    dynamicGlucoseColor: context.state.detailedViewState?.dynamicGlucoseColor ?? false,
+                    offset: context.state.detailedViewState?.unit == "mg/dL" ? 20 : 20.asMmolL
+                )
+
                 if context.state.isInitialState {
                     // add vertical and horizontal spacers around the label to ensure that the live activity view gets filled completely
                     HStack {
@@ -348,7 +363,7 @@ struct LiveActivity: Widget {
                     }
                 } else {
                     HStack(spacing: 3) {
-                        bgAndTrend(context: context, size: .expanded).0.font(.title)
+                        bgAndTrend(context: context, size: .expanded, dynamicColor: glucoseColor).0.font(.title)
                         Spacer()
                         VStack(alignment: .trailing, spacing: 5) {
                             changeLabel(context: context).font(.title3)
@@ -369,14 +384,22 @@ struct LiveActivity: Widget {
     }
 
     func dynamicIsland(context: ActivityViewContext<LiveActivityAttributes>) -> DynamicIsland {
-        let bgValueForColor = Int(context.state.bg) ?? 100
+        let glucoseValueForColor = context.state.bg
         let highGlucose = context.state.detailedViewState?.highGlucose ?? 180
         let lowGlucose = context.state.detailedViewState?.lowGlucose ?? 70
-        let dynamicBGColor = context.state.detailedViewState?.dynamicBGColor ?? false
+        let dynamicGlucoseColor = context.state.detailedViewState?.dynamicGlucoseColor ?? false
+        let glucoseColor = getDynamicGlucoseColor(
+            glucoseValue: Decimal(string: glucoseValueForColor) ?? 100,
+            highGlucoseColorValue: highGlucose,
+            lowGlucoseColorValue: lowGlucose,
+            targetGlucose: 90,
+            dynamicGlucoseColor: dynamicGlucoseColor,
+            offset: context.state.detailedViewState?.unit == "mg/dL" ? 20 : 20.asMmolL
+        )
 
         return DynamicIsland {
             DynamicIslandExpandedRegion(.leading) {
-                bgAndTrend(context: context, size: .expanded).0.font(.title2).padding(.leading, 5)
+                bgAndTrend(context: context, size: .expanded, dynamicColor: glucoseColor).0.font(.title2).padding(.leading, 5)
             }
             DynamicIslandExpandedRegion(.trailing) {
                 changeLabel(context: context).font(.title2).padding(.trailing, 5)
@@ -402,52 +425,11 @@ struct LiveActivity: Widget {
                 }
             }
         } compactLeading: {
-            // bgAndTrend(context: context, size: .compact).0.padding(.leading, 4)
-            HStack(spacing: 1) {
-                Image(systemName: "drop.fill")
-                    .renderingMode(.template)
-                    .foregroundStyle(setBGColor(
-                        bgValue: bgValueForColor,
-                        highBGColorValue: Decimal(highGlucose),
-                        lowBGColorValue: Decimal(lowGlucose),
-                        dynamicBGColor: dynamicBGColor
-                    ))
-                    .baselineOffset(-2)
-                Text("\(context.state.bg)")
-                    .foregroundStyle(setBGColor(
-                        bgValue: bgValueForColor,
-                        highBGColorValue: Decimal(highGlucose),
-                        lowBGColorValue: Decimal(lowGlucose),
-                        dynamicBGColor: dynamicBGColor
-                    ))
-                    .minimumScaleFactor(0.1)
-                    .fontWeight(.bold)
-            }
+            bgAndTrend(context: context, size: .compact, dynamicColor: glucoseColor).0.padding(.leading, 4)
         } compactTrailing: {
-            // changeLabel(context: context).padding(.trailing, 4)
-            HStack(spacing: -5) {
-                Text("\(context.state.direction ?? "--")")
-                    .foregroundStyle(setBGColor(
-                        bgValue: bgValueForColor,
-                        highBGColorValue: Decimal(highGlucose),
-                        lowBGColorValue: Decimal(lowGlucose),
-                        dynamicBGColor: dynamicBGColor
-                    ))
-                    .minimumScaleFactor(0.1)
-                    .fontWeight(.bold)
-                    .baselineOffset(-2)
-                Text("\(context.state.change)")
-                    .foregroundStyle(setBGColor(
-                        bgValue: bgValueForColor,
-                        highBGColorValue: Decimal(highGlucose),
-                        lowBGColorValue: Decimal(lowGlucose),
-                        dynamicBGColor: dynamicBGColor
-                    ))
-                    .minimumScaleFactor(0.1)
-                    .fontWeight(.bold)
-            }
+            changeLabel(context: context).padding(.trailing, 4)
         } minimal: {
-            let (_label, characterCount) = bgAndTrend(context: context, size: .minimal)
+            let (_label, characterCount) = bgAndTrend(context: context, size: .minimal, dynamicColor: glucoseColor)
             let label = _label.padding(.leading, 7).padding(.trailing, 3)
 
             if characterCount < 4 {
@@ -482,7 +464,7 @@ private extension LiveActivityAttributes.ContentState {
     // Use mmol/l notation with decimal point as well for the same reason, it uses up to 4 characters, while mg/dl uses up to 3
     static var testWide: LiveActivityAttributes.ContentState {
         LiveActivityAttributes.ContentState(
-            bg: "00.0",
+            bg: 00.0.description,
             direction: "→",
             change: "+0.0",
             date: Date(),

+ 2 - 2
Trio.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -1,5 +1,5 @@
 {
-  "originHash" : "59ac7eba66375d6eb406e758cb0b9964f4b3b0ae45c5665596f00384c32262b9",
+  "originHash" : "f5c836c216c4ca7d356e3777e58d6d4f9502b03f3974891349eb775f4c4cf750",
   "pins" : [
     {
       "identity" : "cryptoswift",
@@ -49,7 +49,7 @@
     {
       "identity" : "swiftcharts",
       "kind" : "remoteSourceControl",
-      "location" : "https://github.com/ivanschuetz/SwiftCharts.git",
+      "location" : "https://github.com/ivanschuetz/SwiftCharts",
       "state" : {
         "branch" : "master",
         "revision" : "c354c1945bb35a1f01b665b22474f6db28cba4a2"