Browse Source

Avoid text clipping; add glossary help sheet for tags

Deniz Cengiz 1 year ago
parent
commit
79dcf110a2

+ 8 - 4
FreeAPS.xcodeproj/project.pbxproj

@@ -455,6 +455,7 @@
 		DD1745522C55CA5D00211FAC /* UnitsLimitsSettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745512C55CA5D00211FAC /* UnitsLimitsSettingsStateModel.swift */; };
 		DD1745552C55CA6C00211FAC /* UnitsLimitsSettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745542C55CA6C00211FAC /* UnitsLimitsSettingsRootView.swift */; };
 		DD1DB7CC2BECCA1F0048B367 /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */; };
+		DD1E53592D273F26008F32A4 /* LoopStatusHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1E53582D273F20008F32A4 /* LoopStatusHelpView.swift */; };
 		DD21FCB52C6952AD00AF2C25 /* DecimalPickerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD21FCB42C6952AD00AF2C25 /* DecimalPickerSettings.swift */; };
 		DD32CF982CC82463003686D6 /* TrioRemoteControl+Bolus.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD32CF972CC82460003686D6 /* TrioRemoteControl+Bolus.swift */; };
 		DD32CF9A2CC8247B003686D6 /* TrioRemoteControl+Meal.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD32CF992CC8246F003686D6 /* TrioRemoteControl+Meal.swift */; };
@@ -483,10 +484,10 @@
 		DD9ECB712CA9A0BA00AA7C45 /* RemoteControlConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ECB6E2CA9A0BA00AA7C45 /* RemoteControlConfigProvider.swift */; };
 		DD9ECB722CA9A0BA00AA7C45 /* RemoteControlConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ECB6F2CA9A0BA00AA7C45 /* RemoteControlConfigDataFlow.swift */; };
 		DD9ECB742CA9A0C300AA7C45 /* RemoteControlConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ECB732CA9A0C300AA7C45 /* RemoteControlConfig.swift */; };
-		DDA6E3202D258E0500C2988C /* OverrideHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */; };
-		DDA6E3222D25901100C2988C /* TempTargetHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */; };
 		DDA6E2502D22187500C2988C /* ChartLegendView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E24F2D22187500C2988C /* ChartLegendView.swift */; };
 		DDA6E2852D2361F800C2988C /* LoopStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E2842D2361F800C2988C /* LoopStatusView.swift */; };
+		DDA6E3202D258E0500C2988C /* OverrideHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */; };
+		DDA6E3222D25901100C2988C /* TempTargetHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */; };
 		DDA6E3572D25988500C2988C /* ContactImageHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E3562D25988500C2988C /* ContactImageHelpView.swift */; };
 		DDB37CC52D05048F00D99BF4 /* ContactImageStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB37CC42D05048F00D99BF4 /* ContactImageStorage.swift */; };
 		DDB37CC72D05127500D99BF4 /* FontExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB37CC62D05127500D99BF4 /* FontExtensions.swift */; };
@@ -1162,6 +1163,7 @@
 		DD1745512C55CA5D00211FAC /* UnitsLimitsSettingsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsLimitsSettingsStateModel.swift; sourceTree = "<group>"; };
 		DD1745542C55CA6C00211FAC /* UnitsLimitsSettingsRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsLimitsSettingsRootView.swift; sourceTree = "<group>"; };
 		DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildDetails.swift; sourceTree = "<group>"; };
+		DD1E53582D273F20008F32A4 /* LoopStatusHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopStatusHelpView.swift; sourceTree = "<group>"; };
 		DD21FCB42C6952AD00AF2C25 /* DecimalPickerSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecimalPickerSettings.swift; sourceTree = "<group>"; };
 		DD32CF972CC82460003686D6 /* TrioRemoteControl+Bolus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TrioRemoteControl+Bolus.swift"; sourceTree = "<group>"; };
 		DD32CF992CC8246F003686D6 /* TrioRemoteControl+Meal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TrioRemoteControl+Meal.swift"; sourceTree = "<group>"; };
@@ -1190,10 +1192,10 @@
 		DD9ECB6E2CA9A0BA00AA7C45 /* RemoteControlConfigProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteControlConfigProvider.swift; sourceTree = "<group>"; };
 		DD9ECB6F2CA9A0BA00AA7C45 /* RemoteControlConfigDataFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteControlConfigDataFlow.swift; sourceTree = "<group>"; };
 		DD9ECB732CA9A0C300AA7C45 /* RemoteControlConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteControlConfig.swift; sourceTree = "<group>"; };
-		DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideHelpView.swift; sourceTree = "<group>"; };
-		DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetHelpView.swift; sourceTree = "<group>"; };
 		DDA6E24F2D22187500C2988C /* ChartLegendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartLegendView.swift; sourceTree = "<group>"; };
 		DDA6E2842D2361F800C2988C /* LoopStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopStatusView.swift; sourceTree = "<group>"; };
+		DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideHelpView.swift; sourceTree = "<group>"; };
+		DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetHelpView.swift; sourceTree = "<group>"; };
 		DDA6E3562D25988500C2988C /* ContactImageHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactImageHelpView.swift; sourceTree = "<group>"; };
 		DDB37CC22D05044D00D99BF4 /* ContactTrickEntryStored+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContactTrickEntryStored+CoreDataClass.swift"; sourceTree = "<group>"; };
 		DDB37CC32D05044D00D99BF4 /* ContactTrickEntryStored+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContactTrickEntryStored+CoreDataProperties.swift"; sourceTree = "<group>"; };
@@ -1900,6 +1902,7 @@
 		3833B51F260264B6003021B3 /* Header */ = {
 			isa = PBXGroup;
 			children = (
+				DD1E53582D273F20008F32A4 /* LoopStatusHelpView.swift */,
 				DDA6E2842D2361F800C2988C /* LoopStatusView.swift */,
 				383420D525FFE38C002D46C1 /* LoopView.swift */,
 				38AAF85425FFF846004AF583 /* CurrentGlucoseView.swift */,
@@ -3737,6 +3740,7 @@
 				F90692AA274B7AAE0037068D /* HealthKitManager.swift in Sources */,
 				38887CCE25F5725200944304 /* IOBEntry.swift in Sources */,
 				38E98A2425F52C9300C0CED0 /* Logger.swift in Sources */,
+				DD1E53592D273F26008F32A4 /* LoopStatusHelpView.swift in Sources */,
 				CA370FC152BC98B3D1832968 /* BasalProfileEditorRootView.swift in Sources */,
 				195D80BB2AF6980B00D25097 /* DynamicSettingsStateModel.swift in Sources */,
 				E00EEC0327368630002FF094 /* ServiceAssembly.swift in Sources */,

+ 248 - 0
FreeAPS/Sources/Modules/Home/View/Header/LoopStatusHelpView.swift

@@ -0,0 +1,248 @@
+import SwiftUI
+
+struct LoopStatusHelpView: View {
+    @Environment(AppState.self) var appState
+    @Environment(\.colorScheme) var colorScheme
+
+    var state: Home.StateModel
+    var helpSheetDetent: Binding<PresentationDetent>
+    var isHelpSheetPresented: Binding<Bool>
+
+    var body: some View {
+        NavigationStack {
+            VStack(alignment: .leading) {
+                Text(
+                    "The oref algorithm provides recommendations, showing key variables, decisions on temporary basal rates or super-micro-boluses, and a 'reason' field explaining its actions. Find all key terms of this 'reason' explained below:"
+                )
+                .font(.subheadline)
+                .foregroundColor(.secondary)
+                .padding(.top, 50)
+
+                List {
+                    DefinitionRow(
+                        term: "Autosens Ratio",
+                        definition: Text(
+                            "The ratio of how sensitive or resistant to insulin you are in the current loop cycle. Baseline = 1.0, Sensitive < 1.0, Resistant > 1.0"
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "ISF",
+                        definition: Text(
+                            "The first value is your profile Insulin Sensitivity Factor (ISF). The second value, after the arrow, is your adjusted ISF used for the most recent automated dosing calculation."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "COB",
+                        definition: Text(
+                            "Amount of Carbs on Board (COB) used in the most recent automated dosing calculation."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Dev",
+                        definition: Text(
+                            "Abbreviation for 'Deviation'. How much the actual glucose change deviated from the BGI."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "BGI",
+                        definition: Text(
+                            "The degree to which your glucose should be rising or falling based solely on insulin activity."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "CR",
+                        definition: Text(
+                            "The first value is your profile Carb Ratio (CR). The second value, after the arrow, is your adjusted CR used for the most recent automated dosing calculation."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Target",
+                        definition: Text(
+                            "The first value is your target glucose from your settings. The second value, after the arrow, is your adjusted target glucose used for the most recent automated dosing calculation. A second value is shown if you have a temp target, override, or one of the Target Behavior options enabled."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "minPredBG",
+                        definition: Text(
+                            "The lowest forecasted value that Trio has estimated for your future glucose."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "minGuardBG",
+                        definition: Text(
+                            "The lowest forecasted glucose during the remaining duration of insulin action (DIA)."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "IOBpredBG",
+                        definition: Text(
+                            "The forecasted glucose value in 4 hours calculated based on IOB only."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "COBpredBG",
+                        definition: Text(
+                            "The forecasted glucose value in 4 hours calculated based on current IOB and COB."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "UAMpredBG",
+                        definition: Text(
+                            "The forecasted glucose value in 4 hours based on current deviations ramping down to zero at the same rate they have been recently."
+                        ),
+                        color: .insulin
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "TDD",
+                        definition: Text(
+                            "Abbreviation for 'Total Daily Dose'. Last 24 hours of total insulin administered, both basal and bolus."
+                        ),
+                        color: .zt
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Bolus/Basal %",
+                        definition: Text(
+                            "Of the total insulin delivered in the past 24 hours, this indicates what percentage was administered through basals and what was given through bolus."
+                        ),
+                        color: .green
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Dynamic ISF/CR",
+                        definition: Text(
+                            "A display of On/On indicates both Dynamic ISF and CR are enabled. On/Off indicates only Dynamic ISF is enabled. Dynamic CR cannot be enabled when Dynamic ISF is disabled."
+                        ),
+                        color: .zt
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Sigmoid function",
+                        definition: Text("If shown, Sigmoid Dynamic ISF is enabled."),
+                        color: .zt
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Logarithmic formula",
+                        definition: Text("If shown, Logarithmic Dynamic ISF is enabled."),
+                        color: .zt
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "AF",
+                        definition: Text(
+                            "Displays the Adjustment Factor (AF) for either Logathmic or Sigmoid Dynamic ISF in use."
+                        ),
+                        color: .zt
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "SMB Ratio",
+                        definition: Text(
+                            "SMB Delivery Ratio of calculated insulin required that is given as SMB."
+                        ),
+                        color: .zt
+                    ).listRowBackground(Color.gray.opacity(0.1))
+
+                    DefinitionRow(
+                        term: "Smoothing",
+                        definition: Text("Indicates glucose smoothing is enabled."),
+                        color: .gray
+                    ).listRowBackground(Color.gray.opacity(0.1))
+                }
+                .scrollContentBackground(.hidden)
+                .navigationBarTitle("Glossary", displayMode: .inline)
+                .padding(.bottom, 15)
+
+                Button {
+                    isHelpSheetPresented.wrappedValue.toggle()
+                } label: {
+                    Text("Got it!").bold().frame(maxWidth: .infinity, minHeight: 30, alignment: .center)
+                }
+                .buttonStyle(.bordered)
+                .padding(.top)
+            }
+            .padding([.horizontal, .bottom])
+            .listSectionSpacing(10)
+            .ignoresSafeArea(edges: .top)
+            .presentationDetents(
+                [.fraction(0.9), .large],
+                selection: helpSheetDetent
+            )
+        }
+    }
+
+    var legendLinesView: some View {
+        Group {
+            DefinitionRow(
+                term: "IOB (Insulin on Board)",
+                definition: Text(
+                    "Forecasts future glucose readings based on the amount of insulin still active in the body."
+                ),
+                color: .insulin
+            )
+
+            DefinitionRow(
+                term: "ZT (Zero-Temp)",
+                definition: Text(
+                    "Forecasts the worst-case future glucose reading scenario if no carbs are absorbed and insulin delivery is stopped until glucose starts rising."
+                ),
+                color: .zt
+            )
+
+            DefinitionRow(
+                term: "COB (Carbs on Board)",
+                definition: Text(
+                    "Forecasts future glucose reading changes by considering the amount of carbohydrates still being absorbed in the body."
+                ),
+                color: .loopYellow
+            )
+
+            DefinitionRow(
+                term: "UAM (Unannounced Meal)",
+                definition: Text(
+                    "Forecasts future glucose levels and insulin dosing needs for unexpected meals or other causes of glucose reading increases without prior notice."
+                ),
+                color: .uam
+            )
+        }
+    }
+
+    var legendConeOfUncertaintyView: some View {
+        DefinitionRow(
+            term: "Cone of Uncertainty",
+            definition: VStack(alignment: .leading, spacing: 10) {
+                Text(
+                    "For simplicity reasons, oref's various forecast curves are displayed as a \"Cone of Uncertainty\" that depicts a possible, forecasted range of future glucose fluctuation based on the current data and the algothim's result."
+                )
+                Text(
+                    "To modify how the forecast is displayed, go to Settings > Features > User Interface > Forecast Display Type."
+                )
+            },
+            color: Color.blue.opacity(0.5)
+        )
+    }
+}

+ 11 - 18
FreeAPS/Sources/Modules/Home/View/Header/LoopStatusView.swift

@@ -7,11 +7,12 @@ struct LoopStatusView: View {
     var state: Home.StateModel
 
     @State var sheetDetent = PresentationDetent.fraction(0.8)
-    @State private var statusTitle: String = ""
     // Help Sheet
     @State var isHelpSheetPresented: Bool = false
     @State var helpSheetDetent = PresentationDetent.fraction(0.9)
 
+    @State private var statusTitle: String = ""
+
     var body: some View {
         NavigationStack {
             VStack(alignment: .leading, spacing: 10) {
@@ -52,6 +53,9 @@ struct LoopStatusView: View {
                             "Trio is currently using these metrics and values as determined by the oref algorithm:"
                         )
                         .font(.subheadline)
+                        .lineLimit(nil)
+                        .multilineTextAlignment(.leading)
+                        .fixedSize(horizontal: false, vertical: true)
 
                         let tags = !state.isSmoothingEnabled ? determination.reasonParts : determination
                             .reasonParts + ["Smoothing: On"]
@@ -68,7 +72,11 @@ struct LoopStatusView: View {
                                     determination.reasonConclusion,
                                     isMmolL: state.units == .mmolL
                                 )
-                        ).font(.subheadline)
+                        )
+                        .font(.subheadline)
+                        .lineLimit(nil)
+                        .multilineTextAlignment(.leading)
+                        .fixedSize(horizontal: false, vertical: true)
                     }
                 } else {
                     Text("No recent oref algorithm determination.")
@@ -108,22 +116,7 @@ struct LoopStatusView: View {
                 setStatusTitle()
             }
             .sheet(isPresented: $isHelpSheetPresented) {
-                NavigationStack {
-                    List {
-                        DefinitionRow(term: "Placeholder for Algo Term", definition: Text("Lorem Ipsum Dolor Sit Amet"))
-                    }
-                    .navigationBarTitle("Help", displayMode: .inline)
-
-                    Button { isHelpSheetPresented.toggle() }
-                    label: { Text("Got it!").bold().frame(maxWidth: .infinity, minHeight: 30, alignment: .center) }
-                        .buttonStyle(.bordered)
-                        .padding(.top)
-                }
-                .padding()
-                .presentationDetents(
-                    [.fraction(0.9), .large],
-                    selection: $helpSheetDetent
-                ).scrollContentBackground(.hidden)
+                LoopStatusHelpView(state: state, helpSheetDetent: $helpSheetDetent, isHelpSheetPresented: $isHelpSheetPresented)
             }
         }
         .scrollContentBackground(.hidden)