Quellcode durchsuchen

Some UI refactoring for glucose simulator and settings

Deniz Cengiz vor 1 Jahr
Ursprung
Commit
98754742c4

+ 12 - 12
Trio/Sources/Localizations/Main/Localizable.xcstrings

@@ -12754,6 +12754,9 @@
         }
       }
     },
+    "±" : {
+
+    },
     "<  3.3 " : {
       "localizations" : {
         "ar" : {
@@ -29272,7 +29275,7 @@
         }
       }
     },
-    "Amplitude: ±%lld mg/dL" : {
+    "Amplitude:" : {
 
     },
     "An example of a Carb Warning is 'Carbs required: 30 g'" : {
@@ -40899,7 +40902,7 @@
         }
       }
     },
-    "Center Value: %lld mg/dL" : {
+    "Center Value:" : {
 
     },
     "CGM" : {
@@ -42120,9 +42123,6 @@
         }
       }
     },
-    "Changes will take effect on the next glucose reading." : {
-
-    },
     "Chart" : {
       "localizations" : {
         "ar" : {
@@ -45387,6 +45387,9 @@
         }
       }
     },
+    "Configuration changes will take effect on the next glucose reading." : {
+
+    },
     "Configure Libre Transmitter" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -112872,7 +112875,7 @@
     "No Temp Target Presets" : {
 
     },
-    "Noise: ±%lld mg/dL" : {
+    "Noise:" : {
 
     },
     "Noisy CGM Target Increase" : {
@@ -122169,7 +122172,7 @@
         }
       }
     },
-    "Period: %lld hours" : {
+    "Period:" : {
 
     },
     "Persist sensordata" : {
@@ -126670,12 +126673,12 @@
     "Random variation added to each reading to simulate real-world sensor noise." : {
 
     },
-    "Range: %lld–%lld mg/dL" : {
+    "Range: %@–%@ %@" : {
       "localizations" : {
         "en" : {
           "stringUnit" : {
             "state" : "new",
-            "value" : "Range: %1$lld–%2$lld mg/dL"
+            "value" : "Range: %1$@–%2$@ %3$@"
           }
         }
       }
@@ -141155,9 +141158,6 @@
         }
       }
     },
-    "Simulator Settings" : {
-
-    },
     "Skip Bolus screen after carbs" : {
       "comment" : "Do you want to show bolus screen after added carbs?",
       "extractionState" : "manual",

+ 205 - 125
Trio/Sources/Modules/CGMSettings/View/CustomCGMOptionsView.swift

@@ -54,8 +54,10 @@ extension CGMSettings {
                     if cgmCurrent.type != .none {
                         if cgmCurrent.type == .nightscout {
                             nightscoutSection
-                        } else {
-                            customCGMSection
+                        } else if cgmCurrent.type == .xdrip {
+                            xDripConfigurationSection
+                        } else if cgmCurrent.type == .simulator {
+                            simulatorConfigurationSection
                         }
 
                         if let appURL = cgmCurrent.type.appURL {
@@ -97,7 +99,7 @@ extension CGMSettings {
                 }
                 .safeAreaInset(
                     edge: .bottom,
-                    spacing: 30
+                    spacing: 0
                 ) {
                     stickyDeleteButton
                 }
@@ -133,7 +135,7 @@ extension CGMSettings {
                                     "To configure your CGM, tap the button below. In the form that opens, enter your Nightscout credentials to connect to your instance." :
                                     "Tap the button below to open your Nightscout instance in your iPhone's default browser."
                             ).font(.footnote)
-                                .foregroundColor(.secondary)
+                                .foregroundStyle(Color.secondary)
                                 .lineLimit(nil)
                                 .padding(.vertical)
                         }
@@ -174,36 +176,30 @@ extension CGMSettings {
             }
         }
 
-        var customCGMSection: some View {
-            Group {
-                Section(
-                    header: Text("Configuration"),
-                    content: {
-                        if cgmCurrent.type == .xdrip {
-                            VStack(alignment: .leading) {
-                                if let cgmTransmitterDeviceAddress = UserDefaults.standard
-                                    .cgmTransmitterDeviceAddress
-                                {
-                                    Text("CGM address :").padding(.top)
-                                    Text(cgmTransmitterDeviceAddress)
-                                } else {
-                                    Text("CGM is not used as heartbeat.").padding(.top)
-                                }
-
-                                HStack(alignment: .center) {
-                                    Text(
-                                        "A heartbeat tells Trio to start a loop cycle. This is required for closed loop."
-                                    )
-                                    .font(.footnote)
-                                    .foregroundColor(.secondary)
-                                    .lineLimit(nil)
-                                    Spacer()
-                                }.padding(.vertical)
-                            }
-                        } else if cgmCurrent.type == .simulator {
-                            simulatorConfigurationSection
+        var xDripConfigurationSection: some View {
+            Section(
+                header: Text("Configuration"),
+                content: {
+                    VStack(alignment: .leading) {
+                        if let cgmTransmitterDeviceAddress = UserDefaults.standard
+                            .cgmTransmitterDeviceAddress
+                        {
+                            Text("CGM address :").padding(.top)
+                            Text(cgmTransmitterDeviceAddress)
+                        } else {
+                            Text("CGM is not used as heartbeat.").padding(.top)
                         }
 
+                        HStack(alignment: .center) {
+                            Text(
+                                "A heartbeat tells Trio to start a loop cycle. This is required for closed loop."
+                            )
+                            .font(.footnote)
+                            .foregroundStyle(Color.secondary)
+                            .lineLimit(nil)
+                            Spacer()
+                        }.padding(.vertical)
+
                         if let link = cgmCurrent.type.externalLink {
                             Button {
                                 UIApplication.shared.open(link, options: [:], completionHandler: nil)
@@ -217,121 +213,205 @@ extension CGMSettings {
                             .frame(maxWidth: .infinity, alignment: .leading)
                         }
                     }
-                ).listRowBackground(Color.chart)
-            }
+                }
+            ).listRowBackground(Color.chart)
         }
 
         var simulatorConfigurationSection: some View {
-            VStack(alignment: .leading, spacing: 16) {
-                Text("Simulator Settings")
-                    .font(.headline)
-                    .padding(.top, 8)
+            Group {
+                Section(
+                    header: Text("Configuration"),
+                    content: {
+                        VStack(alignment: .leading, spacing: 12) {
+                            Text("CGM is not used as heartbeat.").lineLimit(nil)
+                                .padding(.top)
 
-                Toggle(isOn: $produceStaleValues) {
-                    VStack(alignment: .leading) {
-                        Text("Produce Stale Values")
-                    }
-                }
-                .padding(.vertical, 4)
-                .onChange(of: produceStaleValues) { _, newValue in
-                    UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_ProduceStaleValues")
-                }
+                            Text("Glucose trace WILL NOT be affected by any insulin or carb entries.").lineLimit(nil)
+                                .bold()
+                        }
 
-                if !produceStaleValues {
-                    VStack(alignment: .leading, spacing: 8) {
-                        Text("Center Value: \(Int(centerValue)) mg/dL")
-                        Text("The average glucose level around which values will oscillate.")
-                            .font(.caption)
-                            .foregroundColor(.secondary)
-                        Slider(value: $centerValue, in: 80 ... 200, step: 1)
-                            .accentColor(.accentColor)
-                            .onChange(of: centerValue) { _, newValue in
-                                UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_CenterValue")
-                            }
-                    }
+                        VStack(alignment: .leading, spacing: 8) {
+                            Text(
+                                "The simulator creates a wave-like pattern that mimics natural glucose fluctuations throughout the day."
+                            ).lineLimit(nil)
 
-                    VStack(alignment: .leading, spacing: 8) {
-                        Text("Amplitude: ±\(Int(amplitude)) mg/dL")
-                        Text("Range: \(Int(centerValue - amplitude))–\(Int(centerValue + amplitude)) mg/dL")
-                            .font(.subheadline)
-                            .foregroundColor(.secondary)
-                        Text("The maximum deviation from the center value. Higher values create wider swings.")
-                            .font(.caption)
-                            .foregroundColor(.secondary)
-                        Slider(value: $amplitude, in: 10 ... 100, step: 5)
-                            .accentColor(.accentColor)
-                            .onChange(of: amplitude) { _, newValue in
-                                UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_Amplitude")
-                            }
+                            Text("Configuration changes will take effect on the next glucose reading.")
+                                .padding(.bottom).lineLimit(nil)
+                        }.foregroundStyle(Color.secondary).font(.footnote)
                     }
+                ).listRowBackground(Color.chart)
 
-                    VStack(alignment: .leading, spacing: 8) {
-                        Text("Period: \(Int(period / 3600)) hours")
-                        Text("The time it takes to complete one full cycle from high to low and back to high.")
-                            .font(.caption)
-                            .foregroundColor(.secondary)
-                        Slider(value: $period, in: 3600 ... 21600, step: 1800)
-                            .accentColor(.accentColor)
-                            .onChange(of: period) { _, newValue in
-                                UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_Period")
+                Section {
+                    VStack(alignment: .leading, spacing: 10) {
+                        Toggle(isOn: $produceStaleValues) {
+                            VStack(alignment: .leading) {
+                                Text("Produce Stale Values")
                             }
-                    }
+                        }
+                        .padding(.top)
+                        .onChange(of: produceStaleValues) { _, newValue in
+                            UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_ProduceStaleValues")
+                        }
 
-                    VStack(alignment: .leading, spacing: 8) {
-                        Text("Noise: ±\(Int(noiseAmplitude)) mg/dL")
-                        Text("Random variation added to each reading to simulate real-world sensor noise.")
-                            .font(.caption)
-                            .foregroundColor(.secondary)
-                        Slider(value: $noiseAmplitude, in: 0 ... 20, step: 1)
-                            .accentColor(.accentColor)
-                            .onChange(of: noiseAmplitude) { _, newValue in
-                                UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_NoiseAmplitude")
-                            }
+                        Text(
+                            "When stale values are enabled, the simulator will repeatedly output the last generated glucose value."
+                        )
+                        .font(.footnote)
+                        .foregroundStyle(Color.secondary)
+                        .lineLimit(nil)
+                        .padding(.bottom)
                     }
-                } else {
-                    Text("When stale values are enabled, the simulator will repeatedly output the last generated glucose value.")
-                        .font(.caption)
-                        .foregroundColor(.secondary)
-                        .padding(.vertical, 8)
-                }
+                }.listRowBackground(Color.chart)
+
+                if !produceStaleValues {
+                    Section {
+                        VStack(alignment: .leading, spacing: 10) {
+                            HStack {
+                                Text("Center Value:").bold()
+
+                                Spacer()
+
+                                Text(state.units == .mgdL ? centerValue.description : centerValue.formattedAsMmolL).bold()
 
-                Button("Reset to Defaults") {
-                    centerValue = OscillatingGenerator.Defaults.centerValue
-                    amplitude = OscillatingGenerator.Defaults.amplitude
-                    period = OscillatingGenerator.Defaults.period
-                    noiseAmplitude = OscillatingGenerator.Defaults.noiseAmplitude
-                    produceStaleValues = OscillatingGenerator.Defaults.produceStaleValues
-                    saveSimulatorSettings()
+                                Text(state.units.rawValue).foregroundStyle(Color.secondary)
+                            }.padding(.top)
+
+                            Slider(value: $centerValue, in: 80 ... 200, step: 1)
+                                .accentColor(.accentColor)
+                                .onChange(of: centerValue) { _, newValue in
+                                    UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_CenterValue")
+                                }
+                                .padding(.vertical)
+
+                            Text("The average glucose level around which values will oscillate.")
+                                .font(.footnote)
+                                .foregroundStyle(Color.secondary)
+                                .lineLimit(nil)
+                                .padding(.bottom)
+                        }
+                    }.listRowBackground(Color.chart)
+
+                    Section {
+                        VStack(alignment: .leading, spacing: 10) {
+                            HStack {
+                                Text("Amplitude:").bold()
+
+                                Spacer()
+
+                                Text("±")
+                                Text(state.units == .mgdL ? amplitude.description : amplitude.formattedAsMmolL).bold()
+
+                                Text(state.units.rawValue).foregroundStyle(Color.secondary)
+                            }.padding(.top)
+
+                            Slider(value: $amplitude, in: 10 ... 100, step: 5)
+                                .accentColor(.accentColor)
+                                .onChange(of: amplitude) { _, newValue in
+                                    UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_Amplitude")
+                                }
+                                .padding(.vertical)
+
+                            Text(
+                                "Range: \(state.units == .mgdL ? (centerValue - amplitude).description : (centerValue - amplitude).formattedAsMmolL)–\(state.units == .mgdL ? (centerValue + amplitude).description : (centerValue + amplitude).formattedAsMmolL) \(state.units.rawValue)"
+                            )
+                            .bold()
+                            .font(.footnote)
+                            .foregroundStyle(Color.secondary)
+                            .lineLimit(nil)
+
+                            Text("The maximum deviation from the center value. Higher values create wider swings.")
+                                .font(.footnote)
+                                .foregroundStyle(Color.secondary)
+                                .lineLimit(nil)
+                                .padding(.bottom)
+                        }
+                    }.listRowBackground(Color.chart)
+
+                    Section {
+                        VStack(alignment: .leading, spacing: 10) {
+                            HStack {
+                                Text("Period:").bold()
+
+                                Spacer()
+
+                                Text(Int(period / 3600).description).bold()
+
+                                Text("hours").foregroundStyle(Color.secondary)
+                            }.padding(.top)
+
+                            Slider(value: $period, in: 3600 ... 21600, step: 1800)
+                                .accentColor(.accentColor)
+                                .onChange(of: period) { _, newValue in
+                                    UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_Period")
+                                }
+                                .padding(.vertical)
+
+                            Text("The time it takes to complete one full cycle from high to low and back to high.")
+                                .font(.footnote)
+                                .foregroundStyle(Color.secondary)
+                                .lineLimit(nil)
+                                .padding(.bottom)
+                        }
+                    }.listRowBackground(Color.chart)
+
+                    Section {
+                        VStack(alignment: .leading, spacing: 10) {
+                            HStack {
+                                Text("Noise:").bold()
+
+                                Spacer()
+
+                                Text("±")
+
+                                Text(state.units == .mgdL ? noiseAmplitude.description : noiseAmplitude.formattedAsMmolL).bold()
+
+                                Text(state.units.rawValue).foregroundStyle(Color.secondary)
+                            }.padding(.top)
+
+                            Slider(value: $noiseAmplitude, in: 0 ... 20, step: 1)
+                                .accentColor(.accentColor)
+                                .onChange(of: noiseAmplitude) { _, newValue in
+                                    UserDefaults.standard.set(newValue, forKey: "GlucoseSimulator_NoiseAmplitude")
+                                }
+                                .padding(.vertical)
+
+                            Text("Random variation added to each reading to simulate real-world sensor noise.")
+                                .font(.footnote)
+                                .foregroundStyle(Color.secondary)
+                                .lineLimit(nil)
+                                .padding(.bottom)
+                        }
+                    }.listRowBackground(Color.chart)
                 }
-                .buttonStyle(.bordered)
-                .padding(.top, 8)
-
-                Text("Changes will take effect on the next glucose reading.")
-                    .font(.caption)
-                    .foregroundColor(.secondary)
-                    .padding(.top, 4)
-
-                Text("Glucose trace WILL NOT be affected by any insulin or carb entries.")
-                    .font(.caption)
-                    .foregroundColor(.secondary)
-                    .padding(.top, 4)
-
-                Text("The simulator creates a wave-like pattern that mimics natural glucose fluctuations throughout the day.")
-                    .font(.caption)
-                    .foregroundColor(.secondary)
-                    .padding(.top, 4)
-            }
-            .padding(.vertical, 8)
+
+                Section {
+                    Button(action: {
+                        centerValue = OscillatingGenerator.Defaults.centerValue
+                        amplitude = OscillatingGenerator.Defaults.amplitude
+                        period = OscillatingGenerator.Defaults.period
+                        noiseAmplitude = OscillatingGenerator.Defaults.noiseAmplitude
+                        produceStaleValues = OscillatingGenerator.Defaults.produceStaleValues
+                        saveSimulatorSettings()
+                    }, label: {
+                        Text("Reset to Defaults")
+
+                    })
+                        .frame(maxWidth: .infinity, alignment: .center)
+                        .tint(.white)
+                }.listRowBackground(Color.accentColor)
+
+            }.listSectionSpacing(sectionSpacing)
         }
 
         var stickyDeleteButton: some View {
             ZStack {
                 Rectangle()
-                    .frame(width: UIScreen.main.bounds.width, height: 65)
+                    .frame(width: UIScreen.main.bounds.width, height: 120)
                     .foregroundStyle(colorScheme == .dark ? Color.bgDarkerDarkBlue : Color.white)
                     .background(.thinMaterial)
                     .opacity(0.8)
                     .clipShape(Rectangle())
+                    .padding(.bottom, -55)
 
                 Button(action: {
                     shouldDisplayDeletionConfirmation.toggle()