Просмотр исходного кода

Merge branch 'settings-update' into sync-upstream

Deniz Cengiz 1 год назад
Родитель
Сommit
12b10f58b9
32 измененных файлов с 1420 добавлено и 494 удалено
  1. 10 10
      FreeAPS.xcodeproj/project.pbxproj
  2. 171 81
      FreeAPS/Sources/Modules/AlgorithmAdvancedSettings/View/AlgorithmAdvancedSettingsRootView.swift
  3. 63 20
      FreeAPS/Sources/Modules/AutosensSettings/View/AutosensSettingsRootView.swift
  4. 18 8
      FreeAPS/Sources/Modules/AutotuneConfig/View/AutotuneConfigRootView.swift
  5. 4 4
      FreeAPS/Sources/Modules/BasalProfileEditor/BasalProfileEditorStateModel.swift
  6. 67 19
      FreeAPS/Sources/Modules/BolusCalculatorConfig/View/BolusCalculatorConfigRootView.swift
  7. 34 9
      FreeAPS/Sources/Modules/CGM/View/CGMRootView.swift
  8. 42 11
      FreeAPS/Sources/Modules/CalendarEventSettings/View/CalendarEventSettingsRootView.swift
  9. 173 32
      FreeAPS/Sources/Modules/DynamicSettings/View/DynamicSettingsRootView.swift
  10. 65 20
      FreeAPS/Sources/Modules/GeneralSettings/View/UnitsLimitsSettingsRootView.swift
  11. 60 16
      FreeAPS/Sources/Modules/GlucoseNotificationSettings/View/GlucoseNotificationSettingsRootView.swift
  12. 21 13
      FreeAPS/Sources/Modules/HealthKit/View/AppleHealthKitRootView.swift
  13. 13 5
      FreeAPS/Sources/Modules/Home/View/HomeRootView.swift
  14. 39 6
      FreeAPS/Sources/Modules/LiveActivitySettings/View/LiveActivitySettingsRootView.swift
  15. 145 40
      FreeAPS/Sources/Modules/MealSettings/View/MealSettingsRootView.swift
  16. 34 7
      FreeAPS/Sources/Modules/NightscoutConfig/View/NightscoutConfigRootView.swift
  17. 24 8
      FreeAPS/Sources/Modules/NightscoutConfig/View/NightscoutFetchView.swift
  18. 22 8
      FreeAPS/Sources/Modules/NightscoutConfig/View/NightscoutUploadView.swift
  19. 17 5
      FreeAPS/Sources/Modules/NightscoutConfig/View/ProfileImport/ReviewInsulinActionView.swift
  20. 3 4
      FreeAPS/Sources/Modules/PumpConfig/View/PumpConfigRootView.swift
  21. 16 5
      FreeAPS/Sources/Modules/RemoteControlConfig/View/RemoteControlConfig.swift
  22. 221 76
      FreeAPS/Sources/Modules/SMBSettings/View/SMBSettingsRootView.swift
  23. 11 4
      FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift
  24. 3 1
      FreeAPS/Sources/Modules/Settings/View/TidepoolStartView.swift
  25. 14 5
      FreeAPS/Sources/Modules/ShortcutsConfig/View/ShortcutsConfigView.swift
  26. 84 40
      FreeAPS/Sources/Modules/TargetBehavoir/View/TargetBehavoirRootView.swift
  27. 27 18
      FreeAPS/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift
  28. 7 7
      FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigAppleWatchView.swift
  29. 3 3
      FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigGarminView.swift
  30. 3 3
      FreeAPS/Sources/Views/DefinitionRow.swift
  31. 2 2
      FreeAPS/Sources/Views/SettingInputHintView.swift
  32. 4 4
      FreeAPS/Sources/Views/SettingInputSection.swift

+ 10 - 10
FreeAPS.xcodeproj/project.pbxproj

@@ -3999,7 +3999,7 @@
 				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
 				DEVELOPER_TEAM = "$(DEVELOPER_TEAM)";
 				DEVELOPMENT_ASSET_PATHS = "";
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				ENABLE_PREVIEWS = YES;
 				INFOPLIST_FILE = FreeAPS/Resources/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 17.0;
@@ -4040,7 +4040,7 @@
 				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
 				DEVELOPER_TEAM = "$(DEVELOPER_TEAM)";
 				DEVELOPMENT_ASSET_PATHS = "";
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				ENABLE_PREVIEWS = YES;
 				INFOPLIST_FILE = FreeAPS/Resources/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 17.0;
@@ -4083,7 +4083,7 @@
 				CODE_SIGN_ENTITLEMENTS = FreeAPSWatch/FreeAPSWatch.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				GENERATE_INFOPLIST_FILE = YES;
 				IBSC_MODULE = FreeAPSWatch_WatchKit_Extension;
 				INFOPLIST_FILE = FreeAPSWatch/Info.plist;
@@ -4121,7 +4121,7 @@
 				CODE_SIGN_ENTITLEMENTS = FreeAPSWatch/FreeAPSWatch.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				GENERATE_INFOPLIST_FILE = YES;
 				IBSC_MODULE = FreeAPSWatch_WatchKit_Extension;
 				INFOPLIST_FILE = FreeAPSWatch/Info.plist;
@@ -4152,7 +4152,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
 				DEVELOPMENT_ASSET_PATHS = "\"FreeAPSWatch WatchKit Extension/Preview Content\"";
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "FreeAPSWatch WatchKit Extension/Info.plist";
@@ -4192,7 +4192,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
 				DEVELOPMENT_ASSET_PATHS = "\"FreeAPSWatch WatchKit Extension/Preview Content\"";
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "FreeAPSWatch WatchKit Extension/Info.plist";
@@ -4226,7 +4226,7 @@
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				INFOPLIST_FILE = FreeAPSTests/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 17.0;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -4247,7 +4247,7 @@
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				INFOPLIST_FILE = FreeAPSTests/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 17.0;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -4272,7 +4272,7 @@
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				ENABLE_USER_SCRIPT_SANDBOXING = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu17;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -4306,7 +4306,7 @@
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
+				DEVELOPMENT_TEAM = 54D5ZWZGJG;
 				ENABLE_USER_SCRIPT_SANDBOXING = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu17;
 				GENERATE_INFOPLIST_FILE = YES;

+ 171 - 81
FreeAPS/Sources/Modules/AlgorithmAdvancedSettings/View/AlgorithmAdvancedSettingsRootView.swift

@@ -7,7 +7,7 @@ extension AlgorithmAdvancedSettings {
         @State var state = StateModel()
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -39,7 +39,7 @@ extension AlgorithmAdvancedSettings {
                     content: {
                         VStack(alignment: .leading) {
                             Text(
-                                "The settings in this section are designed for advanced expert users and typically do not require ANY modifications."
+                                "The settings in this section typically do not require ANY modifications. Do not alter them without a solid understanding of what you are changing and the full impact it will have on the algorithm."
                             ).bold()
                         }
                     }
@@ -53,18 +53,25 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Max Daily Safety Multiplier", comment: "Max Daily Safety Multiplier")
                         }
                     ),
                     units: state.units,
                     type: .decimal("maxDailySafetyMultiplier"),
                     label: NSLocalizedString("Max Daily Safety Multiplier", comment: "Max Daily Safety Multiplier"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This is an important OpenAPS safety limit. The default setting (which is unlikely to need adjusting) is 3. This means that OpenAPS will never be allowed to set a temporary basal rate that is more than 3x the highest hourly basal rate programmed in a user’s pump, or, if enabled, determined by autotune.",
-                        comment: "Max Daily Safety Multiplier"
-                    )
+                    miniHint: """
+                    Temporary basal rates cannot be set higher than this percentage of your LARGEST profile basal rate
+                    Default setting: 300%
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: 300%").bold()
+                        Text(
+                            "This limits the automatic adjustment of the temporary basal rate to this value times the highest scheduled basal rate in your basal profile."
+                        )
+                        Text("Note: If Autotune is enabled, Trio uses Autotune basals instead of scheduled basals.").italic()
+                        Text("Warning: Increasing this setting is not advised.").bold().italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -74,7 +81,7 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString(
                                 "Current Basal Safety Multiplier",
                                 comment: "Current Basal Safety Multiplier"
@@ -84,11 +91,18 @@ extension AlgorithmAdvancedSettings {
                     units: state.units,
                     type: .decimal("currentBasalSafetyMultiplier"),
                     label: NSLocalizedString("Current Basal Safety Multiplier", comment: "Current Basal Safety Multiplier"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This is another important OpenAPS safety limit. The default setting (which is also unlikely to need adjusting) is 4. This means that OpenAPS will never be allowed to set a temporary basal rate that is more than 4x the current hourly basal rate programmed in a user’s pump, or, if enabled, determined by autotune.",
-                        comment: "Current Basal Safety Multiplier"
-                    )
+                    miniHint: """
+                    Temporary basal rates cannot be set higher than this percentage of the profile basal rate at the time of the loop cycle
+                    Default: 400%
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: 400%").bold()
+                        Text(
+                            "This limits the automatic adjustment of the temporary basal rate to this percentage of the current hourly basal rate at the time of the loop cycle."
+                        )
+                        Text("Note: If Autotune is enabled, Trio uses Autotune basals instead of scheduled basals.").italic()
+                        Text("Warning: Increasing this setting is not advised.").bold().italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -98,15 +112,24 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Duration of Insulin Action"
                         }
                     ),
                     units: state.units,
                     type: .decimal("dia"),
                     label: "Duration of Insulin Action",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Duration of Insulin Action… bla bla bla"
+                    miniHint: """
+                    Number of hours insulin is active in your body
+                    Default: 6 hours
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: 6 hours").bold()
+                        Text("Number of hours insulin will contribute to IOB after dosing.")
+                        Text("Tip: It is better to use Custom Peak Time rather than adjust your Duration of Insulin Action (DIA)")
+                            .italic()
+                        Text("Warning: Decreasing this setting is not advised.").bold().italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -116,7 +139,7 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Use Custom Peak Time", comment: "Use Custom Peak Time")
                         }
                     ),
@@ -124,13 +147,19 @@ extension AlgorithmAdvancedSettings {
                     type: .conditionalDecimal("insulinPeakTime"),
                     label: NSLocalizedString("Use Custom Peak Time", comment: "Use Custom Peak Time"),
                     conditionalLabel: NSLocalizedString("Insulin Peak Time", comment: "Insulin Peak Time"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Defaults to false. Setting to true allows changing insulinPeakTime", comment: "Use Custom Peak Time"
-                    ) + NSLocalizedString(
-                        "Time of maximum blood glucose lowering effect of insulin, in minutes. Beware: Oref assumes for ultra-rapid (Lyumjev) & rapid-acting (Fiasp) curves minimal (35 & 50 min) and maximal (100 & 120 min) applicable insulinPeakTimes. Using a custom insulinPeakTime outside these bounds will result in issues with Trio, longer loop calculations and possible red loops.",
-                        comment: "Insulin Peak Time"
-                    )
+                    miniHint: """
+                    Time that insulin effect is at it’s highest. Set in minutes since injection.
+                    Default: (Set by Insulin Type)
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: Set by Insulin Type").bold()
+                        Text("Time of maximum glucose lowering effect of insulin. Set in minutes since insulin administration.")
+                        VStack(alignment: .leading) {
+                            Text("System-Determined Defaults:").bold()
+                            Text("𝑼𝒍𝒕𝒓𝒂-𝑹𝒂𝒑𝒊𝒅: 55 minutes (permitted range 35-100 minutes)")
+                            Text("𝑹𝒂𝒑𝒊𝒅-𝑨𝒄𝒕𝒊𝒏𝒈: 75 minutes (permitted range 50-120 minutes)")
+                        }
+                    }
                 )
 
                 SettingInputSection(
@@ -140,18 +169,26 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Skip Neutral Temps", comment: "Skip Neutral Temps")
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString("Skip Neutral Temps", comment: "Skip Neutral Temps"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Defaults to false, so that Trio will set temps whenever it can, so it will be easier to see if the system is working, even when you are offline. This means Trio will set a “neutral” temp (same as your default basal) if no adjustments are needed. This is an old setting for OpenAPS to have the options to minimise sounds and notifications from the 'rig', that may wake you up during the night.",
-                        comment: "Skip Neutral Temps"
-                    )
+                    miniHint: """
+                    When on, Trio will not send a temp basal command to the pump if the determined basal rate is the same as the scheduled basal
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        When enabled, Trio will skip neutral temp basals (those that are the same as your default basal), if no adjustments are needed. 
+
+                        When off, Trio will set temps whenever it can, so it will be easier to see if the system is working.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -161,18 +198,26 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Unsuspend If No Temp", comment: "Unsuspend If No Temp")
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString("Unsuspend If No Temp", comment: "Unsuspend If No Temp"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Many people occasionally forget to resume / unsuspend their pump after reconnecting it. If you’re one of them, and you are willing to reliably set a zero temp basal whenever suspending and disconnecting your pump, this feature has your back. If enabled, it will automatically resume / unsuspend the pump if you forget to do so before your zero temp expires. As long as the zero temp is still running, it will leave the pump suspended.",
-                        comment: "Unsuspend If No Temp"
-                    )
+                    miniHint: """
+                    Automatically resume your insulin pump if you forget to unsuspend it after a zero temp basal expires
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Many people occasionally forget to resume / unsuspend their pump after reconnecting it. If you’re one of them, and you are willing to reliably set a zero temp basal whenever suspending and disconnecting your pump, this feature has your back. If enabled, it will automatically resume / unsuspend the pump if you forget to do so before your zero temp expires. As long as the zero temp is still running, it will leave the pump suspended.
+
+                        """)
+                        Text("Applies only to pumps with manual suspend options").italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -182,18 +227,26 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Suspend Zeros IOB", comment: "Suspend Zeros IOB")
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString("Suspend Zeros IOB", comment: "Suspend Zeros IOB"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Default is false. Any existing temp basals during times the pump was suspended will be deleted and 0 temp basals to negate the profile basal rates during times pump is suspended will be added.",
-                        comment: "Suspend Zeros IOB"
-                    )
+                    miniHint: """
+                    Replaces any enacted temp basals prior to a pump suspend with a zero temp basal
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Any existing temp basals during times the pump was suspended will be deleted and zero temp basals to negate the profile basal rates during times pump is suspended will be added.
+
+                        """)
+                        Text("Applies to only to pumps with manual suspend options").italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -203,20 +256,25 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString(
-                                "Autotune ISF Adjustment Fraction",
-                                comment: "Autotune ISF Adjustment Fraction"
+                                "Autotune ISF Adjustment Percent",
+                                comment: "Autotune ISF Adjustment Percent"
                             )
                         }
                     ),
                     units: state.units,
                     type: .decimal("autotuneISFAdjustmentFraction"),
-                    label: NSLocalizedString("Autotune ISF Adjustment Fraction", comment: "Autotune ISF Adjustment Fraction"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "The default of 0.5 for this value keeps autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 1.0 allows full adjustment, 0 is no adjustment from pump ISF.",
-                        comment: "Autotune ISF Adjustment Fraction"
+                    label: NSLocalizedString("Autotune ISF Adjustment Percent", comment: "Autotune ISF Adjustment Percent"),
+                    miniHint: """
+                    Using Autotune is not advised
+                    Default: 50%
+                    """,
+                    verboseHint: Text(
+                        NSLocalizedString(
+                            "The default of 50% for this value keeps autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 100% allows full adjustment, 0% is no adjustment from pump ISF.",
+                            comment: "Autotune ISF Adjustment Percent"
+                        )
                     )
                 )
 
@@ -227,18 +285,28 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
-                            hintLabel = NSLocalizedString("Min 5m Carbimpact", comment: "Min 5m Carbimpact")
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = NSLocalizedString("Min 5m Carb Impact", comment: "Min 5m Carb Impact")
                         }
                     ),
                     units: state.units,
                     type: .decimal("min5mCarbimpact"),
-                    label: NSLocalizedString("Min 5m Carbimpact", comment: "Min 5m Carbimpact"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This is a setting for default carb absorption impact per 5 minutes. The default is an expected 8 mg/dL/5min. This affects how fast COB is decayed in situations when carb absorption is not visible in BG deviations. The default of 8 mg/dL/5min corresponds to a minimum carb absorption rate of 24g/hr at a CSF of 4 mg/dL/g.",
-                        comment: "Min 5m Carbimpact"
-                    )
+                    label: NSLocalizedString("Min 5m Carb Impact", comment: "Min 5m Carb Impact"),
+                    miniHint: """
+                    Set the default rate of carb absorption when no clear impact on blood glucose is visible
+                    Default: 8 mg/dL/5min
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 8 mg/dL/5min").bold()
+                        Text("""
+
+                        The Min 5m Carbimpact setting determines the default expected glucose rise (in mg/dL) over a 5-minute period from carbs when the system cannot detect clear absorption from your blood glucose levels. 
+
+                        The default value of 8 mg/dL per 5 minutes corresponds to an absorption rate of 24g of carbs per hour. 
+
+                        This setting helps the system estimate how much glucose your body is absorbing, even when it’s not immediately visible in your glucose data, ensuring more accurate insulin dosing during carb absorption.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -248,18 +316,24 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
-                            hintLabel = NSLocalizedString("Remaining Carbs Fraction", comment: "Remaining Carbs Fraction")
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = NSLocalizedString("Remaining Carbs Percentage", comment: "Remaining Carbs Percentage")
                         }
                     ),
                     units: state.units,
                     type: .decimal("remainingCarbsFraction"),
-                    label: NSLocalizedString("Remaining Carbs Fraction", comment: "Remaining Carbs Fraction"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This is the fraction of carbs we’ll assume will absorb over 4h if we don’t yet see carb absorption.",
-                        comment: "Remaining Carbs Fraction"
-                    )
+                    label: NSLocalizedString("Remaining Carbs Percentage", comment: "Remaining Carbs Percentage"),
+                    miniHint: """
+                    Set the percentage of unabsorbed carbs that will be assumed to absorb over 4 hours if no absorption is detected
+                    Default: 100%
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 100%").bold()
+                        Text("""
+
+                        The Remaining Carbs Percentage setting helps estimate how many carbs from a meal will still be absorbed if your glucose readings don’t show clear carb absorption. This percentage, applied to the entered carbs, will be spread over 4 hours. It’s useful when the system can’t detect carb absorption from blood glucose data, providing a fallback estimate to prevent under-dosing.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -269,18 +343,26 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Remaining Carbs Cap", comment: "Remaining Carbs Cap")
                         }
                     ),
                     units: state.units,
                     type: .decimal("remainingCarbsCap"),
                     label: NSLocalizedString("Remaining Carbs Cap", comment: "Remaining Carbs Cap"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This is the amount of the maximum number of carbs we’ll assume will absorb over 4h if we don’t yet see carb absorption.",
-                        comment: "Remaining Carbs Cap"
-                    )
+                    miniHint: """
+                    Set the maximum amount of carbs assumed to absorb over 4 hours if no absorption is detected
+                    Default: 90g
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 90g").bold()
+                        Text("""
+
+                        The Remaining Carbs Cap defines the upper limit for how many carbs the system will assume are absorbing over 4 hours, even when there’s no clear sign of absorption from your glucose readings.
+
+                        This cap prevents the system from overestimating how much insulin is needed when carb absorption isn’t visible, offering a safeguard for accurate dosing.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -290,18 +372,26 @@ extension AlgorithmAdvancedSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Noisy CGM Target Multiplier", comment: "Noisy CGM Target Multiplier")
                         }
                     ),
                     units: state.units,
                     type: .decimal("noisyCGMTargetMultiplier"),
-                    label: NSLocalizedString("Noisy CGM Target Multiplier", comment: "Noisy CGM Target Multiplier"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Defaults to 1.3. Increase target by this amount when looping off raw/noisy CGM data",
-                        comment: "Noisy CGM Target Multiplier"
-                    )
+                    label: NSLocalizedString("Noisy CGM Target Increase", comment: "Noisy CGM Target Increase"),
+                    miniHint: """
+                    Increase glucose target by this percent when relying on noisy CGM data
+                    Default: 130%
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 130%").bold()
+                        Text("""
+
+                        The Noisy CGM Target Multiplier increases your glucose target when the system detects noisy or raw CGM data. By default, the target is increased by 130% to account for the less reliable glucose readings.
+
+                        This helps reduce the risk of incorrect insulin dosing based on inaccurate sensor data, ensuring safer insulin adjustments during periods of poor CGM accuracy.
+                        """)
+                    }
                 )
             }
             .sheet(isPresented: $shouldDisplayHint) {
@@ -309,7 +399,7 @@ extension AlgorithmAdvancedSettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 63 - 20
FreeAPS/Sources/Modules/AutosensSettings/View/AutosensSettingsRootView.swift

@@ -7,7 +7,7 @@ extension AutosensSettings {
         @State var state = StateModel()
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -41,18 +41,33 @@ extension AutosensSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Autosens Max", comment: "Autosens Max")
                         }
                     ),
                     units: state.units,
                     type: .decimal("autosensMax"),
                     label: NSLocalizedString("Autosens Max", comment: "Autosens Max"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This is a multiplier cap for autosens (and autotune) to set a 20% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target.",
-                        comment: "Autosens Max"
-                    ),
+                    miniHint: """
+                    The higher limit of the Autosens Ratio
+                    Default: 120%
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 120%").bold()
+                        Text(
+                            """
+
+                            Autosens Max sets the maximum Autosens Ratio used by Autosens, Dynamic ISF, Sigmoid Formula, and/or Autotune.
+
+                            The Autosens Ratio is used to calculate the amount of adjustment needed to basals, ISF, and CR.
+
+                            """
+                        )
+                        Text(
+                            "Increasing this value allows automatic adjustments of basal rates to be higher, ISF to be lower, and CR to be lower."
+                        )
+                        .italic()
+                    },
                     headerText: "Glucose Deviations Algorithm"
                 )
 
@@ -63,18 +78,33 @@ extension AutosensSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Autosens Min", comment: "Autosens Min")
                         }
                     ),
                     units: state.units,
                     type: .decimal("autosensMin"),
                     label: NSLocalizedString("Autosens Min", comment: "Autosens Min"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "The other side of the autosens safety limits, putting a cap on how low autosens can adjust basals, and how high it can adjust ISF and BG targets.",
-                        comment: "Autosens Min"
-                    )
+                    miniHint: """
+                    The lower limit of the Autosens Ratio
+                    Default: 80%
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 80%").bold()
+                        Text(
+                            """
+
+                            Autosens Min sets the minimum Autosens Ratio used by Autosens, Dynamic ISF, Sigmoid Formula, and/or Autotune.
+
+                            The Autosens Ratio is used to calculate the amount of adjustment needed to basals, ISF, and CR.
+
+                            """
+                        )
+                        Text(
+                            "Decreasing this value allows automatic adjustments of basal rates to be lower, ISF to be higher, and CR to be higher."
+                        )
+                        .italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -84,18 +114,31 @@ extension AutosensSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Rewind Resets Autosens", comment: "Rewind Resets Autosens")
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString("Rewind Resets Autosens", comment: "Rewind Resets Autosens"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "This feature, enabled by default, resets the autosens ratio to neutral when you rewind your pump, on the assumption that this corresponds to a probable site change. Autosens will begin learning sensitivity anew from the time of the rewind, which may take up to 6 hours. If you usually rewind your pump independently of site changes, you may want to consider disabling this feature.",
-                        comment: "Rewind Resets Autosens"
-                    )
+                    miniHint: """
+                    Pump rewind initiates a reset in Autosens Ratio
+                    Default: ON
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: ON").bold()
+                        Text("Medtronic Users Only").bold().italic()
+                        Text(
+                            "This feature resets the Autosens Ratio to neutral when you rewind your pump on the assumption that this corresponds to a site change."
+                        )
+                        Text(
+                            "Autosens will begin learning sensitivity anew from the time of the rewind, which may take up to 6 hours."
+                        )
+                        Text(
+                            "If you usually rewind your pump independently of site changes, you may want to consider disabling this feature."
+                        )
+                        .italic()
+                    }
                 )
             }
             .sheet(isPresented: $shouldDisplayHint) {
@@ -103,7 +146,7 @@ extension AutosensSettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 18 - 8
FreeAPS/Sources/Modules/AutotuneConfig/View/AutotuneConfigRootView.swift

@@ -8,7 +8,7 @@ extension AutotuneConfig {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -63,15 +63,22 @@ extension AutotuneConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Use Autotune"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Use Autotune",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Autotune… bla bla bla",
+                    miniHint: """
+                    It is not advised to use Autotune with Trio
+                    Default: OFF
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: OFF").bold()
+                        Text("It is not advised to use Autotune with Trio").bold()
+                        Text("Autotune is not designed to work with Trio. It is best to keep Autotune off and do not use it.")
+                    },
                     headerText: "Data-driven Adjustments"
                 )
 
@@ -83,15 +90,18 @@ extension AutotuneConfig {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Only Autotune Basal Insulin"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Only Autotune Basal Insulin",
-                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                        verboseHint: "Only Autotune Basal Insulin… bla bla bla"
+                        miniHint: """
+                        Restricts Autotune adjustments to only basal settings
+                        Default: OFF
+                        """,
+                        verboseHint: Text("Restricts Autotune adjustments to only basal settings.")
                     )
                 }
 
@@ -188,7 +198,7 @@ extension AutotuneConfig {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 4 - 4
FreeAPS/Sources/Modules/BasalProfileEditor/BasalProfileEditorStateModel.swift

@@ -120,15 +120,15 @@ extension BasalProfileEditor {
 
         func availableTimeIndices(_ itemIndex: Int) -> [Int] {
             // avoid index out of range issues
-            guard itemIndex >= 0 && itemIndex < items.count else {
+            guard itemIndex >= 0, itemIndex < items.count else {
                 return []
             }
-            
+
             let usedIndicesByOtherItems = items
                 .enumerated()
                 .filter { $0.offset != itemIndex }
-                .map { $0.element.timeIndex }
-            
+                .map(\.element.timeIndex)
+
             return (0 ..< timeValues.count).filter { !usedIndicesByOtherItems.contains($0) }
         }
     }

+ 67 - 19
FreeAPS/Sources/Modules/BolusCalculatorConfig/View/BolusCalculatorConfigRootView.swift

@@ -9,7 +9,7 @@ extension BolusCalculatorConfig {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -55,15 +55,24 @@ extension BolusCalculatorConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Display Meal Presets"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Display Meal Presets",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                    miniHint: """
+                    Enabling this feature allows you to create and save preset meals
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Enabling this feature allows you to create and save preset meals.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -73,15 +82,27 @@ extension BolusCalculatorConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Recommended Bolus Percentage"
                         }
                     ),
                     units: state.units,
                     type: .decimal("overrideFactor"),
                     label: "Recommended Bolus Percentage",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Recommended Bolus Percentage… bla bla bla",
+                    miniHint: """
+                    Percentage of the calculated bolus used as your recommended bolus in the bolus calculator
+                    Default: 70%
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 70%").bold()
+                        Text("""
+
+                        Recommended bolus percentage is a safety feature built into Trio. Trio first calculates an insulin required value, which is the full dosage. That dosage is then multiplied by your Recommended Bolus Percentage to display your suggested insulin dose in the bolus calculator.
+
+                        Because Trio utilizes SMBs and UAM SMBs to help you reach your target glucose, you'll want this setting to be lower than the full calculated amount (<100%).
+                        """)
+                        Text("It is not advised to set this to 100% if you also have SMBs and/or UAM SMBs enabled.").italic()
+                    },
                     headerText: "Calculator Configuration"
                 )
 
@@ -92,16 +113,29 @@ extension BolusCalculatorConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
-                            hintLabel = "Fatty Meal Factor"
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = "Fatty Meal"
                         }
                     ),
                     units: state.units,
                     type: .conditionalDecimal("fattyMealFactor"),
-                    label: "Enable Fatty Meal Factor",
-                    conditionalLabel: "Fatty Meal Factor",
-                    miniHint: "Lower your bolus recommendation by factor x for fatty meals.",
-                    verboseHint: "You can add the option in your bolus calculator to apply another (!) customizable factor at the end of the calculation which could be useful for fatty meals, e.g Pizza (default 0.7)."
+                    label: "Enable Fatty Meal",
+                    conditionalLabel: "Fatty Meal Bolus Percentage",
+                    miniHint: """
+                    A "Fatty Meal" option appears in the bolus calculator
+                    Default: OFF
+                    Default %: 70%
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: OFF").bold()
+                        Text("Default Percentage: 70%").bold()
+                        Text("""
+                        Enabling this setting adds a "Fatty Meal" option to the bolus calculator. Once this feature is enabled, a percentage setting will appear for you to set. When you use a Fatty Meal Bolus, the percentage you select for this setting will replace the Recommended Bolus Percentage setting used in that bolus calculation.
+                        """)
+                        Text(
+                            "Tip: This setting should be LOWER than your Recommended Bolus Percentage setting to enable the bolus calculator to give less than the calculated amount to prevent lows due to carbs absorbing very slowly. This could be useful when eating meals like pizza."
+                        ).italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -111,16 +145,30 @@ extension BolusCalculatorConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
-                            hintLabel = "Super Bolus & Sweet Meal Factor"
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = "Super Bolus"
                         }
                     ),
                     units: state.units,
                     type: .conditionalDecimal("sweetMealFactor"),
                     label: "Enable Super Bolus",
-                    conditionalLabel: "Super Bolus Factor",
-                    miniHint: "Add x times current scheduled basal rate to your bolus recommendation.",
-                    verboseHint: "You can enable the super bolus functionality which could be useful when eating sweets/cake etc. Therefore your current basal rate will be added x-times to your bolus recommendation. You can adjust the factor X here, the default is 2 times your current scheduled basal rate."
+                    conditionalLabel: "Super Bolus Percentage",
+                    miniHint: """
+                    A "Super Bolus" option appears in the bolus calculator
+                    Default: OFF
+                    Default %: 200%
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: OFF").bold()
+                        Text("Default Percentage: 200%").bold()
+                        Text("""
+                        Enabling this setting adds a "Super Bolus" option to the bolus calculator. Once this feature is enabled, a percentage setting will appear for you to set. When you use a Super Bolus, the percentage you select for this setting will replace the Recommended Bolus Percentage setting used in that bolus calculation.
+                        """)
+                        Text("The Super Bolus is a useful option for sweet or fast meals.")
+                        Text(
+                            "Tip: This setting should be HIGHER than your Recommended Bolus Percentage setting to enable the bolus calculator to give above the calculated amount to address carbs that absorb very quickly. This could be useful when eating sweets."
+                        ).italic()
+                    }
                 )
             }
             .sheet(isPresented: $shouldDisplayHint) {
@@ -128,7 +176,7 @@ extension BolusCalculatorConfig {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 34 - 9
FreeAPS/Sources/Modules/CGM/View/CGMRootView.swift

@@ -11,7 +11,7 @@ extension CGM {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -52,7 +52,7 @@ extension CGM {
 
                                 HStack(alignment: .top) {
                                     Text(
-                                        "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        "Select your CGM"
                                     )
                                     .font(.footnote)
                                     .foregroundColor(.secondary)
@@ -62,7 +62,11 @@ extension CGM {
                                         action: {
                                             hintLabel = "Available CGM Types for Trio"
                                             selectedVerboseHint =
-                                                "CGM Types… bla bla \n\nLorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                                AnyView(
+                                                    Text(
+                                                        "● Dexcom G5 \n● Dexcom G6/ONE \n● Dexcom G7/ONE+ \n● Dexcom Share \n● Freestyle Libre \n● Freestyle Libre Demo \n● Glucose Simulator \n● Medtronic Enlite \n● Nightscout \n● xDrip4iOS."
+                                                    )
+                                                )
                                             shouldDisplayHint.toggle()
                                         },
                                         label: {
@@ -163,7 +167,10 @@ extension CGM {
 
                                 HStack(alignment: .top) {
                                     Text(
-                                        "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        """
+                                        A “heartbeat” is what tells Trio to start a loop cycle. 
+                                        This is required to keep looping.
+                                        """
                                     )
                                     .font(.footnote)
                                     .foregroundColor(.secondary)
@@ -172,7 +179,12 @@ extension CGM {
                                     Button(
                                         action: {
                                             hintLabel = "CGM Heartbeat"
-                                            selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                            selectedVerboseHint =
+                                                AnyView(
+                                                    Text(
+                                                        "The Heartbeat can come from either a CGM or a pump to wake up Trio when phone is locked or in the background. If CGM is on the same phone as Trio and xDrip4iOS is configured to use the same AppGroup as Trio and the heartbeat feature is turned on in xDrip4iOS, then the CGM can provide a heartbeat to wake up Trio when phone is locked or app is in the background."
+                                                    )
+                                                )
                                             shouldDisplayHint.toggle()
                                         },
                                         label: {
@@ -199,15 +211,28 @@ extension CGM {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Smooth Glucose Value"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Smooth Glucose Value",
-                        miniHint: "Smooth CGM readings using Savitzky–Golay filtering.",
-                        verboseHint: "Smooth Glucose Value… bla bla bla"
+                        miniHint: """
+                        Smooth CGM readings using Savitzky–Golay filtering
+                        Default: OFF
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: OFF").bold()
+                            Text("""
+
+                            This filter looks at small groups of nearby readings and fits them to a simple mathematical curve (a low-degree polynomial). This process doesn’t change the overall pattern of your glucose data but helps smooth out the "noise" or irregular fluctuations that could lead to false highs or lows.
+
+                            Because your glucose readings are taken at regular intervals, the filter can use a set of pre-calculated "weights" to adjust each group of readings, making the calculations fast and efficient. It’s designed to keep the important trends in your data while minimizing those small, misleading variations, giving you a clearer sense of where your blood sugar is really headed.
+
+                            This type of filtering is useful in Trio, as it can help prevent over-corrections based on inaccurate glucose readings. This can help reduce the impact of sudden spikes or dips that might not reflect your true blood glucose levels, helping you get a more accurate picture of your trends.
+                            """)
+                        }
                     )
                 }
                 .scrollContentBackground(.hidden).background(color)
@@ -219,7 +244,7 @@ extension CGM {
                         hintDetent: $hintDetent,
                         shouldDisplayHint: $shouldDisplayHint,
                         hintLabel: hintLabel ?? "",
-                        hintText: selectedVerboseHint ?? "",
+                        hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                         sheetTitle: "Help"
                     )
                 }

+ 42 - 11
FreeAPS/Sources/Modules/CalendarEventSettings/View/CalendarEventSettingsRootView.swift

@@ -7,7 +7,7 @@ extension CalendarEventSettings {
         @StateObject var state = StateModel()
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -41,15 +41,24 @@ extension CalendarEventSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Create Events in Calendar"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Create Events in Calendar",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Create Calendar Events… bla bla bla",
+                    miniHint: """
+                    When enabled, Trio creates customizable calendar events in an iCloud calendar'
+                    Default: OFF
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: OFF").bold()
+                        Text(
+                            "When enabled, Trio will create a calendar event with every successful loop cycle. The previous calendar event will be deleted."
+                        )
+                        Text("You can customize this with the calendar of your choosing, emojis, and IOB/COB.")
+                    },
                     headerText: "Diabetes Data as Calendar Event"
                 )
 
@@ -71,15 +80,31 @@ extension CalendarEventSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Display Emojis as Labels"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Display Emojis as Labels",
-                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                        verboseHint: "Display Emojis as Labels… bla bla bla"
+                        miniHint: """
+                        Enable to use emojis instead of "IOB" or "COB" and to indicate in-range and out-of-range glucose readings
+                        Default: OFF
+                        """,
+                        verboseHint: VStack(spacing: 10) {
+                            Text("Default: OFF").bold()
+                            Text("""
+                             When enabled, the calendar event created will indicate whether glucose readings are in-range or out-of-range using the following color emojis:
+                            🟢: In-Range
+                            🟠: Above-Range
+                            🔴: Below-Range    
+                            """)
+                            Text("""
+                            If "Display IOB and COB" is also enabled, "IOB" and "COB" will be replaced with the following emojis:
+                            💉: IOB
+                            🥨: COB
+                            """)
+                        }
                     )
 
                     SettingInputSection(
@@ -89,15 +114,21 @@ extension CalendarEventSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Display IOB and COB"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Display IOB and COB",
-                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                        verboseHint: "Display IOB and COB… bla bla bla"
+                        miniHint: """
+                        Include IOB and COB in the calendar event created by Trio
+                        Default: OFF
+                        """,
+                        verboseHint: VStack(spacing: 10) {
+                            Text("Default: OFF").bold()
+                            Text(" When enabled, Trio will include the current IOB and COB values in the calendar event created.")
+                        }
                     )
                 } else if state.useCalendar {
                     if #available(iOS 17.0, *) {
@@ -119,7 +150,7 @@ extension CalendarEventSettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 173 - 32
FreeAPS/Sources/Modules/DynamicSettings/View/DynamicSettingsRootView.swift

@@ -7,7 +7,7 @@ extension DynamicSettings {
         @State var state = StateModel()
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -63,16 +63,35 @@ extension DynamicSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Activate Dynamic Sensitivity (ISF)"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
-                    label: "Activate Dynamic Sensitivity (ISF)",
-                    miniHint: "Trio calculates insulin sensitivity (ISF) each loop cycle based on current blood sugar, daily insulin use, and an adjustment factor, within set limits.",
-                    verboseHint: "DynamicISF",
-                    headerText: "Dynamic Insulin Sensitivity"
+                    label: "Activate Dynamic ISF (Sensitivity)",
+                    miniHint: """
+                    When enabled, Trio adjusts your Insulin Sensitivity Factor (ISF) automatically based on blood glucose, insulin use, and an adjustment factor
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Dynamic ISF allows Trio to calculate a new ISF with each loop cycle by considering your current blood glucose (BG), total daily dose (TDD) of insulin, and adjustment factor (AF). This helps tailor your insulin response more accurately in real-time. 
+
+                        Dynamic ISF calculates a Dynamic Ratio, determining how much your profile ISF will be adjusted every loop cycle, ensuring it stays within safe limits set by your Autosens Min/Max settings. It provides more precise insulin dosing by responding to changes in insulin needs throughout the day.
+                        """)
+                        Text("""
+
+                         Dynamic Ratio = (Profile ISF) × AF × TDD × (log(BG ÷ (Insulin Factor) + 1)) ÷ 1800
+
+                         New ISF = (Profile ISF) ÷ (Dynamic Ratio)
+
+                         Insulin Factor = 120 - (Insulin Peak Time)
+                        """).italic()
+                    },
+                    headerText: "Dynamic Settings"
                 )
 
                 if state.useNewFormula {
@@ -83,15 +102,29 @@ extension DynamicSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
-                                hintLabel = "Activate Dynamic Carb Ratio (CR)"
+                                selectedVerboseHint = $0.map { AnyView($0) }
+                                hintLabel = "Activate Dynamic CR (Carb Ratio)"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
-                        label: "Activate Dynamic Carb Ratio (CR)",
-                        miniHint: "Similar to Dynamic Sensitivity, Trio calculates a dynamic carb ratio every loop cycle.",
-                        verboseHint: "Logarithmic Dynamic Insulin Sensitivity"
+                        label: "Activate Dynamic CR (Carb Ratio)",
+                        miniHint: """
+                        Automatically adjust your carb ratio (CR) based on insulin sensitivity and glucose levels
+                        Default: OFF
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: OFF").bold()
+                            Text("""
+
+                            Dynamic CR adjusts your carb ratio (CR) in real-time, depending on your Dynamic Ratio. When this ratio increases (indicating you need more insulin), the CR is adjusted to make your insulin dosing more effective. When the ratio decreases (indicating you need less insulin), the carb ratio is scaled back to avoid over-delivery.
+
+                            """)
+                            Text(
+                                "It’s recommended not to use this feature with a high Insulin Fraction (>2), as it can cause insulin dosing to become too aggressive."
+                            )
+                            .italic()
+                        }
                     )
 
                     SettingInputSection(
@@ -101,15 +134,38 @@ extension DynamicSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Use Sigmoid Formula"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Use Sigmoid Formula",
-                        miniHint: "Alternative formula for dynamic ISF, that alters ISF based on distance from target BG",
-                        verboseHint: "Sigmoid  Dynamic Insulin Sensitivity"
+                        miniHint: """
+                        Alternative formula for Dynamic ISF (Sensitivity), that adjusts ISF based on distance from target BG using a sigmoid-shaped curve
+                        Default: OFF
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: OFF").bold()
+                            Text("""
+
+                            Turning on the Sigmoid Formula setting changes how your Dynamic Ratio, and thus your New ISF and New Carb Ratio, are calculated using a sigmoid curve rather than the default logarithmic function. The curve's steepness is adjusted by the Adjustment Factor (AF), while the Autosens Min/Max settings determine the limits of the ratio adjustment. 
+
+                            When using the Sigmoid Formula, TDD has a much lower impact on the dynamic adjustments to sensitivity.
+
+                            Careful tuning is essential to avoid overly aggressive insulin changes.
+
+                            """)
+                            Text("""
+                            It is not recommended to set Autosens Max above 150% to maintain safe insulin dosing.
+
+                            """).italic()
+                            Text(
+                                "There has been no empirical data analysis to support the use of the Sigmoid Formula for dynamic sensitivity determination."
+                            )
+                            .italic()
+                            .bold()
+                        }
                     )
 
                     if !state.sigmoid {
@@ -120,15 +176,28 @@ extension DynamicSettings {
                             selectedVerboseHint: Binding(
                                 get: { selectedVerboseHint },
                                 set: {
-                                    selectedVerboseHint = $0
-                                    hintLabel = "Adjustment Factor"
+                                    selectedVerboseHint = $0.map { AnyView($0) }
+                                    hintLabel = "Adjustment Factor (AF)"
                                 }
                             ),
                             units: state.units,
                             type: .decimal("adjustmentFactor"),
-                            label: "Adjustment Factor",
-                            miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                            verboseHint: "Adjustment Factor for logarithmic dynamic sensitvity... bla bla bla"
+                            label: "Adjustment Factor (AF)",
+                            miniHint: """
+                            Fine-tune how aggressively your ISF changes in response to glucose fluctuations when using Dynamic ISF (logarithmic formula)
+                            Default: 80%
+                            """,
+                            verboseHint: VStack {
+                                Text("Default: 80%").bold()
+                                Text("""
+
+                                The Adjustment Factor (AF) allows you to control how aggressively your dynamic ISF responds to changes in blood glucose levels. 
+
+                                A higher value means a stronger correction, increasing or decreasing the sensitivity of your insulin delivery to highs and lows in your glucose readings.
+
+                                """)
+                                Text("The maximum effect of this setting is limited by the Autosens Min/Max values.").italic()
+                            }
                         )
                     } else {
                         SettingInputSection(
@@ -138,15 +207,33 @@ extension DynamicSettings {
                             selectedVerboseHint: Binding(
                                 get: { selectedVerboseHint },
                                 set: {
-                                    selectedVerboseHint = $0
+                                    selectedVerboseHint = $0.map { AnyView($0) }
                                     hintLabel = "Sigmoid Adjustment Factor"
                                 }
                             ),
                             units: state.units,
                             type: .decimal("adjustmentFactorSigmoid"),
                             label: "Sigmoid Adjustment Factor",
-                            miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                            verboseHint: "Sigmoid Adjustment Factor… should be 0.5… bla bla ba"
+                            miniHint: """
+                            Fine-tune how aggressively your ISF changes in response to glucose fluctuations when using Sigmoid Formula for Dynamic ISF
+                            Default: 50%
+                            """,
+                            verboseHint: VStack {
+                                Text("Default: 50%").bold()
+                                Text("""
+
+                                The Sigmoid Adjustment Factor (AF) allows you to control how aggressively your Dynamic ISF using the Sigmoid Formula responds to changes in blood glucose levels. 
+
+                                Higher values lead to stronger corrections for high or low blood glucose levels, making the curve steeper. 
+
+                                This setting allows for a more responsive system, but like other dynamic settings, its effect is capped by the Autosens Min/Max limits.
+
+                                """)
+                                Text(
+                                    "Due to how the curve is calculated when using the Sigmoid Formula, increasing this setting has a greater impact on the steepness of the curve than in the standard logarithmic Dynamic ISF calculation. Use caution when adjusting this setting."
+                                )
+                                .italic()
+                            }
                         )
                     }
 
@@ -157,15 +244,30 @@ extension DynamicSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Weighted Average of TDD"
                             }
                         ),
                         units: state.units,
                         type: .decimal("weightPercentage"),
                         label: "Weighted Average of TDD",
-                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                        verboseHint: "Weight of past 24 hours"
+                        miniHint: """
+                        The weight of the last 24 hours of total daily insulin dose (TDD) to calculate the Autosens Ratio used in Dynamic ISF and Dynamic CR
+                        Default: 65%
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: 65%").bold()
+                            Text("""
+
+                            This setting adjusts how much weight is given to your recent total daily insulin dose (TDD) when calculating Dynamic ISF and Dynamic CR. 
+
+                            At the default setting, 65% of the calculation is based on the last 24 hours of insulin use, with the remaining 35% considering the last 10 days of data. 
+
+                            Setting this to 100% means only the past 24 hours will be used. 
+
+                            A lower value smooths out these variations for more stability.
+                            """)
+                        }
                     )
 
                     SettingInputSection(
@@ -175,15 +277,38 @@ extension DynamicSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Adjust Basal"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Adjust Basal",
-                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                        verboseHint: "Adjust basal dynamically… bla bla"
+                        miniHint: """
+                        Replaces Autosens’s formula for adjusting basal rates, with a formula dependent on total daily dose (TDD) of insulin.
+                        Default: OFF
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: OFF").bold()
+                            Text("""
+
+                            Turn this setting on to give basal adjustments more agility. Keep this setting off if your basal needs are not highly variable.
+
+                            Normally, a new basal rate is set by autosens:
+
+                            """)
+                            Text("New Basal Profile = (Current Basal Profile) x (Autosens Ratio)").italic()
+                            Text("""
+
+                            Adjust Basal replaces the standard Autosens Ratio calculation with its own Autosens Ratio calculated as such:
+
+                            """)
+                            Text("""
+                            Autosens Ratio = (Weighted Average of TDD) ÷ (10-day Average of TDD)
+
+                            New Basal Profile = (Current Basal Profile) × (Autosens Ratio)
+                            """).italic()
+                        }
                     )
 
                     SettingInputSection(
@@ -193,15 +318,31 @@ extension DynamicSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Minimum Safety Threshold"
                             }
                         ),
                         units: state.units,
                         type: .decimal("threshold_setting"),
                         label: "Minimum Safety Threshold",
-                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                        verboseHint: "Minimum Safety Threshold… bla bla bla"
+                        miniHint: """
+                        This gives you the ability to increase the threshold in which insulin delivery stops.
+                        Default: (Set by Algorithm)
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: Set by Algorithm").bold()
+                            Text("""
+
+                            Minimum Threshold Setting is determined by your set Target Glucose. This threshold automatically suspends insulin delivery if your glucose levels are forecasted to fall below this value. It’s designed to protect against hypoglycemia, particularly during sleep or other vulnerable times.
+
+                            If your glucose target is 110 mg/dL, Trio will use a safety threshold of 75 mg/dL, unless you set Minimum Safety Threshold (mg/dL) to something > 75.
+
+                            If you leave Minimum Safety Threshold at the default, then it will use the safety threshold calculated by the algorithm that depends on your target. The lower you set your target, the lower the safety threshold will get set. If you don't want to allow it to set your safety threshold below a certain value, you can raise Minimum Safety Threshold to a higher value using this setting.
+
+                            """)
+                            Text("Basal may be resumed if there's negative IOB and glucose is rising faster than the forecast.")
+                                .italic()
+                        }
                     )
                 }
             }
@@ -210,7 +351,7 @@ extension DynamicSettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

Разница между файлами не показана из-за своего большого размера
+ 65 - 20
FreeAPS/Sources/Modules/GeneralSettings/View/UnitsLimitsSettingsRootView.swift


+ 60 - 16
FreeAPS/Sources/Modules/GlucoseNotificationSettings/View/GlucoseNotificationSettingsRootView.swift

@@ -10,7 +10,7 @@ extension GlucoseNotificationSettings {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -63,15 +63,24 @@ extension GlucoseNotificationSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Show Glucose App Badge"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Show Glucose App Badge",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
+                    miniHint: """
+                    Show your current glucose reading at the top of the Trio app icon
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        This will add your current glucose on the top right of your Trio icon as a red notification badge.
+                        """)
+                    },
                     headerText: "Various Glucose Notifications"
                 )
 
@@ -82,15 +91,24 @@ extension GlucoseNotificationSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Always Notify Glucose"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Always Notify Glucose",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                    miniHint: """
+                    A notification will be triggered every time your glucose is updated in Trio
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        A notification will be triggered every time your glucose is updated in Trio.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -100,15 +118,24 @@ extension GlucoseNotificationSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Play Alarm Sound"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Play Alarm Sound",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                    miniHint: """
+                    This will cause a sound to be triggered by every Trio notification
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        This will cause a sound to be triggered by every Trio notification.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -118,15 +145,24 @@ extension GlucoseNotificationSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Add Glucose Source to Alarm"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Add Glucose Source to Alarm",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                    miniHint: """
+                    The source of the glucose reading will be added to the notification
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        The source of the glucose reading will be added to the notification.
+                        """)
+                    }
                 )
 
                 self.lowAndHighGlucoseAlertSection
@@ -136,7 +172,7 @@ extension GlucoseNotificationSettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }
@@ -229,13 +265,21 @@ extension GlucoseNotificationSettings {
                         .lineLimit(nil)
                         .font(.footnote)
                         .foregroundColor(.secondary)
-
                         Spacer()
                         Button(
                             action: {
                                 hintLabel = "Low and High Glucose Alarm Limits"
                                 selectedVerboseHint =
-                                    "These two settings limit the range outside of which you will be notified via push notifications. If your CGM readings are below 'Low' or above 'High', you will receive an alarm via push notification."
+                                    AnyView(VStack {
+                                        Text("Low Default: 70 mg/dL").bold()
+                                        Text("High Default: 180 mg/dL").bold()
+                                        Text("""
+
+                                        These two settings determine the range outside of which you will be notified via push notifications. 
+
+                                        If your CGM readings are below the Low value or above the High value, you will receive a glucose alarm.
+                                        """)
+                                    })
                                 shouldDisplayHint.toggle()
                             },
                             label: {

+ 21 - 13
FreeAPS/Sources/Modules/HealthKit/View/AppleHealthKitRootView.swift

@@ -8,7 +8,7 @@ extension AppleHealthKit {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -40,18 +40,26 @@ extension AppleHealthKit {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Connect to Apple Health"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Connect to Apple Health",
-                    miniHint: "Allows Trio to read from and write to Apple Health.",
-                    verboseHint: NSLocalizedString(
-                        "This allows Trio to read from and write to Apple Health. You must also give permissions in iOS Settings > Health > Data Access. If you enter a glucose value into Apple Health, open Trio to confirm it shows up.",
-                        comment: "Suspend Zeros IOB"
-                    ),
+                    miniHint: """
+                    Allows Trio to read from and write to Apple Health
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        This allows Trio to read from and write to Apple Health.
+
+                        """)
+                        Text("You must also give permissions in iOS System Settings for the Health app.").bold().italic()
+                    },
                     headerText: "Apple Health Integration"
                 )
 
@@ -63,11 +71,11 @@ extension AppleHealthKit {
                                 Text("Give Apple Health Write Permissions")
                             }.padding(.bottom)
                             Text("""
-                            1. Open the Settings app on your iOS device.
-                            2. Scroll down and select "Health."
-                            3. Tap on "Data Access & Devices."
-                            4. Find and select "Trio" from the list of apps.
-                            5. Ensure that the "Write Data" option is enabled for the desired health metrics.
+                            1. Open the Settings app on your iOS device
+                            2. Scroll down or type "Health" in the settings search bar and select the "Health" app
+                            3. Tap on "Data Access & Devices"
+                            4. Find and select "Trio" from the list of apps
+                            5. Ensure that the "Write Data" option is enabled for the desired health metrics
                             """).font(.footnote)
                         }
                         .padding(.vertical)
@@ -80,7 +88,7 @@ extension AppleHealthKit {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 13 - 5
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -788,22 +788,28 @@ extension Home {
                         List {
                             DefinitionRow(
                                 term: "IOB (Insulin on Board)",
-                                definition: "Forecasts BG based on the amount of insulin still active in the body.",
+                                definition: Text("Forecasts BG based on the amount of insulin still active in the body."),
                                 color: .insulin
                             )
                             DefinitionRow(
                                 term: "ZT (Zero-Temp)",
-                                definition: "Forecasts the worst-case blood glucose (BG) scenario if no carbs are absorbed and insulin delivery is stopped until BG starts rising.",
+                                definition: Text(
+                                    "Forecasts the worst-case blood glucose (BG) scenario if no carbs are absorbed and insulin delivery is stopped until BG starts rising."
+                                ),
                                 color: .zt
                             )
                             DefinitionRow(
                                 term: "COB (Carbs on Board)",
-                                definition: "Forecasts BG changes by considering the amount of carbohydrates still being absorbed in the body.",
+                                definition: Text(
+                                    "Forecasts BG changes by considering the amount of carbohydrates still being absorbed in the body."
+                                ),
                                 color: .loopYellow
                             )
                             DefinitionRow(
                                 term: "UAM (Unannounced Meal)",
-                                definition: "Forecasts BG levels and insulin dosing needs for unexpected meals or other causes of BG rises without prior notice.",
+                                definition: Text(
+                                    "Forecasts BG levels and insulin dosing needs for unexpected meals or other causes of BG rises without prior notice."
+                                ),
                                 color: .uam
                             )
                         }
@@ -813,7 +819,9 @@ extension Home {
                         List {
                             DefinitionRow(
                                 term: "Cone of Uncertainty",
-                                definition: "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.\n\nTo modify the forecast display type, go to Trio Settings > Features > User Interface > Forecast Display Type.",
+                                definition: 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.\n\nTo modify the forecast display type, go to Trio Settings > Features > User Interface > Forecast Display Type."
+                                ),
                                 color: Color.blue.opacity(0.5)
                             )
                         }

+ 39 - 6
FreeAPS/Sources/Modules/LiveActivitySettings/View/LiveActivitySettingsRootView.swift

@@ -9,7 +9,7 @@ extension LiveActivitySettings {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -68,15 +68,33 @@ extension LiveActivitySettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Enable Live Activity"
                             }
                         ),
                         units: state.units,
                         type: .boolean,
                         label: "Enable Live Activity",
-                        miniHint: "Live Activities display Trio's glucose readings, and other current data on the iPhone Lock Screen and in the Dynamic Island",
-                        verboseHint: "With Live Activities, you can let Trio display most current data, e.g. glucose reading from CGM, insulin on board, carbohydrates on board, or even a glucose trend chart, on the iPhone Lock Screen and in the Dynamic Island. It allows you to refer to live information at a glance and perform quick actions in your diabetes management.",
+                        miniHint: """
+                        Live Activities display Trio's glucose readings and other current data on the iPhone Lock Screen and in the Dynamic Island
+                        Default: OFF
+                        """,
+                        verboseHint: VStack(spacing: 10) {
+                            Text("Default: OFF").bold()
+                            Text(
+                                "With Live Activities, Trio displays your choice of the following current data on your iPhone's Lock Screen and in the Dynamic Island:"
+                            )
+                            VStack(alignment: .leading) {
+                                Text("• Current Glucose Reading")
+                                Text("• IOB: Insulin On Board")
+                                Text("• COB: Carbohydrates On Board")
+                                Text("• Last Updated: Time of Last Loop Cycle")
+                                Text("• Glucose Trend Chart")
+                            }
+                            Text(
+                                "It allows you to refer to live information at a glance and perform quick actions in your diabetes management."
+                            )
+                        },
                         headerText: "Display Live Data From Trio"
                     )
 
@@ -104,7 +122,22 @@ extension LiveActivitySettings {
                                         action: {
                                             hintLabel = "Lock Screen Widget Style"
                                             selectedVerboseHint =
-                                                "Trio's simple lock screen widget only display current glucose reading, trend arrow, delta and the timestamp of the current reading.\n\nThe detailed Lock Screen widget offers users a glucose chart, glucose trend arrow, glucose delta, current insulin and carbohydrates on board, and an icon as an indicator for running overrides."
+                                                AnyView(
+                                                    VStack(spacing: 10) {
+                                                        Text(
+                                                            "Trio's Simple Lock Screen Widget only display current glucose reading, trend arrow, delta and the timestamp of the current reading."
+                                                        )
+                                                        Text(
+                                                            "The Detailed Lock Screen Widget offers users a glucose chart as well as the ability to customize the information provided in the Detailed Widget using the following options:"
+                                                        )
+                                                        VStack(alignment: .leading) {
+                                                            Text("• Current Glucose Reading")
+                                                            Text("• IOB: Insulin On Board")
+                                                            Text("• COB: Carbohydrates On Board")
+                                                            Text("• Last Updated: Time of Last Loop Cycle")
+                                                        }
+                                                    }
+                                                )
                                             shouldDisplayHint.toggle()
                                         },
                                         label: {
@@ -139,7 +172,7 @@ extension LiveActivitySettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 145 - 40
FreeAPS/Sources/Modules/MealSettings/View/MealSettingsRootView.swift

@@ -9,7 +9,7 @@ extension MealSettings {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -163,7 +163,7 @@ extension MealSettings {
 
                             HStack(alignment: .top) {
                                 Text(
-                                    "Set limits for entering meals in treatment view."
+                                    "Set limits for each type of macro per meal entry"
                                 )
                                 .lineLimit(nil)
                                 .font(.footnote)
@@ -173,7 +173,14 @@ extension MealSettings {
                                 Button(
                                     action: {
                                         hintLabel = "Limits per Entry"
-                                        selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        selectedVerboseHint =
+                                            AnyView(Text("""
+                                            Max Carbs = Enter the largest carbohydrate value allowed per meal entry
+
+                                            Max Fat = Enter the largest fat value allowed per meal entry
+
+                                            Max Protein = Enter the largest protein value allowed per meal entry
+                                            """))
                                         shouldDisplayHint.toggle()
                                     },
                                     label: {
@@ -194,18 +201,53 @@ extension MealSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
-                            hintLabel = "Display and Allow Fat and Protein Entries"
+                            selectedVerboseHint = $0.map { AnyView($0) }
+                            hintLabel = "Enable Fat and Protein Entries"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
-                    label: "Display and Allow Fat and Protein Entries",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nDefaults: Spread Duration: 8 h, Spread Interval: 30 min, FPU Factor: 0.5, Delay 60 min.",
+                    label: "Enable Fat and Protein Entries",
+                    miniHint: """
+                    Allows you to add fat and protein macros to meals
+                    Default: OFF
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Enabling this setting allows you to log fat and protein, which are then converted into future carb equivalents using the Warsaw Method.
+
+                        The Warsaw Method helps account for the delayed glucose spikes caused by fat and protein in meals. It uses Fat-Protein Units (FPU) to calculate the carb effect from fat and protein. The system spreads insulin delivery over several hours to mimic natural insulin release, helping to manage post-meal glucose spikes.
+
+                        """)
+                        Text("Fat Conversion").bold()
+                        Text("𝑭 = fat(g) × 90%").italic()
+                        Text("""
+
+                        Protein Conversion
+                        """).bold()
+                        Text("𝑷 = protein(g) × 40%").italic()
+                        Text("""
+
+                        FPU Conversion
+                        """).bold()
+                        Text("𝑭 + 𝑷 = g CHO").italic()
+                        Text(
+                            """
+
+                            You can personalize the conversion calculation by adjusting the following settings that will appear when this option is enabled:
+                            """
+                        )
+                        VStack(alignment: .leading) {
+                            Text("• Fat and Protein Delay")
+                            Text("• Maximum Duration")
+                            Text("• Spread Interval")
+                            Text("• Fat and Protein Percentage")
+                        }
+                    },
                     headerText: "Fat and Protein"
                 )
-
                 if state.useFPUconversion {
                     SettingInputSection(
                         decimalValue: $state.delay,
@@ -214,15 +256,26 @@ extension MealSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Fat and Protein Delay"
                             }
                         ),
                         units: state.units,
                         type: .decimal("delay"),
                         label: "Fat and Protein Delay",
-                        miniHint: "Delay is time from now until the first future carb entry.",
-                        verboseHint: "X-Axis Interval Step… bla bla bla"
+                        miniHint: """
+                        Set the delay between fat & protein entry in the bolus calculator and the first FPU entry
+                        Default: 60 min
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: 60 min").bold()
+                            Text("""
+
+                            The Fat Protein Delay setting defines the time between when you log fat and protein and when the system starts delivering insulin for the Fat-Protein Unit Carb Equivalents (FPUs). 
+
+                            This delay accounts for the slower absorption of fat and protein, as calculated by the Warsaw Method, ensuring insulin delivery is properly timed to manage glucose spikes caused by high-fat, high-protein meals.
+                            """)
+                        }
                     )
 
                     SettingInputSection(
@@ -232,15 +285,32 @@ extension MealSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
-                                hintLabel = "Maximum Duration (hours)"
+                                selectedVerboseHint = $0.map { AnyView($0) }
+                                hintLabel = "Maximum Duration"
                             }
                         ),
                         units: state.units,
                         type: .decimal("timeCap"),
-                        label: "Maximum Duration (hours)",
-                        miniHint: "Carb spread over a maximum number of hours (5-12).",
-                        verboseHint: "This spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours."
+                        label: "Maximum Duration",
+                        miniHint: """
+                        Set the maximum timeframe to extend FPUs
+                        Default: 8 hours
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: 8 hours").bold()
+                            Text("""
+
+                            This sets the maximum length of time that Fat and Protein Carb Equivalents (FPUs) will be extended over from a single Fat and/or Protein bolus calcultor entry.
+
+                            It is one factor used in combination with the Fat and Protein Delay, Spread Interval, and Fat and Protein Factor to create the FPU entries
+
+                            Increasing this setting may result in more FPU entries with smaller carb values.
+
+                            Decreasing this setting may result in fewer FPU entries with larger carb values.
+
+                            """)
+                            Text("Accepted range for this setting is 5 - 12 hours.").italic()
+                        }
                     )
 
                     SettingInputSection(
@@ -250,15 +320,32 @@ extension MealSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
-                                hintLabel = "Spread Interval (minutes)"
+                                selectedVerboseHint = $0.map { AnyView($0) }
+                                hintLabel = "Spread Interval"
                             }
                         ),
                         units: state.units,
                         type: .decimal("minuteInterval"),
-                        label: "Spread Interval (minutes)",
-                        miniHint: "Interval in minutes is how many minutes are between entries.",
-                        verboseHint: "Interval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices."
+                        label: "Spread Interval",
+                        miniHint: """
+                        Set the time interval between FPUs
+                        Default: 30 minutes
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: 30 minutes").bold()
+                            Text("""
+
+                            This determines how many minutes will be between individual Fat-Protein Unit Carb Equivalent (FPU) entries from a single Fat and/or Protein bolus calculator entry.
+
+                            The shorter the interval, the smoother the correlating dosing result.
+
+                            Increasing this setting may result in fewer FPU entries with larger carb values.
+
+                            Decreasing this setting may result in more FPU entries with smaller carb values.
+
+                            """)
+                            Text("Accepted range for this setting is 5 - 60 minutes.").italic()
+                        }
                     )
 
                     SettingInputSection(
@@ -268,31 +355,49 @@ extension MealSettings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
-                                hintLabel = "Fat and Protein Factor"
+                                selectedVerboseHint = $0.map { AnyView($0) }
+                                hintLabel = "Fat and Protein Percentage"
                             }
                         ),
                         units: state.units,
                         type: .decimal("individualAdjustmentFactor"),
-                        label: "Fat and Protein Factor",
-                        miniHint: "Influences how many carb equivalents are recorded for fat and protein.",
-                        verboseHint: "The Fat and Protein Factor influences how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it."
+                        label: "Fat and Protein Percentage",
+                        miniHint: """
+                        Influences the conversion rate used in the Warsaw Method
+                        Default: 50%
+                        """,
+                        verboseHint: VStack {
+                            Text("Default: 50%").bold()
+                            Text("This setting changes how much effect the fat and protein entry has on FPUs.")
+                            VStack(alignment: .center) {
+                                Text("50% is half effect:").bold()
+                                Text("(Fat × 45%) + (Protein × 20%)")
+                                Text("100% is full effect:").bold()
+                                Text("(Fat × 90%) + (Protein × 40%)")
+                                Text("200% is double effect:").bold()
+                                Text("(Fat × 180%) + (Protein x 80%)")
+                                Text("""
+
+                                You may find that your normal carb ratio needs to increase to a larger number when you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 50% to ease into it.
+                                """).italic()
+                            }
+                        }
                     )
+                    .sheet(isPresented: $shouldDisplayHint) {
+                        SettingInputHintView(
+                            hintDetent: $hintDetent,
+                            shouldDisplayHint: $shouldDisplayHint,
+                            hintLabel: hintLabel ?? "",
+                            hintText: selectedVerboseHint ?? AnyView(EmptyView()),
+                            sheetTitle: "Help"
+                        )
+                    }
+                    .scrollContentBackground(.hidden).background(color)
+                    .onAppear(perform: configureView)
+                    .navigationBarTitle("Meal Settings")
+                    .navigationBarTitleDisplayMode(.automatic)
                 }
             }
-            .sheet(isPresented: $shouldDisplayHint) {
-                SettingInputHintView(
-                    hintDetent: $hintDetent,
-                    shouldDisplayHint: $shouldDisplayHint,
-                    hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
-                    sheetTitle: "Help"
-                )
-            }
-            .scrollContentBackground(.hidden).background(color)
-            .onAppear(perform: configureView)
-            .navigationBarTitle("Meal Settings")
-            .navigationBarTitleDisplayMode(.automatic)
         }
     }
 }

+ 34 - 7
FreeAPS/Sources/Modules/NightscoutConfig/View/NightscoutConfigRootView.swift

@@ -12,7 +12,7 @@ extension NightscoutConfig {
         @State var importedHasRun = false
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -66,7 +66,16 @@ extension NightscoutConfig {
                                 importAlert = Alert(
                                     title: Text("Import Therapy Settings?"),
                                     message: Text(
-                                        "Are you sure you want to import profile settings from Nightscout?\n\nThis will overwrite the following Trio therapy settings: Basal Rates, Insulin Sensitivities, Carb Ratios, Target Glucose, and Duration of Insulin Action."
+                                        """
+                                        Are you sure you want to import profile settings from Nightscout?
+
+                                        This will overwrite the following Trio therapy settings:
+                                            • Basal Rates
+                                            • Insulin Sensitivities
+                                            • Carb Ratios
+                                            • Target Glucose
+                                            • Duration of Insulin Action
+                                        """
                                     ),
                                     primaryButton: .default(
                                         Text("Yes, Import!"),
@@ -101,7 +110,10 @@ extension NightscoutConfig {
 
                             HStack(alignment: .top) {
                                 Text(
-                                    "You can import therapy settings from Nightscout. See hint for more information which settings will be overwritten."
+                                    """
+                                    Import therapy settings from Nightscout
+                                    See hint for the list of settings available for import
+                                    """
                                 )
                                 .font(.footnote)
                                 .foregroundColor(.secondary)
@@ -111,7 +123,18 @@ extension NightscoutConfig {
                                     action: {
                                         hintLabel = "Import Settings from Nightscout"
                                         selectedVerboseHint =
-                                            "This will overwrite the following Trio therapy settings: \n • Basal Rates \n • Insulin Sensitivities \n • Carb Ratios \n • Target Glucose \n • Duration of Insulin Action"
+                                            AnyView(
+                                                Text(
+                                                    """
+                                                    This will overwrite the following Trio therapy settings:
+                                                        • Basal Rates
+                                                        • Insulin Sensitivities
+                                                        • Carb Ratios
+                                                        • Target Glucose
+                                                        • Duration of Insulin Action
+                                                    """
+                                                )
+                                            )
                                         shouldDisplayHint.toggle()
                                     },
                                     label: {
@@ -141,7 +164,7 @@ extension NightscoutConfig {
 
                                 HStack(alignment: .top) {
                                     Text(
-                                        "You can backfill missing glucose data from Nightscout."
+                                        "Backfill missing glucose data from Nightscout"
                                     )
                                     .font(.footnote)
                                     .foregroundColor(.secondary)
@@ -151,7 +174,11 @@ extension NightscoutConfig {
                                         action: {
                                             hintLabel = "Backfill Glucose from Nightscout"
                                             selectedVerboseHint =
-                                                "Explanation… limitation… etc."
+                                                AnyView(
+                                                    Text(
+                                                        "This will backfill 24 hours of glucose data from your connected Nightscout URL to Trio"
+                                                    )
+                                                )
                                             shouldDisplayHint.toggle()
                                         },
                                         label: {
@@ -178,7 +205,7 @@ extension NightscoutConfig {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 24 - 8
FreeAPS/Sources/Modules/NightscoutConfig/View/NightscoutFetchView.swift

@@ -6,7 +6,7 @@ struct NightscoutFetchView: View {
 
     @State private var shouldDisplayHint: Bool = false
     @State var hintDetent = PresentationDetent.large
-    @State var selectedVerboseHint: String?
+    @State var selectedVerboseHint: AnyView?
     @State var hintLabel: String?
     @State private var decimalPlaceholder: Decimal = 0.0
     @State private var booleanPlaceholder: Bool = false
@@ -38,15 +38,20 @@ struct NightscoutFetchView: View {
                 selectedVerboseHint: Binding(
                     get: { selectedVerboseHint },
                     set: {
-                        selectedVerboseHint = $0
+                        selectedVerboseHint = $0.map { AnyView($0) }
                         hintLabel = "Allow Fetching from Nightscout"
                     }
                 ),
                 units: state.units,
                 type: .boolean,
                 label: "Allow Fetching from Nightscout",
-                miniHint: "Enable fetching of selected data sets from Nightscout. See hint for more details.",
-                verboseHint: "The Fetch Treatments toggle enables fetching of carbs and temp targets entered in Careportal or by another uploading device than Trio from Nightscout.",
+                miniHint: """
+                Enable fetching of selected data sets from Nightscout
+                See hint for more details.
+                """,
+                verboseHint: Text(
+                    "The Fetch Treatments toggle enables fetching of carbs and temp targets entered in Careportal or by another uploading device than Trio from Nightscout."
+                ),
                 headerText: "Remote & Fetch Capabilities"
             )
 
@@ -58,15 +63,26 @@ struct NightscoutFetchView: View {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Allow Remote Control of Trio"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Allow Remote Control of Trio",
-                    miniHint: "Enables selected remote control capabilities via Nightscout. See hint for more details.",
-                    verboseHint: "When enabled you allow these remote functions through announcements from Nightscout: \n • Suspend/Resume Pump \n • Opening/Closing Loop \n  • Set Temp Basal \n • Enact Bolus"
+                    miniHint: """
+                    Enables selected remote control capabilities via Nightscout
+                    See hint for more details
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("When enabled you allow these remote functions through announcements from Nightscout:")
+                        VStack(alignment: .leading) {
+                            Text("• Suspend/Resume Pump")
+                            Text("• Opening/Closing Loop")
+                            Text("• Set Temp Basal")
+                            Text("• Enact Bolus")
+                        }
+                    }
                 )
             } else {
                 Section {
@@ -79,7 +95,7 @@ struct NightscoutFetchView: View {
                 hintDetent: $hintDetent,
                 shouldDisplayHint: $shouldDisplayHint,
                 hintLabel: hintLabel ?? "",
-                hintText: selectedVerboseHint ?? "",
+                hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                 sheetTitle: "Help"
             )
         }

+ 22 - 8
FreeAPS/Sources/Modules/NightscoutConfig/View/NightscoutUploadView.swift

@@ -5,7 +5,7 @@ struct NightscoutUploadView: View {
 
     @State private var shouldDisplayHint: Bool = false
     @State var hintDetent = PresentationDetent.large
-    @State var selectedVerboseHint: String?
+    @State var selectedVerboseHint: AnyView?
     @State var hintLabel: String?
     @State private var decimalPlaceholder: Decimal = 0.0
     @State private var booleanPlaceholder: Bool = false
@@ -37,7 +37,7 @@ struct NightscoutUploadView: View {
                 selectedVerboseHint: Binding(
                     get: { selectedVerboseHint },
                     set: {
-                        selectedVerboseHint = $0
+                        selectedVerboseHint = $0.map { AnyView($0) }
                         hintLabel = "Allow Uploading to Nightscout"
                         shouldDisplayHint = true
                     }
@@ -45,8 +45,20 @@ struct NightscoutUploadView: View {
                 units: state.units,
                 type: .boolean,
                 label: "Allow Uploading to Nightscout",
-                miniHint: "Enables upload of selected data sets to Nightscout. See hint for more details.",
-                verboseHint: "The Upload Treatments toggle enables uploading of carbs, temp targets, device status, preferences and settings."
+                miniHint: """
+                Enables upload of selected data sets to Nightscout
+                See hint for more details
+                """,
+                verboseHint: VStack(spacing: 5) {
+                    Text("The Upload Treatments toggle enables uploading of:")
+                    VStack(alignment: .leading) {
+                        Text("• Carbs")
+                        Text("• Temp Targets")
+                        Text("• Device Status")
+                        Text("• Preferences")
+                        Text("• Settings")
+                    }
+                }
             )
 
             if state.changeUploadGlucose {
@@ -57,7 +69,7 @@ struct NightscoutUploadView: View {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Upload Glucose"
                             shouldDisplayHint = true
                         }
@@ -65,8 +77,10 @@ struct NightscoutUploadView: View {
                     units: state.units,
                     type: .boolean,
                     label: "Upload Glucose",
-                    miniHint: "Enables uploading of CGM readings to Nightscout.",
-                    verboseHint: "Write stuff here."
+                    miniHint: "Enables uploading of CGM readings to Nightscout",
+                    verboseHint: Text(
+                        "Enabling this setting allows CGM readings from Trio to be used in Nightscout."
+                    )
                 )
             }
         }
@@ -75,7 +89,7 @@ struct NightscoutUploadView: View {
                 hintDetent: $hintDetent,
                 shouldDisplayHint: $shouldDisplayHint,
                 hintLabel: hintLabel ?? "",
-                hintText: selectedVerboseHint ?? "",
+                hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                 sheetTitle: "Help"
             )
         }

+ 17 - 5
FreeAPS/Sources/Modules/NightscoutConfig/View/ProfileImport/ReviewInsulinActionView.swift

@@ -10,7 +10,7 @@ struct ReviewInsulinActionView: BaseView {
 
     @State private var shouldDisplayHint: Bool = false
     @State private var hintDetent = PresentationDetent.large
-    @State private var selectedVerboseHint: String?
+    @State private var selectedVerboseHint: AnyView?
     @State private var hintLabel: String?
     @State private var decimalPlaceholder: Decimal = 0.0
     @State private var booleanPlaceholder: Bool = false
@@ -42,15 +42,27 @@ struct ReviewInsulinActionView: BaseView {
                 selectedVerboseHint: Binding(
                     get: { selectedVerboseHint },
                     set: {
-                        selectedVerboseHint = $0
+                        selectedVerboseHint = $0.map { AnyView($0) }
                         hintLabel = "Duration of Insulin Action"
                     }
                 ),
                 units: state.units,
                 type: .decimal("dia"),
                 label: "Duration of Insulin Action",
-                miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                verboseHint: "Duration of Insulin Action… bla bla bla",
+                miniHint: """
+                Number of hours insulin is active in your body
+                Default: 6 hours
+                """,
+                verboseHint: VStack {
+                    Text("Default: 6 hours").bold()
+                    Text("""
+
+                    Number of hours insulin will contribute to IOB after dosing.
+
+                    """)
+                    Text("It is better to use Custom Peak Timing rather than adjust your Duration of Insulin Action (DIA)")
+                        .italic()
+                },
                 headerText: "Review imported DIA"
             )
         }
@@ -59,7 +71,7 @@ struct ReviewInsulinActionView: BaseView {
                 hintDetent: $hintDetent,
                 shouldDisplayHint: $shouldDisplayHint,
                 hintLabel: hintLabel ?? "",
-                hintText: selectedVerboseHint ?? "",
+                hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                 sheetTitle: "Help"
             )
         }

+ 3 - 4
FreeAPS/Sources/Modules/PumpConfig/View/PumpConfigRootView.swift

@@ -9,7 +9,7 @@ extension PumpConfig {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -73,8 +73,7 @@ extension PumpConfig {
                                         Button(
                                             action: {
                                                 hintLabel = "Pump Pairing to Trio"
-                                                selectedVerboseHint =
-                                                    "Explanation… limitation… etc."
+                                                selectedVerboseHint = AnyView(Text("Explanation… limitation… etc."))
                                                 shouldDisplayHint.toggle()
                                             },
                                             label: {
@@ -119,7 +118,7 @@ extension PumpConfig {
                         hintDetent: $hintDetent,
                         shouldDisplayHint: $shouldDisplayHint,
                         hintLabel: hintLabel ?? "",
-                        hintText: selectedVerboseHint ?? "",
+                        hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                         sheetTitle: "Help"
                     )
                 }

+ 16 - 5
FreeAPS/Sources/Modules/RemoteControlConfig/View/RemoteControlConfig.swift

@@ -11,7 +11,7 @@ extension RemoteControlConfig {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var isCopied: Bool = false
@@ -44,15 +44,26 @@ extension RemoteControlConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Enable Remote Command"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Enable Remote Control",
-                    miniHint: "Remote Control allow Trio to receive instructions, such as boluses and temp targets, from LoopFollow.",
-                    verboseHint: "When Remote Control is enabled, you can send boluses, overrides, temporary targets, carbs, and other commands to Trio via push notifications. To ensure security, these commands are protected by a shared secret, which must be entered in LoopFollow.",
+                    miniHint: """
+                    Allow Trio to receive instructions, such as boluses and temp targets, from Loop Follow remotely
+                    Default: OFF
+                    """,
+                    verboseHint: VStack(spacing: 10) {
+                        Text("Default: OFF").bold()
+                        Text(
+                            "When Remote Control is enabled, you can send boluses, overrides, temporary targets, carbs, and other commands to Trio via push notifications."
+                        )
+                        Text(
+                            "To ensure security, these commands are protected by a shared secret, which must be entered in the Loop Follow app."
+                        )
+                    },
                     headerText: "Trio Remote Control"
                 )
 
@@ -100,7 +111,7 @@ extension RemoteControlConfig {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

Разница между файлами не показана из-за своего большого размера
+ 221 - 76
FreeAPS/Sources/Modules/SMBSettings/View/SMBSettingsRootView.swift


+ 11 - 4
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -14,7 +14,7 @@ extension Settings {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -91,7 +91,7 @@ extension Settings {
                         selectedVerboseHint: Binding(
                             get: { selectedVerboseHint },
                             set: {
-                                selectedVerboseHint = $0
+                                selectedVerboseHint = $0.map { AnyView($0) }
                                 hintLabel = "Closed Loop"
                             }
                         ),
@@ -99,7 +99,14 @@ extension Settings {
                         type: .boolean,
                         label: "Closed Loop",
                         miniHint: "Enables automated insulin delivery. Requires active CGM sensor session and connected pump.",
-                        verboseHint: "Running Trio in closed loop mode requires an active CGM sensor session and a connected pump. This enables automated insulin delivery.\n\nBefore enabling, dial in your settings (basal / insulin sensitivity / carb ratio), and familiarize yourself with the app.",
+                        verboseHint: VStack(spacing: 10) {
+                            Text(
+                                "Running Trio in closed loop mode requires an active CGM sensor session and a connected pump. This enables automated insulin delivery."
+                            )
+                            Text(
+                                "Before enabling, dial in your settings (basal / insulin sensitivity / carb ratio), and familiarize yourself with the app."
+                            )
+                        },
                         headerText: "Automated Insulin Delivery"
                     )
 
@@ -303,7 +310,7 @@ extension Settings {
                         hintDetent: $hintDetent,
                         shouldDisplayHint: $shouldDisplayHint,
                         hintLabel: hintLabel ?? "",
-                        hintText: selectedVerboseHint ?? "",
+                        hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                         sheetTitle: "Help"
                     )
                 }

+ 3 - 1
FreeAPS/Sources/Modules/Settings/View/TidepoolStartView.swift

@@ -113,7 +113,9 @@ struct TidepoolStartView: BaseView {
                 hintDetent: $hintDetent,
                 shouldDisplayHint: $shouldDisplayHint,
                 hintLabel: "Connect to Tidepool",
-                hintText: "When connected, uploading of carbs, bolus, basal and glucose from Trio to your Tidepool account is enabled.\n\nUse your Tidepool credentials to login. If you dont already have a Tidepool account, you can sign up for one on the login page.",
+                hintText: Text(
+                    "When connected, uploading of carbs, bolus, basal and glucose from Trio to your Tidepool account is enabled.\n\nUse your Tidepool credentials to login. If you dont already have a Tidepool account, you can sign up for one on the login page."
+                ),
                 sheetTitle: "Help"
             )
         }

+ 14 - 5
FreeAPS/Sources/Modules/ShortcutsConfig/View/ShortcutsConfigView.swift

@@ -11,7 +11,7 @@ extension ShortcutsConfig {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -63,15 +63,24 @@ extension ShortcutsConfig {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Allow Bolusing with Shortcuts"
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: "Allow Bolusing with Shortcuts",
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Allow Bolusing with Shortcuts… bla bla bla"
+                    miniHint: """
+                    Automate boluses using the Shortcuts App
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("Enabling this setting allows the iOS Shortcuts App to send bolus commands to Trio.")
+                        Text(
+                            "Disabling this setting will still allow other commands, like Temp Targets, Add Carbs, and Start/End Overrides"
+                        )
+                    }
                 )
             }
             .sheet(isPresented: $shouldDisplayHint) {
@@ -79,7 +88,7 @@ extension ShortcutsConfig {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 84 - 40
FreeAPS/Sources/Modules/TargetBehavoir/View/TargetBehavoirRootView.swift

@@ -7,7 +7,7 @@ extension TargetBehavoir {
         @StateObject var state = StateModel()
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -41,24 +41,35 @@ extension TargetBehavoir {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString(
-                                "High Temptarget Raises Sensitivity",
-                                comment: "High Temptarget Raises Sensitivity"
+                                "High Temp Target Raises Sensitivity",
+                                comment: "High Temp Target Raises Sensitivity"
                             )
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString(
-                        "High Temptarget Raises Sensitivity",
-                        comment: "High Temptarget Raises Sensitivity"
-                    ),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Defaults to false. When set to true, raises sensitivity (lower sensitivity ratio) for temp targets set to >= 111. Synonym for exercise_mode. The higher your temp target above 110 will result in more sensitive (lower) ratios, e.g., temp target of 120 results in sensitivity ratio of 0.75, while 140 results in 0.6 (with default halfBasalTarget of 160).",
-                        comment: "High Temptarget Raises Sensitivity"
+                        "High Temp Target Raises Sensitivity",
+                        comment: "High Temp Target Raises Sensitivity"
                     ),
+                    miniHint: """
+                    A Temp Target above 110 mg/dL increases sensitivity when glucose is above target
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Exercise Mode").bold().italic()
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        When this feature is enabled, setting a temporary target above 110 mg/dL will decrease the Autosens Ratio used for ISF and basal adjustments, resulting in less insulin delivered overall. This scales with the temporary target set; the higher the temp target, the lower the Autosens Ratio used.
+
+                        If Half Basal Exercise Target is set to 160, a temp target of 120 mg/dL uses an Autosens Ratio of 0.75. A temp target of 140 mg/dL uses an Autosens Ratio of 0.6.
+
+                        """)
+                        Text("The effect of this can be adjusted with the Half Basal Exercise Target").italic()
+                    },
                     headerText: "Algorithmic Target Settings"
                 )
 
@@ -69,24 +80,35 @@ extension TargetBehavoir {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString(
-                                "Low Temptarget Lowers Sensitivity",
-                                comment: "Low Temptarget Lowers Sensitivity"
+                                "Low Temp Target Lowers Sensitivity",
+                                comment: "Low Temp Target Lowers Sensitivity"
                             )
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString(
-                        "Low Temptarget Lowers Sensitivity",
-                        comment: "Low Temptarget Lowers Sensitivity"
+                        "Low Temp Target Lowers Sensitivity",
+                        comment: "Low Temp Target Lowers Sensitivity"
                     ),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Defaults to false. When set to true, can lower sensitivity (higher sensitivity ratio) for temptargets <= 99. The lower your temp target below 100 will result in less sensitive (higher) ratios, e.g., temp target of 95 results in sensitivity ratio of 1.09, while 85 results in 1.33 (with default halfBasalTarget of 160).",
-                        comment: "Low Temptarget Lowers Sensitivity"
-                    )
+                    miniHint: """
+                    A Temp Target below 100 mg/dL decreases sensitivity when glucose is below target
+                    Default setting: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Eating Soon Mode").bold().italic()
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        When this feature is enabled, setting a temporary target below 100 mg/dL will increase the Autosens Ratio used for ISF and basal adjustments, resulting in more insulin delivered overall. This scales with the temporary target set; the lower the Temp Target, the higher the Autosens Ratio used.
+
+                        If Half Basal Exercise Target is 160, a Temp Target of 95 mg/dL uses an Autosens Ratio of 1.09. A Temp Target of 85 mg/dL uses an Autosens Ratio of 1.33.
+
+                        """)
+                        Text("The effect of this can be adjusted with the Half Basal Exercise Target").italic()
+                    }
                 )
 
                 SettingInputSection(
@@ -96,18 +118,24 @@ extension TargetBehavoir {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Sensitivity Raises Target", comment: "Sensitivity Raises Target")
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString("Sensitivity Raises Target", comment: "Sensitivity Raises Target"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "When true, raises BG target when autosens detects sensitivity",
-                        comment: "Sensitivity Raises Target"
-                    )
+                    miniHint: """
+                    Trio will automatically raise your target glucose with increased sensitivity
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Enabling this feature causes Trio to automatically increase the targeted glucose if it detects an increase in sensitivity.
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -117,18 +145,24 @@ extension TargetBehavoir {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Resistance Lowers Target", comment: "Resistance Lowers Target")
                         }
                     ),
                     units: state.units,
                     type: .boolean,
                     label: NSLocalizedString("Resistance Lowers Target", comment: "Resistance Lowers Target"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Defaults to false. When true, will lower BG target when autosens detects resistance",
-                        comment: "Resistance Lowers Target"
-                    )
+                    miniHint: """
+                    Trio will automatically lower your target glucose when it detects resistance
+                    Default: OFF
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: OFF").bold()
+                        Text("""
+
+                        Enabling this feature causes Trio to automatically reduce the targeted glucose if it detects a decrease in sensitivity (resistance).
+                        """)
+                    }
                 )
 
                 SettingInputSection(
@@ -138,18 +172,28 @@ extension TargetBehavoir {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = NSLocalizedString("Half Basal Exercise Target", comment: "Half Basal Exercise Target")
                         }
                     ),
                     units: state.units,
                     type: .decimal("halfBasalExerciseTarget"),
                     label: NSLocalizedString("Half Basal Exercise Target", comment: "Half Basal Exercise Target"),
-                    miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: NSLocalizedString(
-                        "Set to a number, e.g. 160, which means when temp target is 160 mg/dL, run 50% basal at this level (120 = 75%; 140 = 60%). This can be adjusted, to give you more control over your exercise modes.",
-                        comment: "Half Basal Exercise Target"
-                    )
+                    miniHint: """
+                    Sets your current basal rate to 50% when a temp target is set to this number (in mg/dL)
+                    Default: 160 mg/dL
+                    """,
+                    verboseHint: VStack {
+                        Text("Default: 160 mg/dL").bold()
+                        Text("""
+
+                        The Half Basal Exercise Target allows you to scale down your basal insulin during exercise or scale up your basal insulin when eating soon when a temporary glucose target is set. For example, at a temp target of 160 mg/dL, your basal is reduced to 50%, but this scales depending on the target (e.g., 75% at 120 mg/dL, 60% at 140 mg/dL).
+
+                        """)
+                        Text("""
+                        This setting is only utilized if the settings "Low Temp Target Lowers Sensitivity" OR "High Temp Target Raises Sensitivity" are enabled.
+                        """).italic()
+                    }
                 )
             }
             .sheet(isPresented: $shouldDisplayHint) {
@@ -157,7 +201,7 @@ extension TargetBehavoir {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 27 - 18
FreeAPS/Sources/Modules/UserInterfaceSettings/View/UserInterfaceSettingsRootView.swift

@@ -8,7 +8,7 @@ extension UserInterfaceSettings {
 
         @State private var shouldDisplayHint: Bool = false
         @State var hintDetent = PresentationDetent.large
-        @State var selectedVerboseHint: String?
+        @State var selectedVerboseHint: AnyView?
         @State var hintLabel: String?
         @State private var decimalPlaceholder: Decimal = 0.0
         @State private var booleanPlaceholder: Bool = false
@@ -79,7 +79,8 @@ extension UserInterfaceSettings {
                                 Button(
                                     action: {
                                         hintLabel = "Color Scheme Preference"
-                                        selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        selectedVerboseHint =
+                                            AnyView(Text("Lorem ipsum dolor sit amet, consetetur sadipscing elitr."))
                                         shouldDisplayHint.toggle()
                                     },
                                     label: {
@@ -116,7 +117,11 @@ extension UserInterfaceSettings {
                                 action: {
                                     hintLabel = "Glucose Color Scheme"
                                     selectedVerboseHint =
-                                        "Glucose Color Scheme... Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        AnyView(
+                                            Text(
+                                                "Glucose Color Scheme... Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                            )
+                                        )
                                     shouldDisplayHint.toggle()
                                 },
                                 label: {
@@ -147,7 +152,8 @@ extension UserInterfaceSettings {
                                 Button(
                                     action: {
                                         hintLabel = "Show Main Chart X- and Y-Axis Grid Lines"
-                                        selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        selectedVerboseHint =
+                                            AnyView(Text("Lorem ipsum dolor sit amet, consetetur sadipscing elitr."))
                                         shouldDisplayHint.toggle()
                                     },
                                     label: {
@@ -168,7 +174,7 @@ extension UserInterfaceSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Show Low and High Thresholds"
                         }
                     ),
@@ -176,7 +182,7 @@ extension UserInterfaceSettings {
                     type: .boolean,
                     label: "Show Low and High Thresholds",
                     miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Display Low and High Thresholds… bla bla bla"
+                    verboseHint: Text("Display Low and High Thresholds… bla bla bla")
                 )
 
                 if state.rulerMarks {
@@ -263,7 +269,8 @@ extension UserInterfaceSettings {
                                 Button(
                                     action: {
                                         hintLabel = "Low and High Thresholds"
-                                        selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                        selectedVerboseHint =
+                                            AnyView(Text("Lorem ipsum dolor sit amet, consetetur sadipscing elitr."))
                                         shouldDisplayHint.toggle()
                                     },
                                     label: {
@@ -299,7 +306,8 @@ extension UserInterfaceSettings {
                             Button(
                                 action: {
                                     hintLabel = "Forecast Display Type"
-                                    selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                    selectedVerboseHint =
+                                        AnyView(Text("Lorem ipsum dolor sit amet, consetetur sadipscing elitr."))
                                     shouldDisplayHint.toggle()
                                 },
                                 label: {
@@ -319,7 +327,7 @@ extension UserInterfaceSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "X-Axis Interval Step"
                         }
                     ),
@@ -327,7 +335,7 @@ extension UserInterfaceSettings {
                     type: .decimal("hours"),
                     label: "X-Axis Interval Step",
                     miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "X-Axis Interval Step… bla bla bla"
+                    verboseHint: Text("X-Axis Interval Step… bla bla bla")
                 )
 
                 Section {
@@ -352,7 +360,8 @@ extension UserInterfaceSettings {
                             Button(
                                 action: {
                                     hintLabel = "Total Insulin Display Type"
-                                    selectedVerboseHint = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."
+                                    selectedVerboseHint =
+                                        AnyView(Text("Lorem ipsum dolor sit amet, consetetur sadipscing elitr."))
                                     shouldDisplayHint.toggle()
                                 },
                                 label: {
@@ -373,7 +382,7 @@ extension UserInterfaceSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Override HbA1c Unit"
                         }
                     ),
@@ -381,7 +390,7 @@ extension UserInterfaceSettings {
                     type: .boolean,
                     label: "Override HbA1c Unit",
                     miniHint: "Display HbA1c in mmol/L or %. Default is percent.",
-                    verboseHint: "Override HbA1c Unit… bla bla bla",
+                    verboseHint: Text("Override HbA1c Unit… bla bla bla"),
                     headerText: "Trio Statistics"
                 )
 
@@ -393,7 +402,7 @@ extension UserInterfaceSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Standing / Laying TIR Chart"
                         }
                     ),
@@ -401,7 +410,7 @@ extension UserInterfaceSettings {
                     type: .boolean,
                     label: "Standing / Laying TIR Chart",
                     miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Standing / Laying TIR Chart… bla bla bla"
+                    verboseHint: Text("Standing / Laying TIR Chart… bla bla bla")
                 )
 
                 SettingInputSection(
@@ -411,7 +420,7 @@ extension UserInterfaceSettings {
                     selectedVerboseHint: Binding(
                         get: { selectedVerboseHint },
                         set: {
-                            selectedVerboseHint = $0
+                            selectedVerboseHint = $0.map { AnyView($0) }
                             hintLabel = "Show Carbs Required Badge"
                         }
                     ),
@@ -420,7 +429,7 @@ extension UserInterfaceSettings {
                     label: "Show Carbs Required Badge",
                     conditionalLabel: "Carbs Required Threshold",
                     miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Show Carbs Required Badge… bla bla bla",
+                    verboseHint: Text("Show Carbs Required Badge… bla bla bla"),
                     headerText: "Carbs Required Badge"
                 )
             }
@@ -429,7 +438,7 @@ extension UserInterfaceSettings {
                     hintDetent: $hintDetent,
                     shouldDisplayHint: $shouldDisplayHint,
                     hintLabel: hintLabel ?? "",
-                    hintText: selectedVerboseHint ?? "",
+                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                     sheetTitle: "Help"
                 )
             }

+ 7 - 7
FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigAppleWatchView.swift

@@ -5,7 +5,7 @@ struct WatchConfigAppleWatchView: View {
 
     @State private var shouldDisplayHint: Bool = false
     @State var hintDetent = PresentationDetent.large
-    @State var selectedVerboseHint: String?
+    @State var selectedVerboseHint: AnyView?
     @State var hintLabel: String?
     @State private var decimalPlaceholder: Decimal = 0.0
     @State private var booleanPlaceholder: Bool = false
@@ -59,7 +59,7 @@ struct WatchConfigAppleWatchView: View {
                             Button(
                                 action: {
                                     hintLabel = "Display on Watch"
-                                    selectedVerboseHint = "Display on Watch… bla bla bla"
+                                    selectedVerboseHint = AnyView(Text("Display on Watch… bla bla bla"))
                                     shouldDisplayHint.toggle()
                                 },
                                 label: {
@@ -80,7 +80,7 @@ struct WatchConfigAppleWatchView: View {
                 selectedVerboseHint: Binding(
                     get: { selectedVerboseHint },
                     set: {
-                        selectedVerboseHint = $0
+                        selectedVerboseHint = $0.map { AnyView($0) }
                         hintLabel = "Show Protein and Fat"
                     }
                 ),
@@ -88,7 +88,7 @@ struct WatchConfigAppleWatchView: View {
                 type: .boolean,
                 label: "Show Protein and Fat",
                 miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                verboseHint: "Show Protein and Fat… bla bla bla"
+                verboseHint: Text("Show Protein and Fat… bla bla bla")
             )
 
             SettingInputSection(
@@ -98,7 +98,7 @@ struct WatchConfigAppleWatchView: View {
                 selectedVerboseHint: Binding(
                     get: { selectedVerboseHint },
                     set: {
-                        selectedVerboseHint = $0
+                        selectedVerboseHint = $0.map { AnyView($0) }
                         hintLabel = "Confirm Bolus Faster"
                     }
                 ),
@@ -106,7 +106,7 @@ struct WatchConfigAppleWatchView: View {
                 type: .boolean,
                 label: "Confirm Bolus Faster",
                 miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                verboseHint: "Confirm Bolus Faster… bla bla bla"
+                verboseHint: Text("Confirm Bolus Faster… bla bla bla")
             )
         }
         .sheet(isPresented: $shouldDisplayHint) {
@@ -114,7 +114,7 @@ struct WatchConfigAppleWatchView: View {
                 hintDetent: $hintDetent,
                 shouldDisplayHint: $shouldDisplayHint,
                 hintLabel: hintLabel ?? "",
-                hintText: selectedVerboseHint ?? "",
+                hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                 sheetTitle: "Help"
             )
         }

+ 3 - 3
FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigGarminView.swift

@@ -5,7 +5,7 @@ struct WatchConfigGarminView: View {
 
     @State private var shouldDisplayHint: Bool = false
     @State var hintDetent = PresentationDetent.large
-    @State var selectedVerboseHint: String?
+    @State var selectedVerboseHint: AnyView?
     @State var hintLabel: String?
     @State private var decimalPlaceholder: Decimal = 0.0
     @State private var booleanPlaceholder: Bool = false
@@ -59,7 +59,7 @@ struct WatchConfigGarminView: View {
                             Button(
                                 action: {
                                     hintLabel = "Add Device"
-                                    selectedVerboseHint = "Add Garmin Device… bla bla bla"
+                                    selectedVerboseHint = AnyView(Text("Add Garmin Device… bla bla bla"))
                                     shouldDisplayHint.toggle()
                                 },
                                 label: {
@@ -89,7 +89,7 @@ struct WatchConfigGarminView: View {
                 hintDetent: $hintDetent,
                 shouldDisplayHint: $shouldDisplayHint,
                 hintLabel: hintLabel ?? "",
-                hintText: selectedVerboseHint ?? "",
+                hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                 sheetTitle: "Help"
             )
         }

+ 3 - 3
FreeAPS/Sources/Views/DefinitionRow.swift

@@ -1,9 +1,9 @@
 import Foundation
 import SwiftUI
 
-struct DefinitionRow: View {
+struct DefinitionRow<DefinitionView: View>: View {
     var term: String
-    var definition: String
+    var definition: DefinitionView
     var color: Color?
     var fontSize: Font?
 
@@ -15,7 +15,7 @@ struct DefinitionRow: View {
                 }
                 Text(term).font(fontSize ?? .subheadline).fontWeight(.semibold)
             }.padding(.bottom, 5)
-            Text(definition)
+            definition
                 .font(fontSize ?? .subheadline)
                 .foregroundColor(.secondary)
         }

+ 2 - 2
FreeAPS/Sources/Views/SettingInputHintView.swift

@@ -1,10 +1,10 @@
 import SwiftUI
 
-struct SettingInputHintView: View {
+struct SettingInputHintView<HintView: View>: View {
     @Binding var hintDetent: PresentationDetent
     @Binding var shouldDisplayHint: Bool
     var hintLabel: String
-    var hintText: String
+    var hintText: HintView
     var sheetTitle: String
 
     @Environment(\.colorScheme) private var colorScheme

+ 4 - 4
FreeAPS/Sources/Views/SettingInputSection.swift

@@ -1,6 +1,6 @@
 import SwiftUI
 
-struct SettingInputSection: View {
+struct SettingInputSection<VerboseHint: View>: View {
     enum SettingInputSectionType: Equatable {
         case decimal(String)
         case boolean
@@ -23,14 +23,14 @@ struct SettingInputSection: View {
     @Binding var decimalValue: Decimal
     @Binding var booleanValue: Bool
     @Binding var shouldDisplayHint: Bool
-    @Binding var selectedVerboseHint: String?
+    @Binding var selectedVerboseHint: (any View)?
 
     var units: GlucoseUnits
     var type: SettingInputSectionType
     var label: String
     var conditionalLabel: String?
     var miniHint: String
-    var verboseHint: String
+    var verboseHint: VerboseHint
     var headerText: String?
     var footerText: String?
 
@@ -235,7 +235,7 @@ struct SettingInputSection: View {
         }.padding(.top)
     }
 
-    private func hintSection(miniHint: String, shouldDisplayHint: Binding<Bool>, verboseHint: String) -> some View {
+    private func hintSection(miniHint: String, shouldDisplayHint: Binding<Bool>, verboseHint: VerboseHint) -> some View {
         HStack(alignment: .top) {
             Text(miniHint)
                 .font(.footnote)