polscm32 aka Marvout 1 год назад
Родитель
Сommit
f2affaaa3c

+ 8 - 2
FreeAPS/Sources/Services/LiveActivity/Data/DataManager.swift

@@ -59,7 +59,7 @@ extension LiveActivityBridge {
             key: "date",
             key: "date",
             ascending: false,
             ascending: false,
             fetchLimit: 1,
             fetchLimit: 1,
-            propertiesToFetch: ["enabled", "name"]
+            propertiesToFetch: ["enabled", "name", "target", "date", "duration"]
         )
         )
 
 
         guard let overrideResults = results as? [[String: Any]] else {
         guard let overrideResults = results as? [[String: Any]] else {
@@ -68,7 +68,13 @@ extension LiveActivityBridge {
 
 
         await context.perform {
         await context.perform {
             self.isOverridesActive = overrideResults.first.map {
             self.isOverridesActive = overrideResults.first.map {
-                OverrideData(isActive: $0["enabled"] as? Bool ?? false, overrideName: $0["name"] as? String ?? "Override")
+                OverrideData(
+                    isActive: $0["enabled"] as? Bool ?? false,
+                    overrideName: $0["name"] as? String ?? "Override",
+                    date: $0["date"] as? Date ?? Date(),
+                    duration: $0["duration"] as? Decimal ?? 0,
+                    target: $0["target"] as? Decimal ?? 0
+                )
             }
             }
         }
         }
     }
     }

+ 3 - 0
FreeAPS/Sources/Services/LiveActivity/Data/OverrideData.swift

@@ -3,4 +3,7 @@ import Foundation
 struct OverrideData {
 struct OverrideData {
     let isActive: Bool
     let isActive: Bool
     let overrideName: String
     let overrideName: String
+    let date: Date
+    let duration: Decimal
+    let target: Decimal
 }
 }

+ 3 - 0
FreeAPS/Sources/Services/LiveActivity/LiveActitiyAttributes.swift

@@ -33,6 +33,9 @@ struct LiveActivityAttributes: ActivityAttributes {
         let unit: String
         let unit: String
         let isOverrideActive: Bool
         let isOverrideActive: Bool
         let overrideName: String
         let overrideName: String
+        let overrideDate: Date
+        let overrideDuration: Decimal
+        let overrideTarget: Decimal
     }
     }
 
 
     let startDate: Date
     let startDate: Date

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

@@ -104,7 +104,10 @@ extension LiveActivityAttributes.ContentState {
                 iob: determination?.iob ?? 0 as Decimal,
                 iob: determination?.iob ?? 0 as Decimal,
                 unit: settings.units.rawValue,
                 unit: settings.units.rawValue,
                 isOverrideActive: override?.isActive ?? false,
                 isOverrideActive: override?.isActive ?? false,
-                overrideName: override?.overrideName ?? "Override"
+                overrideName: override?.overrideName ?? "Override",
+                overrideDate: override?.date ?? Date(),
+                overrideDuration: override?.duration ?? 0,
+                overrideTarget: override?.target ?? 0
             )
             )
 
 
         case .simple:
         case .simple:

+ 84 - 55
LiveActivity/LiveActivity.swift

@@ -314,64 +314,93 @@ struct LiveActivityChartView: View {
     var additionalState: LiveActivityAttributes.ContentAdditionalState
     var additionalState: LiveActivityAttributes.ContentAdditionalState
 
 
     var body: some View {
     var body: some View {
-        if context.isStale {
-            Text("No data available")
-        } else {
-            // Determine scale
-            let minValue = min(additionalState.chart.min() ?? 45, 40) - 20
-            let maxValue = max(additionalState.chart.max() ?? 270, 300) + 50
-
-            let yAxisRuleMarkMin = additionalState.unit == "mg/dL" ? additionalState.lowGlucose : additionalState.lowGlucose
-                .asMmolL
-            let yAxisRuleMarkMax = additionalState.unit == "mg/dL" ? additionalState.highGlucose : additionalState.highGlucose
-                .asMmolL
-            let target = additionalState.unit == "mg/dL" ? additionalState.target : additionalState.target.asMmolL
-
-            Chart {
-                RuleMark(y: .value("Low", yAxisRuleMarkMin))
-                    .lineStyle(.init(lineWidth: 0.5, dash: [5]))
-                RuleMark(y: .value("High", yAxisRuleMarkMax))
-                    .lineStyle(.init(lineWidth: 0.5, dash: [5]))
-                RuleMark(y: .value("Target", target)).foregroundStyle(.green.gradient).lineStyle(.init(lineWidth: 1))
-
-                ForEach(additionalState.chart.indices, id: \.self) { index in
-                    let currentValue = additionalState.chart[index]
-                    let displayValue = additionalState.unit == "mg/dL" ? currentValue : currentValue.asMmolL
-                    let chartDate = additionalState.chartDate[index] ?? Date()
-                    let pointMark = PointMark(
-                        x: .value("Time", chartDate),
-                        y: .value("Value", displayValue)
-                    ).symbolSize(15)
-
-                    if displayValue > yAxisRuleMarkMax {
-                        pointMark.foregroundStyle(Color.orange.gradient)
-                    } else if displayValue < yAxisRuleMarkMin {
-                        pointMark.foregroundStyle(Color.red.gradient)
-                    } else {
-                        pointMark.foregroundStyle(Color.green.gradient)
-                    }
-                }
+        // Determine scale
+        let minValue = min(additionalState.chart.min() ?? 39, 39) as Decimal
+        let maxValue = max(additionalState.chart.max() ?? 300, 300) as Decimal
+
+        let yAxisRuleMarkMin = additionalState.unit == "mg/dL" ? additionalState.lowGlucose : additionalState.lowGlucose
+            .asMmolL
+        let yAxisRuleMarkMax = additionalState.unit == "mg/dL" ? additionalState.highGlucose : additionalState.highGlucose
+            .asMmolL
+        let target = additionalState.unit == "mg/dL" ? additionalState.target : additionalState.target.asMmolL
+
+        let calendar = Calendar.current
+        let now = Date()
+
+        let startDate = calendar.date(byAdding: .hour, value: -6, to: now) ?? now
+        let endDate = calendar.date(byAdding: .hour, value: 2, to: now) ?? now
+
+        Chart {
+            RuleMark(y: .value("Low", yAxisRuleMarkMin))
+                .lineStyle(.init(lineWidth: 0.5, dash: [5]))
+            RuleMark(y: .value("High", yAxisRuleMarkMax))
+                .lineStyle(.init(lineWidth: 0.5, dash: [5]))
+            RuleMark(y: .value("Target", target)).foregroundStyle(.green.gradient).lineStyle(.init(lineWidth: 1))
+
+            if context.state.detailedViewState?.isOverrideActive == true {
+                drawActiveOverrides()
             }
             }
-            .chartYAxis {
-                AxisMarks(position: .trailing) { _ in
-                    AxisGridLine(stroke: .init(lineWidth: 0.2, dash: [2, 3])).foregroundStyle(Color.white)
-                    AxisValueLabel().foregroundStyle(.primary).font(.footnote)
-                }
+
+            drawChart(yAxisRuleMarkMin: yAxisRuleMarkMin, yAxisRuleMarkMax: yAxisRuleMarkMax)
+        }
+        .chartYAxis {
+            AxisMarks(position: .trailing) { _ in
+                AxisGridLine(stroke: .init(lineWidth: 0.2, dash: [2, 3])).foregroundStyle(Color.white)
+                AxisValueLabel().foregroundStyle(.primary).font(.footnote)
             }
             }
-            .chartYScale(domain: additionalState.unit == "mg/dL" ? minValue ... maxValue : minValue.asMmolL ... maxValue.asMmolL)
-            .chartYAxis(.hidden)
-            .chartPlotStyle { plotContent in
-                plotContent
-                    .background(
-                        RoundedRectangle(cornerRadius: 12)
-                            .fill(Color.clear)
-                    )
-                    .clipShape(RoundedRectangle(cornerRadius: 12))
+        }
+        .chartYScale(domain: additionalState.unit == "mg/dL" ? minValue ... maxValue : minValue.asMmolL ... maxValue.asMmolL)
+        .chartYAxis(.hidden)
+        .chartPlotStyle { plotContent in
+            plotContent
+                .background(
+                    RoundedRectangle(cornerRadius: 12)
+                        .fill(Color.clear)
+                )
+                .clipShape(RoundedRectangle(cornerRadius: 12))
+        }
+        .chartXScale(domain: startDate ... endDate)
+        .chartXAxis {
+            AxisMarks(position: .automatic) { _ in
+                AxisGridLine(stroke: .init(lineWidth: 0.2, dash: [2, 3])).foregroundStyle(Color.white)
             }
             }
-            .chartXAxis {
-                AxisMarks(position: .automatic) { _ in
-                    AxisGridLine(stroke: .init(lineWidth: 0.2, dash: [2, 3])).foregroundStyle(Color.white)
-                }
+        }
+    }
+
+    private func drawActiveOverrides() -> some ChartContent {
+        let start: Date = context.state.detailedViewState?.overrideDate ?? .distantPast
+
+        let duration = context.state.detailedViewState?.overrideDuration ?? 0
+        let durationAsTimeInterval = TimeInterval((duration as NSDecimalNumber).doubleValue * 60) // return seconds
+
+        let end: Date = start.addingTimeInterval(durationAsTimeInterval)
+        let target = context.state.detailedViewState?.overrideTarget ?? 0
+
+        return RuleMark(
+            xStart: .value("Start", start, unit: .second),
+            xEnd: .value("End", end, unit: .second),
+            y: .value("Value", target)
+        )
+        .foregroundStyle(Color.purple.opacity(0.6))
+        .lineStyle(.init(lineWidth: 8))
+    }
+
+    private func drawChart(yAxisRuleMarkMin: Decimal, yAxisRuleMarkMax: Decimal) -> some ChartContent {
+        ForEach(additionalState.chart.indices, id: \.self) { index in
+            let currentValue = additionalState.chart[index]
+            let displayValue = additionalState.unit == "mg/dL" ? currentValue : currentValue.asMmolL
+            let chartDate = additionalState.chartDate[index] ?? Date()
+            let pointMark = PointMark(
+                x: .value("Time", chartDate),
+                y: .value("Value", displayValue)
+            ).symbolSize(15)
+
+            if displayValue > yAxisRuleMarkMax {
+                pointMark.foregroundStyle(Color.orange.gradient)
+            } else if displayValue < yAxisRuleMarkMin {
+                pointMark.foregroundStyle(Color.red.gradient)
+            } else {
+                pointMark.foregroundStyle(Color.green.gradient)
             }
             }
         }
         }
     }
     }