ソースを参照

Merge branch 'override-update' into tt+or

Mike Plante 1 年間 前
コミット
fb73418297

+ 66 - 0
FreeAPS/Sources/Modules/OverrideConfig/OverrideStateModel.swift

@@ -1082,3 +1082,69 @@ struct RadioButton: View {
         .buttonStyle(PlainButtonStyle())
     }
 }
+
+struct TargetPicker: View {
+    let label: String
+    @Binding var selection: Decimal
+    let options: [Decimal]
+    let units: GlucoseUnits
+    var hasChanges: Binding<Bool>?
+    @Binding var targetStep: Decimal
+    @Binding var displayPickerTarget: Bool
+    var toggleScrollWheel: (_ picker: Bool) -> Bool
+
+    var body: some View {
+        HStack {
+            Text(label)
+            Spacer()
+            Text(
+                (units == .mgdL ? selection.description : selection.formattedAsMmolL) + " " + units.rawValue
+            )
+            .foregroundColor(!displayPickerTarget ? .primary : .accentColor)
+        }
+        .onTapGesture {
+            displayPickerTarget = toggleScrollWheel(displayPickerTarget)
+        }
+        if displayPickerTarget {
+            HStack {
+                // Radio buttons and text on the left side
+                VStack(alignment: .leading) {
+                    // Radio buttons for step iteration
+                    let stepChoices: [Decimal] = units == .mgdL ? [1, 5] : [1, 9]
+                    ForEach(stepChoices, id: \.self) { step in
+                        let label = (units == .mgdL ? step.description : step.formattedAsMmolL) + " " +
+                            units.rawValue
+                        RadioButton(
+                            isSelected: targetStep == step,
+                            label: label
+                        ) {
+                            targetStep = step
+                            selection = OverrideConfig.StateModel.roundTargetToStep(selection, step)
+                        }
+                        .padding(.top, 10)
+                    }
+                }
+                .frame(maxWidth: .infinity)
+
+                Spacer()
+
+                // Picker on the right side
+                Picker(selection: Binding(
+                    get: { OverrideConfig.StateModel.roundTargetToStep(selection, targetStep) },
+                    set: {
+                        selection = $0
+                        hasChanges?.wrappedValue = true // This safely updates if hasChanges is provided
+                    }
+                ), label: Text("")) {
+                    ForEach(options, id: \.self) { option in
+                        Text((units == .mgdL ? option.description : option.formattedAsMmolL) + " " + units.rawValue)
+                            .tag(option)
+                    }
+                }
+                .pickerStyle(WheelPickerStyle())
+                .frame(maxWidth: .infinity)
+            }
+            .listRowSeparator(.hidden, edges: .top)
+        }
+    }
+}

+ 22 - 63
FreeAPS/Sources/Modules/OverrideConfig/View/AddOverrideForm.swift

@@ -230,73 +230,32 @@ struct AddOverrideForm: View {
 
             Section {
                 Toggle(isOn: $state.shouldOverrideTarget) {
-                    Text("Override Profile Target")
+                    Text("Override Target")
                 }
 
                 if state.shouldOverrideTarget {
-                    HStack {
-                        Text("Target Glucose")
-                        Spacer()
-                        Text(
-                            (state.units == .mgdL ? state.target.description : state.target.formattedAsMmolL) + " " + state
-                                .units.rawValue
-                        )
-                        .foregroundColor(!displayPickerTarget ? .primary : .accentColor)
-                    }
-                    .onTapGesture {
-                        displayPickerTarget = toggleScrollWheel(displayPickerTarget)
-                    }
-
-                    if displayPickerTarget {
-                        HStack {
-                            // Radio buttons and text on the left side
-                            VStack(alignment: .leading) {
-                                // Radio buttons for step iteration
-                                let stepChoices: [Decimal] = state.units == .mgdL ? [1, 5] : [1, 9]
-                                ForEach(stepChoices, id: \.self) { step in
-                                    let label = (state.units == .mgdL ? step.description : step.formattedAsMmolL) + " " +
-                                        state.units.rawValue
-
-                                    RadioButton(
-                                        isSelected: targetStep == step,
-                                        label: label
-                                    ) {
-                                        targetStep = step
-                                        state.target = OverrideConfig.StateModel.roundTargetToStep(state.target, targetStep)
-                                    }
-                                    .padding(.top, 10)
-                                }
-                            }
-                            .frame(maxWidth: .infinity)
-
-                            Spacer()
-
-                            // Picker on the right side
-                            let settingsProvider = PickerSettingsProvider.shared
-                            let glucoseSetting = PickerSetting(value: 0, step: targetStep, min: 72, max: 270, type: .glucose)
-                            Picker(selection: Binding(
-                                get: { OverrideConfig.StateModel.roundTargetToStep(state.target, targetStep) },
-                                set: { state.target = $0 }
-                            ), label: Text("")) {
-                                ForEach(
-                                    settingsProvider.generatePickerValues(
-                                        from: glucoseSetting,
-                                        units: state.units,
-                                        roundMinToStep: true
-                                    ),
-                                    id: \.self
-                                ) { glucose in
-                                    Text(
-                                        (state.units == .mgdL ? glucose.description : glucose.formattedAsMmolL) + " " + state
-                                            .units.rawValue
-                                    )
-                                    .tag(glucose)
-                                }
-                            }
-                            .pickerStyle(WheelPickerStyle())
-                            .frame(maxWidth: .infinity)
+                    let settingsProvider = PickerSettingsProvider.shared
+                    let glucoseSetting = PickerSetting(value: 0, step: targetStep, min: 72, max: 270, type: .glucose)
+                    TargetPicker(
+                        label: "Target Glucose",
+                        selection: Binding(
+                            get: { state.target },
+                            set: { state.target = $0 }
+                        ),
+                        options: settingsProvider.generatePickerValues(
+                            from: glucoseSetting,
+                            units: state.units,
+                            roundMinToStep: true
+                        ),
+                        units: state.units,
+                        targetStep: $targetStep,
+                        displayPickerTarget: $displayPickerTarget,
+                        toggleScrollWheel: toggleScrollWheel
+                    )
+                    .onAppear {
+                        if state.target == 0 {
+                            state.target = 100
                         }
-                        .listRowSeparator(.hidden, edges: .top)
                     }
                 }
             }

+ 1 - 68
FreeAPS/Sources/Modules/OverrideConfig/View/EditOverrideForm.swift

@@ -320,6 +320,7 @@ struct EditOverrideForm: View {
                 if target_override {
                     let settingsProvider = PickerSettingsProvider.shared
                     let glucoseSetting = PickerSetting(value: 0, step: targetStep, min: 72, max: 270, type: .glucose)
+
                     TargetPicker(
                         label: "Target Glucose",
                         selection: Binding(
@@ -646,71 +647,3 @@ struct EditOverrideForm: View {
         return !toggle
     }
 }
-
-struct TargetPicker: View {
-    let label: String
-    @Binding var selection: Decimal
-    let options: [Decimal]
-    let units: GlucoseUnits
-    @Binding var hasChanges: Bool
-    @Binding var targetStep: Decimal
-    @Binding var displayPickerTarget: Bool
-    var toggleScrollWheel: (_ picker: Bool) -> Bool
-
-    var body: some View {
-        VStack {
-            HStack {
-                Text(label)
-                Spacer()
-                Text(
-                    (units == .mgdL ? selection.description : selection.formattedAsMmolL) + " " + units.rawValue
-                )
-                .foregroundColor(!displayPickerTarget ? .primary : .accentColor)
-            }
-            .onTapGesture {
-                displayPickerTarget = toggleScrollWheel(displayPickerTarget)
-            }
-            if displayPickerTarget {
-                HStack {
-                    // Radio buttons and text on the left side
-                    VStack(alignment: .leading) {
-                        // Radio buttons for step iteration
-                        let stepChoices: [Decimal] = units == .mgdL ? [1, 5] : [1, 9]
-                        ForEach(stepChoices, id: \.self) { step in
-                            let label = (units == .mgdL ? step.description : step.formattedAsMmolL) + " " +
-                                units.rawValue
-                            RadioButton(
-                                isSelected: targetStep == step,
-                                label: label
-                            ) {
-                                targetStep = step
-                                selection = OverrideConfig.StateModel.roundTargetToStep(selection, step)
-                            }
-                            .padding(.top, 10)
-                        }
-                    }
-                    .frame(maxWidth: .infinity)
-
-                    Spacer()
-
-                    // Picker on the right side
-                    Picker(selection: Binding(
-                        get: { OverrideConfig.StateModel.roundTargetToStep(selection, targetStep) },
-                        set: {
-                            selection = $0
-                            hasChanges = true
-                        }
-                    ), label: Text("")) {
-                        ForEach(options, id: \.self) { option in
-                            Text((units == .mgdL ? option.description : option.formattedAsMmolL) + " " + units.rawValue)
-                                .tag(option)
-                        }
-                    }
-                    .pickerStyle(WheelPickerStyle())
-                    .frame(maxWidth: .infinity)
-                }
-                .listRowSeparator(.hidden, edges: .top)
-            }
-        }
-    }
-}

+ 43 - 27
FreeAPS/Sources/Modules/OverrideConfig/View/OverrideRootView.swift

@@ -554,32 +554,46 @@ extension OverrideConfig {
         }
 
         @ViewBuilder private func overridesView(for preset: OverrideStored) -> some View {
-            let duration = (preset.duration ?? 0) as Decimal
+            let isSelected = preset.id == selectedPresetID
             let name = preset.name ?? ""
+            let indefinite = preset.indefinite
+            let duration = preset.duration?.decimalValue ?? Decimal(0)
             let percentage = preset.percentage
-            let perpetual = preset.indefinite
-            let durationString = perpetual ? "" : "\(formatHrMin(Int(duration)))"
-            let scheduledSMBstring = preset.smbIsScheduledOff && preset.start != preset.end
-                ? " \(formatTimeRange(start: preset.start?.stringValue, end: preset.end?.stringValue))"
-                : ""
-            let smbString = (preset.smbIsOff || preset.smbIsScheduledOff) ? "SMBs Off\(scheduledSMBstring)" : ""
-            let targetValue = (preset.target == 0 || preset.target == nil) ? "" :
-                (state.units == .mgdL ? preset.target?.description ?? "" : preset.target?.decimalValue.formattedAsMmolL)
-
-            let targetString = (targetValue?.isEmpty ?? true) ? "" : "\(targetValue!) \(state.units.rawValue)"
-            let maxMinutesSMB = (preset.smbMinutes as Decimal?) != nil ? (preset.smbMinutes ?? 0) as Decimal : 0
-            let maxMinutesUAM = (preset.uamMinutes as Decimal?) != nil ? (preset.uamMinutes ?? 0) as Decimal : 0
-            let maxSmbMinsString = (
-                maxMinutesSMB != 0 && preset.advancedSettings && !preset.smbIsOff && maxMinutesSMB != state
-                    .defaultSmbMinutes
-            ) ?
-                "\(maxMinutesSMB.formatted()) min SMB" : ""
-            let maxUamMinsString = (
-                maxMinutesUAM != 0 && preset.advancedSettings && !preset.smbIsOff && maxMinutesUAM != state
-                    .defaultUamMinutes
-            ) ?
-                "\(maxMinutesUAM.formatted()) min UAM" : ""
-            let isfAndCRstring: String = {
+            let smbMinutes = preset.smbMinutes?.decimalValue ?? Decimal(0)
+            let uamMinutes = preset.uamMinutes?.decimalValue ?? Decimal(0)
+
+            let target: String = {
+                guard let targetValue = preset.target, targetValue != 0 else { return "" }
+                return state.units == .mgdL ? targetValue.description : targetValue.decimalValue.formattedAsMmolL
+            }()
+
+            let targetString = target.isEmpty ? "" : "\(target) \(state.units.rawValue)"
+
+            let durationString = indefinite ? "" : "\(formatHrMin(Int(duration)))"
+
+            let scheduledSMBString: String = {
+                guard preset.smbIsScheduledOff, preset.start != preset.end else { return "" }
+                return " \(formatTimeRange(start: preset.start?.stringValue, end: preset.end?.stringValue))"
+            }()
+
+            let smbString: String = {
+                guard preset.smbIsOff || preset.smbIsScheduledOff else { return "" }
+                return "SMBs Off\(scheduledSMBString)"
+            }()
+
+            let maxSmbMinsString: String = {
+                guard smbMinutes != 0, preset.advancedSettings, !preset.smbIsOff,
+                      smbMinutes != state.defaultSmbMinutes else { return "" }
+                return "\(smbMinutes.formatted()) min SMB"
+            }()
+
+            let maxUamMinsString: String = {
+                guard uamMinutes != 0, preset.advancedSettings, !preset.smbIsOff,
+                      uamMinutes != state.defaultUamMinutes else { return "" }
+                return "\(uamMinutes.formatted()) min UAM"
+            }()
+
+            let isfAndCrString: String = {
                 switch (preset.isfAndCr, preset.isf, preset.cr) {
                 case (_, true, true),
                      (true, _, _):
@@ -592,16 +606,18 @@ extension OverrideConfig {
                     return ""
                 }
             }()
-            let isSelected = preset.id == selectedPresetID
 
+            let percentageString = percentage != 100 ? "\(Int(percentage))%\(isfAndCrString)" : ""
+
+            // Combine all labels into a single array, filtering out empty strings
             let labels: [String] = [
                 durationString,
-                percentage != 100 ? "\(Int(percentage))%\(isfAndCRstring)" : "",
+                percentageString,
                 targetString,
                 smbString,
                 maxSmbMinsString,
                 maxUamMinsString
-            ].filter { !$0.isEmpty } // filter out empty labels
+            ].filter { !$0.isEmpty }
 
             if !name.isEmpty {
                 ZStack(alignment: .trailing) {