Jonas Björkert vor 1 Jahr
Ursprung
Commit
570ae3370e

+ 5 - 5
LoopFollow/Alarm/Alarm.swift

@@ -34,14 +34,14 @@ struct Alarm: Identifiable, Codable, Equatable {
 
     /// Alarm threashold, it can be a bgvalue (in mg/Dl), or day for example
     /// Also used as bg limit for drop alarms for example
-    var threshold: Float?
+    var threshold: Double?
 
     /// If the alarm looks at predictions, this is how many predictions to include
     var predictiveReadings: Int?
 
     /// If the alarm acts on delta, the delta is stored here, it can be a delta bgvalue (in mg/Dl)
     /// If a delta alarm is only active below a bg, that bg is stored in threshold
-    var delta: Float?
+    var delta: Double?
 
     /// Number of consecutive 5‑min readings that must satisfy the alarm criteria
     var consecutiveReadings: Int?
@@ -74,13 +74,13 @@ struct Alarm: Identifiable, Codable, Equatable {
     var missedBolusPrebolusWindow: Int?
 
     /// “Ignore Bolus <= X units” (don’t count any bolus smaller than or equal to this)
-    var missedBolusIgnoreSmallBolusUnits: Float?
+    var missedBolusIgnoreSmallBolusUnits: Double?
 
     /// “Ignore Under Grams” (if carb entry is under this many grams, skip the alert)
-    var missedBolusIgnoreUnderGrams: Float?
+    var missedBolusIgnoreUnderGrams: Double?
 
     /// “Ignore Under BG” (if current BG is below this, skip the alert)
-    var missedBolusIgnoreUnderBG: Float?
+    var missedBolusIgnoreUnderBG: Double?
 
     // ─────────────────────────────────────────────────────────────
     // Bolus‑Count fields ─

+ 11 - 21
LoopFollow/Alarm/AlarmEditing/Components/AlarmThresholdPickerSection.swift

@@ -9,12 +9,11 @@
 import SwiftUI
 import HealthKit
 
-struct AlarmThresholdRow: View {
+struct AlarmBGSection: View {
     // ── Public API ──────────────────────────────────────────────────────────────
     let title: String
     let range: ClosedRange<Double>
-    let step: Double          // 1 for mg/dL, 0.1 for mmol/L
-    @Binding var value: Double   // **stored in mg/dL**
+    @Binding var value: Double
 
     // ── Private state ──────────────────────────────────────────────────────────
     @State private var showPicker = false
@@ -23,12 +22,14 @@ struct AlarmThresholdRow: View {
     private var unit: HKUnit { UserDefaultsRepository.getPreferredUnit() }
 
     private var displayValue: String {
-        format(value, in: unit)
+        Localizer.formatQuantity(value)
     }
 
     // Generate all selectable display values for the picker
     private var pickerValues: [Double] {
-        stride(from: range.lowerBound, through: range.upperBound, by: step)
+        let step : Double = unit == .millimolesPerLiter ? 18.0 * 0.1 : 1.0
+
+        return stride(from: range.lowerBound, through: range.upperBound, by: step)
             .map { $0 }
     }
 
@@ -45,12 +46,11 @@ struct AlarmThresholdRow: View {
             .onTapGesture { showPicker = true }
         }
         .sheet(isPresented: $showPicker) {
-            // Expanded wheel picker
             NavigationStack {
                 VStack {
                     Picker("", selection: bindingForPicker) {
                         ForEach(pickerValues, id: \.self) { v in
-                            Text(format(v, in: unit))
+                            Text(Localizer.formatQuantity(v))
                                 .tag(v)
                         }
                     }
@@ -62,22 +62,12 @@ struct AlarmThresholdRow: View {
                         Button("Done") { showPicker = false }
                     }
                 }
-            }   .presentationDetents([.fraction(0.35), .medium])   // 35 % or medium height
-                .presentationDragIndicator(.visible)               // the little grab-bar
-        }
-    }
-
-    // MARK: – Helpers
-    private func format(_ mgdl: Double, in unit: HKUnit) -> String {
-        if unit == .millimolesPerLiter {
-            let mmol = mgdl / 18.0
-            return String(format: "%.1f mmol/L", mmol)
-        } else {
-            return String(format: "%.0f mg/dL", mgdl)
+            }
+            .presentationDetents([.fraction(0.35), .medium])
+            .presentationDragIndicator(.visible)
         }
     }
 
-    // Bind the picker directly to `value`, snapping to the closest choice
     private var bindingForPicker: Binding<Double> {
         Binding(
             get: {
@@ -85,7 +75,7 @@ struct AlarmThresholdRow: View {
                 pickerValues.min(by: { abs($0 - value) < abs($1 - value) }) ?? value
             },
             set: { newVal in
-                value = newVal    // stored in mg/dL
+                value = newVal // stored in mg/dL
             }
         )
     }

+ 2 - 2
LoopFollow/Alarm/AlarmEditing/Editors/BuildExpireAlarmEditor.swift

@@ -21,8 +21,8 @@ struct BuildExpireAlarmEditor: View {
             step: 1,
             unitLabel: alarm.type.timeUnit.label,
             value: Binding(
-              get: { Double(alarm.threshold ?? 1) },
-              set: { alarm.threshold = Float($0) }
+              get: { alarm.threshold ?? 1 },
+              set: { alarm.threshold = $0 }
             )
           )
 

+ 3 - 4
LoopFollow/Alarm/AlarmEditing/Editors/LowBgAlarmEditor.swift

@@ -16,13 +16,12 @@ struct LowBgAlarmEditor: View {
         Form {
             AlarmGeneralSection(alarm: $alarm)
 
-            AlarmThresholdRow(
+            AlarmBGSection(
                 title: "BG",
                 range: 40...150,
-                step: UserDefaultsRepository.getPreferredUnit() == .millimolesPerLiter ? 18.0 * 0.1 : 1.0,
                 value: Binding(
-                    get: { Double(alarm.threshold ?? 80) },
-                    set: { alarm.threshold = Float($0) }
+                    get: { alarm.threshold ?? 80 },
+                    set: { alarm.threshold = $0 }
                 )
             )
         }

+ 2 - 2
LoopFollow/Alarm/AlarmManager.swift

@@ -36,8 +36,8 @@ class AlarmManager {
             }
             // Secondary: threshold ordering if applicable
             if let asc = lhs.type.thresholdSortAscending {
-                let leftVal = lhs.threshold ?? (asc ? Float.infinity : -Float.infinity)
-                let rightVal = rhs.threshold ?? (asc ? Float.infinity : -Float.infinity)
+                let leftVal = lhs.threshold ?? (asc ? Double.infinity : -Double.infinity)
+                let rightVal = rhs.threshold ?? (asc ? Double.infinity : -Double.infinity)
                 return asc ? leftVal < rightVal : leftVal > rightVal
             }
             // Tertiary: fallback to insertion order

+ 7 - 8
LoopFollow/Helpers/Localizer.swift

@@ -22,15 +22,14 @@ class Localizer {
     }
 
     static func formatQuantity(_ quantity: HKQuantity) -> String {
-        let unitPreference = UserDefaultsRepository.units.value
+        let unit: HKUnit = UserDefaultsRepository.getPreferredUnit()
+        let value = quantity.doubleValue(for: unit)
 
-        if unitPreference == "mg/dL" {
-            let valueInMgdL = quantity.doubleValue(for: .milligramsPerDeciliter)
-            return formatToLocalizedString(valueInMgdL, maxFractionDigits: 0, minFractionDigits: 0)
-        } else {
-            let valueInMmolL = quantity.doubleValue(for: .millimolesPerLiter)
-            return formatToLocalizedString(valueInMmolL, maxFractionDigits: 1, minFractionDigits: 1)
-        }
+        return formatToLocalizedString(value, maxFractionDigits: unit.preferredFractionDigits, minFractionDigits: unit.preferredFractionDigits)
+    }
+
+    static func formatQuantity(_ value: Double) -> String {
+        formatQuantity(HKQuantity(unit: .milligramsPerDeciliter, doubleValue: value))
     }
 
     static func formatTimestampToLocalString(_ timestamp: TimeInterval) -> String {