Преглед на файлове

All 'Preferences' settings split up and restructured WIP

Deniz Cengiz преди 1 година
родител
ревизия
2092dbc3b5
променени са 32 файла, в които са добавени 1480 реда и са изтрити 265 реда
  1. 155 23
      FreeAPS.xcodeproj/project.pbxproj
  2. 5 0
      FreeAPS/Sources/Modules/AlgorithmVariousSettings/AlgorithmVariousDataFlow.swift
  3. 3 0
      FreeAPS/Sources/Modules/AlgorithmVariousSettings/AlgorithmVariousProvider.swift
  4. 81 0
      FreeAPS/Sources/Modules/AlgorithmVariousSettings/AlgorithmVariousStateModel.swift
  5. 285 0
      FreeAPS/Sources/Modules/AlgorithmVariousSettings/View/AlgorithmVariousRootView.swift
  6. 5 0
      FreeAPS/Sources/Modules/AutosensSettings/AutosensSettingsDataFlow.swift
  7. 3 0
      FreeAPS/Sources/Modules/AutosensSettings/AutosensSettingsProvider.swift
  8. 45 0
      FreeAPS/Sources/Modules/AutosensSettings/AutosensSettingsStateModel.swift
  9. 116 0
      FreeAPS/Sources/Modules/AutosensSettings/View/AutosensSettingsRootView.swift
  10. 0 5
      FreeAPS/Sources/Modules/Dynamic/DynamicDataFlow.swift
  11. 0 3
      FreeAPS/Sources/Modules/Dynamic/DynamicProvider.swift
  12. 0 211
      FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift
  13. 5 0
      FreeAPS/Sources/Modules/DynamicSettings/DynamicSettingsDataFlow.swift
  14. 3 0
      FreeAPS/Sources/Modules/DynamicSettings/DynamicSettingsProvider.swift
  15. 1 1
      FreeAPS/Sources/Modules/Dynamic/DynamicStateModel.swift
  16. 218 0
      FreeAPS/Sources/Modules/DynamicSettings/View/DynamicSettingsRootView.swift
  17. 5 0
      FreeAPS/Sources/Modules/GeneralSettings/GeneralSettingsDataFlow.swift
  18. 75 0
      FreeAPS/Sources/Modules/GeneralSettings/GeneralSettingsProvider.swift
  19. 47 0
      FreeAPS/Sources/Modules/GeneralSettings/GeneralSettingsStateModel.swift
  20. 105 0
      FreeAPS/Sources/Modules/GeneralSettings/View/GeneralSettingsRootView.swift
  21. 1 0
      FreeAPS/Sources/Modules/SMBSettings/SMBSettingsStateModel.swift
  22. 10 7
      FreeAPS/Sources/Modules/SMBSettings/View/SMBSettingsView.swift
  23. 3 2
      FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift
  24. 51 0
      FreeAPS/Sources/Modules/Settings/View/Subviews/AlgorithmSettings.swift
  25. 0 10
      FreeAPS/Sources/Modules/Settings/View/Subviews/FeatureSettingsView.swift
  26. 8 0
      FreeAPS/Sources/Modules/Settings/View/Subviews/TherapySettingsView.swift
  27. 3 0
      FreeAPS/Sources/Modules/TargetBehavoir/TargetBehaviorProvider.swift
  28. 5 0
      FreeAPS/Sources/Modules/TargetBehavoir/TargetBehavoirDataFlow.swift
  29. 56 0
      FreeAPS/Sources/Modules/TargetBehavoir/TargetBehavoirStateModel.swift
  30. 168 0
      FreeAPS/Sources/Modules/TargetBehavoir/View/TargetBehavoirRootView.swift
  31. 16 1
      FreeAPS/Sources/Router/Screen.swift
  32. 2 2
      FreeAPS/Sources/Views/SettingInputSection.swift

+ 155 - 23
FreeAPS.xcodeproj/project.pbxproj

@@ -27,10 +27,10 @@
 		1927C8E62744606D00347C69 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1927C8E82744606D00347C69 /* InfoPlist.strings */; };
 		1935364028496F7D001E0B16 /* Oref2_variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1935363F28496F7D001E0B16 /* Oref2_variables.swift */; };
 		193F6CDD2A512C8F001240FD /* Loops.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193F6CDC2A512C8F001240FD /* Loops.swift */; };
-		195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B32AF6973A00D25097 /* DynamicRootView.swift */; };
-		195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */; };
-		195D80B92AF697F700D25097 /* DynamicProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B82AF697F700D25097 /* DynamicProvider.swift */; };
-		195D80BB2AF6980B00D25097 /* DynamicStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80BA2AF6980B00D25097 /* DynamicStateModel.swift */; };
+		195D80B42AF6973A00D25097 /* DynamicSettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B32AF6973A00D25097 /* DynamicSettingsRootView.swift */; };
+		195D80B72AF697B800D25097 /* DynamicSettingsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B62AF697B800D25097 /* DynamicSettingsDataFlow.swift */; };
+		195D80B92AF697F700D25097 /* DynamicSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B82AF697F700D25097 /* DynamicSettingsProvider.swift */; };
+		195D80BB2AF6980B00D25097 /* DynamicSettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80BA2AF6980B00D25097 /* DynamicSettingsStateModel.swift */; };
 		1967DFBE29D052C200759F30 /* Icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFBD29D052C200759F30 /* Icons.swift */; };
 		1967DFC029D053AC00759F30 /* IconSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFBF29D053AC00759F30 /* IconSelection.swift */; };
 		1967DFC229D053D300759F30 /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFC129D053D300759F30 /* IconImage.swift */; };
@@ -393,9 +393,26 @@
 		DD1745202C55523E00211FAC /* SMBSettingsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17451F2C55523E00211FAC /* SMBSettingsDataFlow.swift */; };
 		DD1745222C55524800211FAC /* SMBSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745212C55524800211FAC /* SMBSettingsProvider.swift */; };
 		DD1745242C55526000211FAC /* SMBSettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745232C55526000211FAC /* SMBSettingsStateModel.swift */; };
-		DD1745262C55526F00211FAC /* SMBSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745252C55526F00211FAC /* SMBSettingsView.swift */; };
+		DD1745262C55526F00211FAC /* SMBSettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745252C55526F00211FAC /* SMBSettingsRootView.swift */; };
 		DD1745292C55642100211FAC /* SettingInputSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745282C55642100211FAC /* SettingInputSection.swift */; };
 		DD17452B2C556E8100211FAC /* SettingInputHintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17452A2C556E8100211FAC /* SettingInputHintView.swift */; };
+		DD17452E2C55AE4800211FAC /* TargetBehavoirDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17452D2C55AE4800211FAC /* TargetBehavoirDataFlow.swift */; };
+		DD1745302C55AE5300211FAC /* TargetBehaviorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17452F2C55AE5300211FAC /* TargetBehaviorProvider.swift */; };
+		DD1745322C55AE6000211FAC /* TargetBehavoirStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745312C55AE6000211FAC /* TargetBehavoirStateModel.swift */; };
+		DD1745352C55AE7E00211FAC /* TargetBehavoirRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745342C55AE7E00211FAC /* TargetBehavoirRootView.swift */; };
+		DD1745372C55B74200211FAC /* AlgorithmSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745362C55B74200211FAC /* AlgorithmSettings.swift */; };
+		DD17453A2C55BFA600211FAC /* AlgorithmVariousDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745392C55BFA600211FAC /* AlgorithmVariousDataFlow.swift */; };
+		DD17453C2C55BFAD00211FAC /* AlgorithmVariousProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17453B2C55BFAD00211FAC /* AlgorithmVariousProvider.swift */; };
+		DD17453E2C55BFB600211FAC /* AlgorithmVariousStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17453D2C55BFB600211FAC /* AlgorithmVariousStateModel.swift */; };
+		DD1745402C55BFC100211FAC /* AlgorithmVariousRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17453F2C55BFC100211FAC /* AlgorithmVariousRootView.swift */; };
+		DD1745442C55C60E00211FAC /* AutosensSettingsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745432C55C60E00211FAC /* AutosensSettingsDataFlow.swift */; };
+		DD1745462C55C61500211FAC /* AutosensSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745452C55C61500211FAC /* AutosensSettingsProvider.swift */; };
+		DD1745482C55C61D00211FAC /* AutosensSettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745472C55C61D00211FAC /* AutosensSettingsStateModel.swift */; };
+		DD17454B2C55C62800211FAC /* AutosensSettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17454A2C55C62800211FAC /* AutosensSettingsRootView.swift */; };
+		DD17454E2C55CA4D00211FAC /* GeneralSettingsDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17454D2C55CA4D00211FAC /* GeneralSettingsDataFlow.swift */; };
+		DD1745502C55CA5500211FAC /* GeneralSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17454F2C55CA5500211FAC /* GeneralSettingsProvider.swift */; };
+		DD1745522C55CA5D00211FAC /* GeneralSettingsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745512C55CA5D00211FAC /* GeneralSettingsStateModel.swift */; };
+		DD1745552C55CA6C00211FAC /* GeneralSettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745542C55CA6C00211FAC /* GeneralSettingsRootView.swift */; };
 		DD1DB7CC2BECCA1F0048B367 /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */; };
 		DD399FB31EACB9343C944C4C /* PreferencesEditorStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA3E609094E064C99A4752C /* PreferencesEditorStateModel.swift */; };
 		DD57C4B22C4C7103001A5B28 /* LoopStatRecord+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD57C4902C4C7103001A5B28 /* LoopStatRecord+CoreDataClass.swift */; };
@@ -599,10 +616,10 @@
 		193F1E3B2B44C14800525770 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		193F1E3C2B44C14800525770 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
 		193F6CDC2A512C8F001240FD /* Loops.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loops.swift; sourceTree = "<group>"; };
-		195D80B32AF6973A00D25097 /* DynamicRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRootView.swift; sourceTree = "<group>"; };
-		195D80B62AF697B800D25097 /* DynamicDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicDataFlow.swift; sourceTree = "<group>"; };
-		195D80B82AF697F700D25097 /* DynamicProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicProvider.swift; sourceTree = "<group>"; };
-		195D80BA2AF6980B00D25097 /* DynamicStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicStateModel.swift; sourceTree = "<group>"; };
+		195D80B32AF6973A00D25097 /* DynamicSettingsRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicSettingsRootView.swift; sourceTree = "<group>"; };
+		195D80B62AF697B800D25097 /* DynamicSettingsDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicSettingsDataFlow.swift; sourceTree = "<group>"; };
+		195D80B82AF697F700D25097 /* DynamicSettingsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicSettingsProvider.swift; sourceTree = "<group>"; };
+		195D80BA2AF6980B00D25097 /* DynamicSettingsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicSettingsStateModel.swift; sourceTree = "<group>"; };
 		1967DFBD29D052C200759F30 /* Icons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icons.swift; sourceTree = "<group>"; };
 		1967DFBF29D053AC00759F30 /* IconSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSelection.swift; sourceTree = "<group>"; };
 		1967DFC129D053D300759F30 /* IconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconImage.swift; sourceTree = "<group>"; };
@@ -1006,9 +1023,26 @@
 		DD17451F2C55523E00211FAC /* SMBSettingsDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMBSettingsDataFlow.swift; sourceTree = "<group>"; };
 		DD1745212C55524800211FAC /* SMBSettingsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMBSettingsProvider.swift; sourceTree = "<group>"; };
 		DD1745232C55526000211FAC /* SMBSettingsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMBSettingsStateModel.swift; sourceTree = "<group>"; };
-		DD1745252C55526F00211FAC /* SMBSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMBSettingsView.swift; sourceTree = "<group>"; };
+		DD1745252C55526F00211FAC /* SMBSettingsRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMBSettingsRootView.swift; sourceTree = "<group>"; };
 		DD1745282C55642100211FAC /* SettingInputSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingInputSection.swift; sourceTree = "<group>"; };
 		DD17452A2C556E8100211FAC /* SettingInputHintView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingInputHintView.swift; sourceTree = "<group>"; };
+		DD17452D2C55AE4800211FAC /* TargetBehavoirDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetBehavoirDataFlow.swift; sourceTree = "<group>"; };
+		DD17452F2C55AE5300211FAC /* TargetBehaviorProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetBehaviorProvider.swift; sourceTree = "<group>"; };
+		DD1745312C55AE6000211FAC /* TargetBehavoirStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetBehavoirStateModel.swift; sourceTree = "<group>"; };
+		DD1745342C55AE7E00211FAC /* TargetBehavoirRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetBehavoirRootView.swift; sourceTree = "<group>"; };
+		DD1745362C55B74200211FAC /* AlgorithmSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmSettings.swift; sourceTree = "<group>"; };
+		DD1745392C55BFA600211FAC /* AlgorithmVariousDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmVariousDataFlow.swift; sourceTree = "<group>"; };
+		DD17453B2C55BFAD00211FAC /* AlgorithmVariousProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmVariousProvider.swift; sourceTree = "<group>"; };
+		DD17453D2C55BFB600211FAC /* AlgorithmVariousStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmVariousStateModel.swift; sourceTree = "<group>"; };
+		DD17453F2C55BFC100211FAC /* AlgorithmVariousRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmVariousRootView.swift; sourceTree = "<group>"; };
+		DD1745432C55C60E00211FAC /* AutosensSettingsDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensSettingsDataFlow.swift; sourceTree = "<group>"; };
+		DD1745452C55C61500211FAC /* AutosensSettingsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensSettingsProvider.swift; sourceTree = "<group>"; };
+		DD1745472C55C61D00211FAC /* AutosensSettingsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensSettingsStateModel.swift; sourceTree = "<group>"; };
+		DD17454A2C55C62800211FAC /* AutosensSettingsRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensSettingsRootView.swift; sourceTree = "<group>"; };
+		DD17454D2C55CA4D00211FAC /* GeneralSettingsDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsDataFlow.swift; sourceTree = "<group>"; };
+		DD17454F2C55CA5500211FAC /* GeneralSettingsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsProvider.swift; sourceTree = "<group>"; };
+		DD1745512C55CA5D00211FAC /* GeneralSettingsStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsStateModel.swift; sourceTree = "<group>"; };
+		DD1745542C55CA6C00211FAC /* GeneralSettingsRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsRootView.swift; sourceTree = "<group>"; };
 		DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildDetails.swift; sourceTree = "<group>"; };
 		DD57C4902C4C7103001A5B28 /* LoopStatRecord+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoopStatRecord+CoreDataClass.swift"; sourceTree = SOURCE_ROOT; };
 		DD57C4912C4C7103001A5B28 /* LoopStatRecord+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoopStatRecord+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
@@ -1231,21 +1265,21 @@
 			name = "Recovered References";
 			sourceTree = "<group>";
 		};
-		195D80B22AF696EE00D25097 /* Dynamic */ = {
+		195D80B22AF696EE00D25097 /* DynamicSettings */ = {
 			isa = PBXGroup;
 			children = (
-				195D80B62AF697B800D25097 /* DynamicDataFlow.swift */,
-				195D80B82AF697F700D25097 /* DynamicProvider.swift */,
-				195D80BA2AF6980B00D25097 /* DynamicStateModel.swift */,
+				195D80B62AF697B800D25097 /* DynamicSettingsDataFlow.swift */,
+				195D80B82AF697F700D25097 /* DynamicSettingsProvider.swift */,
+				195D80BA2AF6980B00D25097 /* DynamicSettingsStateModel.swift */,
 				195D80B52AF6974200D25097 /* View */,
 			);
-			path = Dynamic;
+			path = DynamicSettings;
 			sourceTree = "<group>";
 		};
 		195D80B52AF6974200D25097 /* View */ = {
 			isa = PBXGroup;
 			children = (
-				195D80B32AF6973A00D25097 /* DynamicRootView.swift */,
+				195D80B32AF6973A00D25097 /* DynamicSettingsRootView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -1349,6 +1383,10 @@
 		3811DE0325C9D31700A708ED /* Modules */ = {
 			isa = PBXGroup;
 			children = (
+				DD17454C2C55CA0200211FAC /* GeneralSettings */,
+				DD1745422C55C5C400211FAC /* AutosensSettings */,
+				DD1745382C55BF8B00211FAC /* AlgorithmVariousSettings */,
+				DD17452C2C55AE3500211FAC /* TargetBehavoir */,
 				DD17451E2C55520000211FAC /* SMBSettings */,
 				672F63EEAE27400625E14BAD /* AutotuneConfig */,
 				A42F1FEDFFD0DDE00AAD54D3 /* BasalProfileEditor */,
@@ -1360,7 +1398,7 @@
 				0610F7D6D2EC00E3BA1569F0 /* ConfigEditor */,
 				E42231DBF0DBE2B4B92D1B15 /* CREditor */,
 				9E56E3626FAD933385101B76 /* DataTable */,
-				195D80B22AF696EE00D25097 /* Dynamic */,
+				195D80B22AF696EE00D25097 /* DynamicSettings */,
 				19D466A129AA2B0A004D5F33 /* FPUConfig */,
 				F90692CD274B99850037068D /* HealthKit */,
 				3811DE2725C9D49500A708ED /* Home */,
@@ -2428,6 +2466,7 @@
 				DD1745162C54389F00211FAC /* FeatureSettingsView.swift */,
 				DD1745182C543B5700211FAC /* NotificationsView.swift */,
 				DD17451C2C543C5F00211FAC /* ServicesView.swift */,
+				DD1745362C55B74200211FAC /* AlgorithmSettings.swift */,
 			);
 			path = Subviews;
 			sourceTree = "<group>";
@@ -2446,7 +2485,83 @@
 		DD1745272C5553C400211FAC /* View */ = {
 			isa = PBXGroup;
 			children = (
-				DD1745252C55526F00211FAC /* SMBSettingsView.swift */,
+				DD1745252C55526F00211FAC /* SMBSettingsRootView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		DD17452C2C55AE3500211FAC /* TargetBehavoir */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745332C55AE6500211FAC /* View */,
+				DD17452D2C55AE4800211FAC /* TargetBehavoirDataFlow.swift */,
+				DD17452F2C55AE5300211FAC /* TargetBehaviorProvider.swift */,
+				DD1745312C55AE6000211FAC /* TargetBehavoirStateModel.swift */,
+			);
+			path = TargetBehavoir;
+			sourceTree = "<group>";
+		};
+		DD1745332C55AE6500211FAC /* View */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745342C55AE7E00211FAC /* TargetBehavoirRootView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		DD1745382C55BF8B00211FAC /* AlgorithmVariousSettings */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745412C55BFC400211FAC /* View */,
+				DD1745392C55BFA600211FAC /* AlgorithmVariousDataFlow.swift */,
+				DD17453B2C55BFAD00211FAC /* AlgorithmVariousProvider.swift */,
+				DD17453D2C55BFB600211FAC /* AlgorithmVariousStateModel.swift */,
+			);
+			path = AlgorithmVariousSettings;
+			sourceTree = "<group>";
+		};
+		DD1745412C55BFC400211FAC /* View */ = {
+			isa = PBXGroup;
+			children = (
+				DD17453F2C55BFC100211FAC /* AlgorithmVariousRootView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		DD1745422C55C5C400211FAC /* AutosensSettings */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745492C55C62000211FAC /* View */,
+				DD1745432C55C60E00211FAC /* AutosensSettingsDataFlow.swift */,
+				DD1745452C55C61500211FAC /* AutosensSettingsProvider.swift */,
+				DD1745472C55C61D00211FAC /* AutosensSettingsStateModel.swift */,
+			);
+			path = AutosensSettings;
+			sourceTree = "<group>";
+		};
+		DD1745492C55C62000211FAC /* View */ = {
+			isa = PBXGroup;
+			children = (
+				DD17454A2C55C62800211FAC /* AutosensSettingsRootView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		DD17454C2C55CA0200211FAC /* GeneralSettings */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745532C55CA6100211FAC /* View */,
+				DD17454D2C55CA4D00211FAC /* GeneralSettingsDataFlow.swift */,
+				DD17454F2C55CA5500211FAC /* GeneralSettingsProvider.swift */,
+				DD1745512C55CA5D00211FAC /* GeneralSettingsStateModel.swift */,
+			);
+			path = GeneralSettings;
+			sourceTree = "<group>";
+		};
+		DD1745532C55CA6100211FAC /* View */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745542C55CA6C00211FAC /* GeneralSettingsRootView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -2948,7 +3063,7 @@
 				F90692CF274B999A0037068D /* HealthKitDataFlow.swift in Sources */,
 				CE7CA3552A064973004BE681 /* ListStateIntent.swift in Sources */,
 				BDF530D82B40F8AC002CAF43 /* LockScreenView.swift in Sources */,
-				195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */,
+				195D80B72AF697B800D25097 /* DynamicSettingsDataFlow.swift in Sources */,
 				3862CC2E2743F9F700BF832C /* CalendarManager.swift in Sources */,
 				CEA4F62329BE10F70011ADF7 /* SavitzkyGolayFilter.swift in Sources */,
 				38B4F3C325E2A20B00E76A18 /* PumpSetupView.swift in Sources */,
@@ -2965,8 +3080,9 @@
 				38DF1786276A73D400B3528F /* TagCloudView.swift in Sources */,
 				38B4F3CD25E5031100E76A18 /* Broadcaster.swift in Sources */,
 				383420D925FFEB3F002D46C1 /* Popup.swift in Sources */,
+				DD1745402C55BFC100211FAC /* AlgorithmVariousRootView.swift in Sources */,
 				110AEDEE2C51A0AE00615CC9 /* ShortcutsConfigStateModel.swift in Sources */,
-				DD1745262C55526F00211FAC /* SMBSettingsView.swift in Sources */,
+				DD1745262C55526F00211FAC /* SMBSettingsRootView.swift in Sources */,
 				3811DE3025C9D49500A708ED /* HomeStateModel.swift in Sources */,
 				38BF021725E7CBBC00579895 /* PumpManagerExtensions.swift in Sources */,
 				CEE9A6552BBB418300EB5194 /* CalibrationsProvider.swift in Sources */,
@@ -2982,12 +3098,14 @@
 				CE94598029E9E3BD0047C9C6 /* WatchConfigDataFlow.swift in Sources */,
 				388E596C25AD95110019842D /* OpenAPS.swift in Sources */,
 				E00EEC0527368630002FF094 /* StorageAssembly.swift in Sources */,
+				DD1745552C55CA6C00211FAC /* GeneralSettingsRootView.swift in Sources */,
 				384E803825C388640086DB71 /* Script.swift in Sources */,
 				CE94597E29E9E1EE0047C9C6 /* GarminManager.swift in Sources */,
 				3883583425EEB38000E024B2 /* PumpSettings.swift in Sources */,
 				38DAB280260CBB7F00F74C1A /* PumpView.swift in Sources */,
 				DDD1631C2C4C697400CD525A /* AddOverrideForm.swift in Sources */,
 				3811DEB125C9D88300A708ED /* Keychain.swift in Sources */,
+				DD17453E2C55BFB600211FAC /* AlgorithmVariousStateModel.swift in Sources */,
 				CE95BF572BA5F5FE00DC3DE3 /* PluginManager.swift in Sources */,
 				382C133725F13A1E00715CE1 /* InsulinSensitivities.swift in Sources */,
 				19D466A529AA2BD4004D5F33 /* FPUConfigProvider.swift in Sources */,
@@ -2998,6 +3116,7 @@
 				38E44539274E411700EC9A94 /* Disk+UIImage.swift in Sources */,
 				388E595C25AD948C0019842D /* FreeAPSApp.swift in Sources */,
 				38FEF3FC2737E53800574A46 /* MainStateModel.swift in Sources */,
+				DD1745352C55AE7E00211FAC /* TargetBehavoirRootView.swift in Sources */,
 				5887527C2BD986E1008B081D /* OpenAPSBattery.swift in Sources */,
 				38569348270B5DFB0002C50D /* GlucoseSource.swift in Sources */,
 				CEE9A6582BBB418300EB5194 /* CalibrationsStateModel.swift in Sources */,
@@ -3007,6 +3126,7 @@
 				CEE9A6562BBB418300EB5194 /* CalibrationsRootView.swift in Sources */,
 				3811DE2525C9D48300A708ED /* MainRootView.swift in Sources */,
 				CE94598229E9E3D30047C9C6 /* WatchConfigProvider.swift in Sources */,
+				DD1745322C55AE6000211FAC /* TargetBehavoirStateModel.swift in Sources */,
 				38E44535274E411700EC9A94 /* Disk+Data.swift in Sources */,
 				3811DE3125C9D49500A708ED /* HomeProvider.swift in Sources */,
 				FE41E4D629463EE20047FD55 /* NightscoutPreferences.swift in Sources */,
@@ -3038,6 +3158,8 @@
 				DD1745152C54388A00211FAC /* TherapySettingsView.swift in Sources */,
 				585E2CAE2BE7BF46006ECF1A /* PumpEvent+helper.swift in Sources */,
 				DDD1631F2C4C6F6900CD525A /* TrioCoreDataPersistentContainer.xcdatamodeld in Sources */,
+				DD1745482C55C61D00211FAC /* AutosensSettingsStateModel.swift in Sources */,
+				DD1745462C55C61500211FAC /* AutosensSettingsProvider.swift in Sources */,
 				3811DEAF25C9D88300A708ED /* KeyValueStorage.swift in Sources */,
 				38FE826D25CC8461001FF17A /* NightscoutAPI.swift in Sources */,
 				388358C825EEF6D200E024B2 /* BasalProfileEntry.swift in Sources */,
@@ -3070,6 +3192,7 @@
 				DD57C4C22C4C7103001A5B28 /* Forecast+CoreDataClass.swift in Sources */,
 				DD57C4C32C4C7103001A5B28 /* Forecast+CoreDataProperties.swift in Sources */,
 				DD57C4C42C4C7103001A5B28 /* BolusStored+CoreDataClass.swift in Sources */,
+				DD1745302C55AE5300211FAC /* TargetBehaviorProvider.swift in Sources */,
 				DD57C4C52C4C7103001A5B28 /* BolusStored+CoreDataProperties.swift in Sources */,
 				DD57C4C62C4C7103001A5B28 /* CarbEntryStored+CoreDataClass.swift in Sources */,
 				DD57C4C72C4C7103001A5B28 /* CarbEntryStored+CoreDataProperties.swift in Sources */,
@@ -3082,6 +3205,7 @@
 				DD57C4CE2C4C7103001A5B28 /* OverrideRunStored+CoreDataClass.swift in Sources */,
 				DD57C4CF2C4C7103001A5B28 /* OverrideRunStored+CoreDataProperties.swift in Sources */,
 				DD57C4D02C4C7103001A5B28 /* ImportError+CoreDataClass.swift in Sources */,
+				DD17454E2C55CA4D00211FAC /* GeneralSettingsDataFlow.swift in Sources */,
 				DD57C4D12C4C7103001A5B28 /* ImportError+CoreDataProperties.swift in Sources */,
 				DD57C4D22C4C7103001A5B28 /* StatsData+CoreDataClass.swift in Sources */,
 				DD57C4D32C4C7103001A5B28 /* StatsData+CoreDataProperties.swift in Sources */,
@@ -3120,6 +3244,7 @@
 				3811DE5F25C9D4D500A708ED /* ProgressBar.swift in Sources */,
 				38E87408274F9AD000975559 /* UserNotificationsManager.swift in Sources */,
 				CE82E02528E867BA00473A9C /* AlertStorage.swift in Sources */,
+				DD1745372C55B74200211FAC /* AlgorithmSettings.swift in Sources */,
 				38BF021D25E7E3AF00579895 /* Reservoir.swift in Sources */,
 				583684082BD195A700070A60 /* Determination.swift in Sources */,
 				DD17451D2C543C5F00211FAC /* ServicesView.swift in Sources */,
@@ -3144,6 +3269,7 @@
 				38E989DD25F5021400C0CED0 /* PumpStatus.swift in Sources */,
 				BDFD165A2AE40438007F0DDA /* BolusRootView.swift in Sources */,
 				38E98A2525F52C9300C0CED0 /* IssueReporter.swift in Sources */,
+				DD1745522C55CA5D00211FAC /* GeneralSettingsStateModel.swift in Sources */,
 				190EBCC429FF136900BA767D /* StatConfigDataFlow.swift in Sources */,
 				5A2325582BFCC168003518CA /* NightscoutConnectView.swift in Sources */,
 				3811DEB025C9D88300A708ED /* BaseKeychain.swift in Sources */,
@@ -3172,13 +3298,16 @@
 				BD2B464E0745FBE7B79913F4 /* NightscoutConfigProvider.swift in Sources */,
 				9825E5E923F0B8FA80C8C7C7 /* NightscoutConfigStateModel.swift in Sources */,
 				38A43598262E0E4900E80935 /* FetchAnnouncementsManager.swift in Sources */,
+				DD1745442C55C60E00211FAC /* AutosensSettingsDataFlow.swift in Sources */,
 				642F76A05A4FF530463A9FD0 /* NightscoutConfigRootView.swift in Sources */,
 				BD7DA9AC2AE06EB900601B20 /* BolusCalculatorConfigRootView.swift in Sources */,
 				AD3D2CD42CD01B9EB8F26522 /* PumpConfigDataFlow.swift in Sources */,
+				DD17452E2C55AE4800211FAC /* TargetBehavoirDataFlow.swift in Sources */,
 				53F2382465BF74DB1A967C8B /* PumpConfigProvider.swift in Sources */,
 				5D16287A969E64D18CE40E44 /* PumpConfigStateModel.swift in Sources */,
 				19D466AA29AA3099004D5F33 /* FPUConfigRootView.swift in Sources */,
 				E974172296125A5AE99E634C /* PumpConfigRootView.swift in Sources */,
+				DD1745502C55CA5500211FAC /* GeneralSettingsProvider.swift in Sources */,
 				581AC4392BE22ED10038760C /* JSONConverter.swift in Sources */,
 				CE7CA3522A064973004BE681 /* ListTempPresetsIntent.swift in Sources */,
 				BD4064D12C4ED26900582F43 /* CoreDataObserver.swift in Sources */,
@@ -3199,7 +3328,7 @@
 				19F95FF729F10FEE00314DDC /* StatStateModel.swift in Sources */,
 				385CEAC125F2EA52002D6D5B /* Announcement.swift in Sources */,
 				8B759CFCF47B392BB365C251 /* BasalProfileEditorDataFlow.swift in Sources */,
-				195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */,
+				195D80B42AF6973A00D25097 /* DynamicSettingsRootView.swift in Sources */,
 				389442CB25F65F7100FA1F27 /* NightscoutTreatment.swift in Sources */,
 				CE7CA3512A064973004BE681 /* ApplyTempPresetIntent.swift in Sources */,
 				FA630397F76B582C8D8681A7 /* BasalProfileEditorProvider.swift in Sources */,
@@ -3208,15 +3337,17 @@
 				38FEF3FA2737E42000574A46 /* BaseStateModel.swift in Sources */,
 				CC6C406E2ACDD69E009B8058 /* RawFetchedProfile.swift in Sources */,
 				385CEA8225F23DFD002D6D5B /* NightscoutStatus.swift in Sources */,
+				DD17453C2C55BFAD00211FAC /* AlgorithmVariousProvider.swift in Sources */,
 				F90692AA274B7AAE0037068D /* HealthKitManager.swift in Sources */,
 				38887CCE25F5725200944304 /* IOBEntry.swift in Sources */,
 				38E98A2425F52C9300C0CED0 /* Logger.swift in Sources */,
 				CA370FC152BC98B3D1832968 /* BasalProfileEditorRootView.swift in Sources */,
-				195D80BB2AF6980B00D25097 /* DynamicStateModel.swift in Sources */,
+				195D80BB2AF6980B00D25097 /* DynamicSettingsStateModel.swift in Sources */,
 				E00EEC0327368630002FF094 /* ServiceAssembly.swift in Sources */,
 				38192E07261BA9960094D973 /* FetchTreatmentsManager.swift in Sources */,
 				19012CDC291D2CB900FB8210 /* LoopStats.swift in Sources */,
 				6632A0DC746872439A858B44 /* ISFEditorDataFlow.swift in Sources */,
+				DD17454B2C55C62800211FAC /* AutosensSettingsRootView.swift in Sources */,
 				DBA5254DBB2586C98F61220C /* ISFEditorProvider.swift in Sources */,
 				BDF34EBE2C0A31D100D51995 /* CustomNotification.swift in Sources */,
 				BDC2EA472C3045AD00E5BBD0 /* Override.swift in Sources */,
@@ -3242,6 +3373,7 @@
 				38E98A2325F52C9300C0CED0 /* Signpost.swift in Sources */,
 				CE7CA3542A064973004BE681 /* TempPresetsIntentRequest.swift in Sources */,
 				F5F7E6C1B7F098F59EB67EC5 /* TargetsEditorDataFlow.swift in Sources */,
+				DD17453A2C55BFA600211FAC /* AlgorithmVariousDataFlow.swift in Sources */,
 				5075C1608E6249A51495C422 /* TargetsEditorProvider.swift in Sources */,
 				E13B7DAB2A435F57066AF02E /* TargetsEditorStateModel.swift in Sources */,
 				9702FF92A09C53942F20D7EA /* TargetsEditorRootView.swift in Sources */,
@@ -3303,7 +3435,7 @@
 				19F95FFA29F1102A00314DDC /* StatRootView.swift in Sources */,
 				0D9A5E34A899219C5C4CDFAF /* DataTableStateModel.swift in Sources */,
 				6BCF84DD2B16843A003AD46E /* LiveActitiyAttributes.swift in Sources */,
-				195D80B92AF697F700D25097 /* DynamicProvider.swift in Sources */,
+				195D80B92AF697F700D25097 /* DynamicSettingsProvider.swift in Sources */,
 				6BCF84DD2B16843A003AD46E /* LiveActitiyAttributes.swift in Sources */,
 				DD1745202C55523E00211FAC /* SMBSettingsDataFlow.swift in Sources */,
 				D6D02515BBFBE64FEBE89856 /* DataTableRootView.swift in Sources */,

+ 5 - 0
FreeAPS/Sources/Modules/AlgorithmVariousSettings/AlgorithmVariousDataFlow.swift

@@ -0,0 +1,5 @@
+enum AlgorithmVarious {
+    enum Config {}
+}
+
+protocol AlgorithmVariousProvider: Provider {}

+ 3 - 0
FreeAPS/Sources/Modules/AlgorithmVariousSettings/AlgorithmVariousProvider.swift

@@ -0,0 +1,3 @@
+extension AlgorithmVarious {
+    final class Provider: BaseProvider, AlgorithmVariousProvider {}
+}

+ 81 - 0
FreeAPS/Sources/Modules/AlgorithmVariousSettings/AlgorithmVariousStateModel.swift

@@ -0,0 +1,81 @@
+import SwiftUI
+
+extension AlgorithmVarious {
+    final class StateModel: BaseStateModel<Provider> {
+        @Injected() var settings: SettingsManager!
+        @Injected() var storage: FileStorage!
+
+        @Published var units: GlucoseUnits = .mgdL
+
+        @Published var maxDailySafetyMultiplier: Decimal = 3
+        @Published var currentBasalSafetyMultiplier: Decimal = 4
+        @Published var useCustomPeakTime: Bool = false
+        @Published var insulinPeakTime: Decimal = 75
+        @Published var skipNeutralTemps: Bool = false
+        @Published var unsuspendIfNoTemp: Bool = false
+        @Published var suspendZerosIOB: Bool = false
+        @Published var min5mCarbimpact: Decimal = 8
+        @Published var autotuneISFAdjustmentFraction: Decimal = 1.0
+        @Published var remainingCarbsFraction: Decimal = 1.0
+        @Published var remainingCarbsCap: Decimal = 90
+        @Published var noisyCGMTargetMultiplier: Decimal = 1.3
+
+        var preferences: Preferences {
+            settingsManager.preferences
+        }
+
+        override func subscribe() {
+            units = settingsManager.settings.units
+
+            maxDailySafetyMultiplier = settings.preferences.maxDailySafetyMultiplier
+            currentBasalSafetyMultiplier = settings.preferences.currentBasalSafetyMultiplier
+            useCustomPeakTime = settings.preferences.useCustomPeakTime
+            insulinPeakTime = settings.preferences.insulinPeakTime
+            skipNeutralTemps = settings.preferences.skipNeutralTemps
+            unsuspendIfNoTemp = settings.preferences.unsuspendIfNoTemp
+            suspendZerosIOB = settings.preferences.suspendZerosIOB
+            min5mCarbimpact = settings.preferences.min5mCarbimpact
+            autotuneISFAdjustmentFraction = settings.preferences.autotuneISFAdjustmentFraction
+            remainingCarbsFraction = settings.preferences.remainingCarbsFraction
+            remainingCarbsCap = settings.preferences.remainingCarbsCap
+            noisyCGMTargetMultiplier = settings.preferences.noisyCGMTargetMultiplier
+        }
+
+        var isSettingUnchanged: Bool {
+            preferences.maxDailySafetyMultiplier == maxDailySafetyMultiplier &&
+                preferences.currentBasalSafetyMultiplier == currentBasalSafetyMultiplier &&
+                preferences.useCustomPeakTime == useCustomPeakTime &&
+                preferences.insulinPeakTime == insulinPeakTime &&
+                preferences.skipNeutralTemps == skipNeutralTemps &&
+                preferences.unsuspendIfNoTemp == unsuspendIfNoTemp &&
+                preferences.suspendZerosIOB == suspendZerosIOB &&
+                preferences.min5mCarbimpact == min5mCarbimpact &&
+                preferences.autotuneISFAdjustmentFraction == autotuneISFAdjustmentFraction &&
+                preferences.remainingCarbsFraction == remainingCarbsFraction &&
+                preferences.remainingCarbsCap == remainingCarbsCap &&
+                preferences.noisyCGMTargetMultiplier == noisyCGMTargetMultiplier
+        }
+
+        func saveIfChanged() {
+            if !isSettingUnchanged {
+                var newSettings = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) ?? Preferences()
+
+                newSettings.maxDailySafetyMultiplier = maxDailySafetyMultiplier
+                newSettings.currentBasalSafetyMultiplier = currentBasalSafetyMultiplier
+                newSettings.useCustomPeakTime = useCustomPeakTime
+                newSettings.insulinPeakTime = insulinPeakTime
+                newSettings.skipNeutralTemps = skipNeutralTemps
+                newSettings.unsuspendIfNoTemp = unsuspendIfNoTemp
+                newSettings.suspendZerosIOB = suspendZerosIOB
+                newSettings.min5mCarbimpact = min5mCarbimpact
+                newSettings.autotuneISFAdjustmentFraction = autotuneISFAdjustmentFraction
+                newSettings.remainingCarbsFraction = remainingCarbsFraction
+                newSettings.remainingCarbsCap = remainingCarbsCap
+                newSettings.noisyCGMTargetMultiplier = noisyCGMTargetMultiplier
+
+                newSettings.timestamp = Date()
+                storage.save(newSettings, as: OpenAPS.Settings.preferences)
+            }
+        }
+    }
+}

+ 285 - 0
FreeAPS/Sources/Modules/AlgorithmVariousSettings/View/AlgorithmVariousRootView.swift

@@ -0,0 +1,285 @@
+import SwiftUI
+import Swinject
+
+extension AlgorithmVarious {
+    struct RootView: BaseView {
+        let resolver: Resolver
+        @StateObject var state = StateModel()
+        @State private var shouldDisplayHint: Bool = false
+        @State var hintDetent = PresentationDetent.large
+        @State var selectedVerboseHint: String?
+        @State var hintLabel: String?
+        @State private var decimalPlaceholder: Decimal = 0.0
+        @State private var booleanPlaceholder: Bool = false
+
+        @Environment(\.colorScheme) var colorScheme
+        @EnvironmentObject var appIcons: Icons
+
+        private var color: LinearGradient {
+            colorScheme == .dark ? LinearGradient(
+                gradient: Gradient(colors: [
+                    Color.bgDarkBlue,
+                    Color.bgDarkerDarkBlue
+                ]),
+                startPoint: .top,
+                endPoint: .bottom
+            )
+                :
+                LinearGradient(
+                    gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
+                    startPoint: .top,
+                    endPoint: .bottom
+                )
+        }
+
+        var body: some View {
+            List {
+                SettingInputSection(
+                    decimalValue: $state.maxDailySafetyMultiplier,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Max Daily Safety Multiplier", comment: "Max Daily Safety Multiplier")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    ),
+                    headerText: "Miscellaneous"
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.currentBasalSafetyMultiplier,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString(
+                                "Current Basal Safety Multiplier",
+                                comment: "Current Basal Safety Multiplier"
+                            )
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.insulinPeakTime,
+                    booleanValue: $state.useCustomPeakTime,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Use Custom Peak Time", comment: "Use Custom Peak Time")
+                        }
+                    ),
+                    type: .conditionalDecimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.skipNeutralTemps,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Skip Neutral Temps", comment: "Skip Neutral Temps")
+                        }
+                    ),
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.unsuspendIfNoTemp,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Unsuspend If No Temp", comment: "Unsuspend If No Temp")
+                        }
+                    ),
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.suspendZerosIOB,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Suspend Zeros IOB", comment: "Suspend Zeros IOB")
+                        }
+                    ),
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.min5mCarbimpact,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Min 5m Carbimpact", comment: "Min 5m Carbimpact")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.autotuneISFAdjustmentFraction,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString(
+                                "Autotune ISF Adjustment Fraction",
+                                comment: "Autotune ISF Adjustment Fraction"
+                            )
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.remainingCarbsFraction,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Remaining Carbs Fraction", comment: "Remaining Carbs Fraction")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.remainingCarbsCap,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Remaining Carbs Cap", comment: "Remaining Carbs Cap")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.noisyCGMTargetMultiplier,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Noisy CGM Target Multiplier", comment: "Noisy CGM Target Multiplier")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+            }
+            .sheet(isPresented: $shouldDisplayHint) {
+                SettingInputHintView(
+                    hintDetent: $hintDetent,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    hintLabel: hintLabel ?? "",
+                    hintText: selectedVerboseHint ?? "",
+                    sheetTitle: "Hint"
+                )
+            }
+            .scrollContentBackground(.hidden).background(color)
+            .onAppear(perform: configureView)
+            .navigationTitle("Various")
+            .navigationBarTitleDisplayMode(.automatic)
+            .onDisappear {
+                state.saveIfChanged()
+            }
+        }
+    }
+}

+ 5 - 0
FreeAPS/Sources/Modules/AutosensSettings/AutosensSettingsDataFlow.swift

@@ -0,0 +1,5 @@
+enum AutosensSettings {
+    enum Config {}
+}
+
+protocol AutosensSettingsProvider: Provider {}

+ 3 - 0
FreeAPS/Sources/Modules/AutosensSettings/AutosensSettingsProvider.swift

@@ -0,0 +1,3 @@
+extension AutosensSettings {
+    final class Provider: BaseProvider, AutosensSettingsProvider {}
+}

+ 45 - 0
FreeAPS/Sources/Modules/AutosensSettings/AutosensSettingsStateModel.swift

@@ -0,0 +1,45 @@
+import SwiftUI
+
+extension AutosensSettings {
+    final class StateModel: BaseStateModel<Provider> {
+        @Injected() var settings: SettingsManager!
+        @Injected() var storage: FileStorage!
+
+        @Published var units: GlucoseUnits = .mgdL
+
+        @Published var autosensMax: Decimal = 1.2
+        @Published var autosensMin: Decimal = 0.7
+        @Published var rewindResetsAutosens: Bool = true
+
+        var preferences: Preferences {
+            settingsManager.preferences
+        }
+
+        override func subscribe() {
+            units = settingsManager.settings.units
+
+            autosensMax = settings.preferences.autosensMax
+            autosensMin = settings.preferences.autosensMin
+            rewindResetsAutosens = settings.preferences.rewindResetsAutosens
+        }
+
+        var isSettingUnchanged: Bool {
+            preferences.autosensMax == autosensMax &&
+                preferences.autosensMin == autosensMin &&
+                preferences.rewindResetsAutosens == rewindResetsAutosens
+        }
+
+        func saveIfChanged() {
+            if !isSettingUnchanged {
+                var newSettings = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) ?? Preferences()
+
+                newSettings.autosensMax = autosensMax
+                newSettings.autosensMin = autosensMin
+                newSettings.rewindResetsAutosens = rewindResetsAutosens
+
+                newSettings.timestamp = Date()
+                storage.save(newSettings, as: OpenAPS.Settings.preferences)
+            }
+        }
+    }
+}

+ 116 - 0
FreeAPS/Sources/Modules/AutosensSettings/View/AutosensSettingsRootView.swift

@@ -0,0 +1,116 @@
+import SwiftUI
+import Swinject
+
+extension AutosensSettings {
+    struct RootView: BaseView {
+        let resolver: Resolver
+        @StateObject var state = StateModel()
+        @State private var shouldDisplayHint: Bool = false
+        @State var hintDetent = PresentationDetent.large
+        @State var selectedVerboseHint: String?
+        @State var hintLabel: String?
+        @State private var decimalPlaceholder: Decimal = 0.0
+        @State private var booleanPlaceholder: Bool = false
+
+        @Environment(\.colorScheme) var colorScheme
+        @EnvironmentObject var appIcons: Icons
+
+        private var color: LinearGradient {
+            colorScheme == .dark ? LinearGradient(
+                gradient: Gradient(colors: [
+                    Color.bgDarkBlue,
+                    Color.bgDarkerDarkBlue
+                ]),
+                startPoint: .top,
+                endPoint: .bottom
+            )
+                :
+                LinearGradient(
+                    gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
+                    startPoint: .top,
+                    endPoint: .bottom
+                )
+        }
+
+        var body: some View {
+            List {
+                SettingInputSection(
+                    decimalValue: $state.autosensMax,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Autosens Max", comment: "Autosens Max")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    ),
+                    headerText: "Glucose Deviations Algorithm"
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.autosensMin,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Autosens Max", comment: "Autosens Max")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.rewindResetsAutosens,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Rewind Resets Autosens", comment: "Rewind Resets Autosens")
+                        }
+                    ),
+                    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"
+                    )
+                )
+            }
+            .sheet(isPresented: $shouldDisplayHint) {
+                SettingInputHintView(
+                    hintDetent: $hintDetent,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    hintLabel: hintLabel ?? "",
+                    hintText: selectedVerboseHint ?? "",
+                    sheetTitle: "Hint"
+                )
+            }
+            .scrollContentBackground(.hidden).background(color)
+            .onAppear(perform: configureView)
+            .navigationTitle("Autosens")
+            .navigationBarTitleDisplayMode(.automatic)
+            .onDisappear {
+                state.saveIfChanged()
+            }
+        }
+    }
+}

+ 0 - 5
FreeAPS/Sources/Modules/Dynamic/DynamicDataFlow.swift

@@ -1,5 +0,0 @@
-enum Dynamic {
-    enum Config {}
-}
-
-protocol DynamicProvider: Provider {}

+ 0 - 3
FreeAPS/Sources/Modules/Dynamic/DynamicProvider.swift

@@ -1,3 +0,0 @@
-extension Dynamic {
-    final class Provider: BaseProvider, DynamicProvider {}
-}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 211
FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift


+ 5 - 0
FreeAPS/Sources/Modules/DynamicSettings/DynamicSettingsDataFlow.swift

@@ -0,0 +1,5 @@
+enum DynamicSettings {
+    enum Config {}
+}
+
+protocol DynamicSettingsProvider: Provider {}

+ 3 - 0
FreeAPS/Sources/Modules/DynamicSettings/DynamicSettingsProvider.swift

@@ -0,0 +1,3 @@
+extension DynamicSettings {
+    final class Provider: BaseProvider, DynamicSettingsProvider {}
+}

+ 1 - 1
FreeAPS/Sources/Modules/Dynamic/DynamicStateModel.swift

@@ -1,6 +1,6 @@
 import SwiftUI
 
-extension Dynamic {
+extension DynamicSettings {
     final class StateModel: BaseStateModel<Provider> {
         @Injected() var settings: SettingsManager!
         @Injected() var storage: FileStorage!

+ 218 - 0
FreeAPS/Sources/Modules/DynamicSettings/View/DynamicSettingsRootView.swift

@@ -0,0 +1,218 @@
+import SwiftUI
+import Swinject
+
+extension DynamicSettings {
+    struct RootView: BaseView {
+        let resolver: Resolver
+        @StateObject var state = StateModel()
+        @State private var shouldDisplayHint: Bool = false
+        @State var hintDetent = PresentationDetent.large
+        @State var selectedVerboseHint: String?
+        @State var hintLabel: String?
+        @State private var decimalPlaceholder: Decimal = 0.0
+        @State private var booleanPlaceholder: Bool = false
+
+        private var conversionFormatter: NumberFormatter {
+            let formatter = NumberFormatter()
+            formatter.numberStyle = .decimal
+            formatter.maximumFractionDigits = 1
+
+            return formatter
+        }
+
+        @Environment(\.colorScheme) var colorScheme
+        var color: LinearGradient {
+            colorScheme == .dark ? LinearGradient(
+                gradient: Gradient(colors: [
+                    Color.bgDarkBlue,
+                    Color.bgDarkerDarkBlue
+                ]),
+                startPoint: .top,
+                endPoint: .bottom
+            )
+                :
+                LinearGradient(
+                    gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
+                    startPoint: .top,
+                    endPoint: .bottom
+                )
+        }
+
+        private var formatter: NumberFormatter {
+            let formatter = NumberFormatter()
+            formatter.numberStyle = .decimal
+            return formatter
+        }
+
+        private var glucoseFormatter: NumberFormatter {
+            let formatter = NumberFormatter()
+            formatter.numberStyle = .decimal
+            if state.unit == .mmolL {
+                formatter.maximumFractionDigits = 1
+            } else { formatter.maximumFractionDigits = 0 }
+            formatter.roundingMode = .halfUp
+            return formatter
+        }
+
+        var body: some View {
+            List {
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.useNewFormula,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = "Activate Dynamic Sensitivity (ISF)"
+                        }
+                    ),
+                    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"
+                )
+
+                if state.useNewFormula {
+                    SettingInputSection(
+                        decimalValue: $decimalPlaceholder,
+                        booleanValue: $state.enableDynamicCR,
+                        shouldDisplayHint: $shouldDisplayHint,
+                        selectedVerboseHint: Binding(
+                            get: { selectedVerboseHint },
+                            set: {
+                                selectedVerboseHint = $0
+                                hintLabel = "Activate Dynamic Carb Ratio (CR)"
+                            }
+                        ),
+                        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"
+                    )
+
+                    SettingInputSection(
+                        decimalValue: $decimalPlaceholder,
+                        booleanValue: $state.sigmoid,
+                        shouldDisplayHint: $shouldDisplayHint,
+                        selectedVerboseHint: Binding(
+                            get: { selectedVerboseHint },
+                            set: {
+                                selectedVerboseHint = $0
+                                hintLabel = "Use Sigmoid Formula"
+                            }
+                        ),
+                        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"
+                    )
+
+                    if !state.sigmoid {
+                        SettingInputSection(
+                            decimalValue: $state.adjustmentFactor,
+                            booleanValue: $booleanPlaceholder,
+                            shouldDisplayHint: $shouldDisplayHint,
+                            selectedVerboseHint: Binding(
+                                get: { selectedVerboseHint },
+                                set: {
+                                    selectedVerboseHint = $0
+                                    hintLabel = "Adjustment Factor"
+                                }
+                            ),
+                            type: .decimal,
+                            label: "Adjustment Factor",
+                            miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
+                            verboseHint: "Adjustment Factor for logarithmic dynamic sensitvity... bla bla bla"
+                        )
+                    } else {
+                        SettingInputSection(
+                            decimalValue: $state.adjustmentFactorSigmoid,
+                            booleanValue: $booleanPlaceholder,
+                            shouldDisplayHint: $shouldDisplayHint,
+                            selectedVerboseHint: Binding(
+                                get: { selectedVerboseHint },
+                                set: {
+                                    selectedVerboseHint = $0
+                                    hintLabel = "Sigmoid Adjustment Factor"
+                                }
+                            ),
+                            type: .decimal,
+                            label: "Sigmoid Adjustment Factor",
+                            miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
+                            verboseHint: "Sigmoid Adjustment Factor… should be 0.5… bla bla ba"
+                        )
+                    }
+
+                    SettingInputSection(
+                        decimalValue: $state.weightPercentage,
+                        booleanValue: $booleanPlaceholder,
+                        shouldDisplayHint: $shouldDisplayHint,
+                        selectedVerboseHint: Binding(
+                            get: { selectedVerboseHint },
+                            set: {
+                                selectedVerboseHint = $0
+                                hintLabel = "Weighted Average of TDD"
+                            }
+                        ),
+                        type: .decimal,
+                        label: "Weighted Average of TDD",
+                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
+                        verboseHint: "Weight of past 24 hours"
+                    )
+
+                    SettingInputSection(
+                        decimalValue: $decimalPlaceholder,
+                        booleanValue: $state.tddAdjBasal,
+                        shouldDisplayHint: $shouldDisplayHint,
+                        selectedVerboseHint: Binding(
+                            get: { selectedVerboseHint },
+                            set: {
+                                selectedVerboseHint = $0
+                                hintLabel = "Adjust Basal"
+                            }
+                        ),
+                        type: .boolean,
+                        label: "Adjust Basal",
+                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
+                        verboseHint: "Adjust basal dynamically… bla bla"
+                    )
+
+                    SettingInputSection(
+                        decimalValue: $state.threshold_setting,
+                        booleanValue: $booleanPlaceholder,
+                        shouldDisplayHint: $shouldDisplayHint,
+                        selectedVerboseHint: Binding(
+                            get: { selectedVerboseHint },
+                            set: {
+                                selectedVerboseHint = $0
+                                hintLabel = "Threshold Setting"
+                            }
+                        ),
+                        type: .decimal,
+                        label: "Threshold Setting",
+                        miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
+                        verboseHint: "BG threshold"
+                    )
+                }
+            }
+            .sheet(isPresented: $shouldDisplayHint) {
+                SettingInputHintView(
+                    hintDetent: $hintDetent,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    hintLabel: hintLabel ?? "",
+                    hintText: selectedVerboseHint ?? "",
+                    sheetTitle: "Hint"
+                )
+            }
+            .scrollContentBackground(.hidden).background(color)
+            .onAppear(perform: configureView)
+            .navigationBarTitle("Dynamic Settings")
+            .navigationBarTitleDisplayMode(.automatic)
+            .onDisappear {
+                state.saveIfChanged()
+            }
+        }
+    }
+}

+ 5 - 0
FreeAPS/Sources/Modules/GeneralSettings/GeneralSettingsDataFlow.swift

@@ -0,0 +1,5 @@
+enum GeneralSettings {
+    enum Config {}
+}
+
+protocol GeneralSettingsProvider: Provider {}

+ 75 - 0
FreeAPS/Sources/Modules/GeneralSettings/GeneralSettingsProvider.swift

@@ -0,0 +1,75 @@
+import Foundation
+
+extension GeneralSettings {
+    final class Provider: BaseProvider, GeneralSettingsProvider {
+        @Injected() private var settingsManager: SettingsManager!
+
+        func migrateUnits() {
+            migrateTargets()
+            migrateISF()
+        }
+
+        private func migrateTargets() {
+            let profile = storage.retrieve(OpenAPS.Settings.bgTargets, as: BGTargets.self)
+                ?? BGTargets(from: OpenAPS.defaults(for: OpenAPS.Settings.bgTargets))
+                ?? BGTargets(units: .mmolL, userPrefferedUnits: .mmolL, targets: [])
+
+            let units = settingsManager.settings.units
+            guard units != profile.units else { return }
+
+            let targets = profile.targets.map { target -> BGTargetEntry in
+                if units == .mmolL {
+                    return BGTargetEntry(
+                        low: Decimal(round(Double(target.low.asMmolL) * 10) / 10),
+                        high: Decimal(round(Double(target.high.asMmolL) * 10) / 10),
+                        start: target.start,
+                        offset: target.offset
+                    )
+                } else {
+                    return BGTargetEntry(
+                        low: Decimal(round(Double(target.low.asMgdL))),
+                        high: Decimal(round(Double(target.high.asMgdL))),
+                        start: target.start,
+                        offset: target.offset
+                    )
+                }
+            }
+
+            let newProfile = BGTargets(units: units, userPrefferedUnits: units, targets: targets)
+            storage.save(newProfile, as: OpenAPS.Settings.bgTargets)
+        }
+
+        private func migrateISF() {
+            let profile = storage.retrieve(OpenAPS.Settings.insulinSensitivities, as: InsulinSensitivities.self)
+                ?? InsulinSensitivities(from: OpenAPS.defaults(for: OpenAPS.Settings.insulinSensitivities))
+                ?? InsulinSensitivities(
+                    units: .mmolL,
+                    userPrefferedUnits: .mmolL,
+                    sensitivities: []
+                )
+            let units = settingsManager.settings.units
+            guard units != profile.units else { return }
+
+            let sensitivities = profile.sensitivities.map { item -> InsulinSensitivityEntry in
+
+                if units == .mmolL {
+                    return InsulinSensitivityEntry(
+                        sensitivity: Decimal(round(Double(item.sensitivity.asMmolL) * 10) / 10),
+                        offset: item.offset,
+                        start: item.start
+                    )
+                } else {
+                    return InsulinSensitivityEntry(
+                        sensitivity: Decimal(round(Double(item.sensitivity.asMgdL))),
+                        offset: item.offset,
+                        start: item.start
+                    )
+                }
+            }
+
+            let newProfile = InsulinSensitivities(units: units, userPrefferedUnits: units, sensitivities: sensitivities)
+
+            storage.save(newProfile, as: OpenAPS.Settings.insulinSensitivities)
+        }
+    }
+}

+ 47 - 0
FreeAPS/Sources/Modules/GeneralSettings/GeneralSettingsStateModel.swift

@@ -0,0 +1,47 @@
+import SwiftUI
+
+extension GeneralSettings {
+    final class StateModel: BaseStateModel<Provider> {
+        @Injected() var settings: SettingsManager!
+        @Injected() var storage: FileStorage!
+
+        @Published var units: GlucoseUnits = .mgdL
+        @Published var unitsIndex = 1
+
+        @Published var maxIOB: Decimal = 0
+        @Published var maxCOB: Decimal = 120
+
+        var preferences: Preferences {
+            settingsManager.preferences
+        }
+
+        override func subscribe() {
+            units = settingsManager.settings.units
+            subscribeSetting(\.units, on: $unitsIndex.map { $0 == 0 ? GlucoseUnits.mgdL : .mmolL }) {
+                unitsIndex = $0 == .mgdL ? 0 : 1
+            } didSet: { [weak self] _ in
+                self?.provider.migrateUnits()
+            }
+
+            maxIOB = settings.preferences.maxIOB
+            maxCOB = settings.preferences.maxCOB
+        }
+
+        var isSettingUnchanged: Bool {
+            preferences.maxIOB == maxIOB &&
+                preferences.maxCOB == maxCOB
+        }
+
+        func saveIfChanged() {
+            if !isSettingUnchanged {
+                var newSettings = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) ?? Preferences()
+
+                newSettings.maxIOB = maxIOB
+                newSettings.maxCOB = maxCOB
+
+                newSettings.timestamp = Date()
+                storage.save(newSettings, as: OpenAPS.Settings.preferences)
+            }
+        }
+    }
+}

Файловите разлики са ограничени, защото са твърде много
+ 105 - 0
FreeAPS/Sources/Modules/GeneralSettings/View/GeneralSettingsRootView.swift


+ 1 - 0
FreeAPS/Sources/Modules/SMBSettings/SMBSettingsStateModel.swift

@@ -6,6 +6,7 @@ extension SMBSettings {
         @Injected() var storage: FileStorage!
 
         @Published var units: GlucoseUnits = .mgdL
+
         @Published var enableSMBAlways: Bool = false
         @Published var maxDeltaBGthreshold: Decimal = 0.2
         @Published var enableSMBWithCOB: Bool = false

+ 10 - 7
FreeAPS/Sources/Modules/SMBSettings/View/SMBSettingsView.swift

@@ -1,6 +1,3 @@
-import HealthKit
-import LoopKit
-import LoopKitUI
 import SwiftUI
 import Swinject
 
@@ -51,7 +48,10 @@ extension SMBSettings {
                     type: .boolean,
                     label: NSLocalizedString("Enable SMB Always", comment: "Enable SMB Always"),
                     miniHint: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.",
-                    verboseHint: "Enable SMB always bla bla bla",
+                    verboseHint: NSLocalizedString(
+                        "Defaults to false. When true, always enable supermicrobolus (unless disabled by high temptarget).",
+                        comment: "Enable SMB Always"
+                    ),
                     headerText: "Super-Micro-Bolus"
                 )
 
@@ -283,6 +283,8 @@ extension SMBSettings {
                         comment: "SMB Interval"
                     )
                 )
+
+                Text("Bolus Increment removed – should be pump derived!")
             }
             .sheet(isPresented: $shouldDisplayHint) {
                 SettingInputHintView(
@@ -294,11 +296,12 @@ extension SMBSettings {
                 )
             }
             .scrollContentBackground(.hidden).background(color)
+            .onAppear(perform: configureView)
             .navigationTitle("SMB Settings")
             .navigationBarTitleDisplayMode(.automatic)
-//            .onDisappear {
-//                state.saveIfChanged()
-//            }
+            .onDisappear {
+                state.saveIfChanged()
+            }
         }
     }
 }

+ 3 - 2
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -102,8 +102,9 @@ extension Settings {
                     header: Text("Trio Configuration"),
                     content: {
                         Text("Devices").navigationLink(to: .devices, from: self)
-                        Text("Therapy Settings").navigationLink(to: .therapySettings, from: self)
-                        Text("Feature Settings").navigationLink(to: .featureSettings, from: self)
+                        Text("Therapy").navigationLink(to: .therapySettings, from: self)
+                        Text("Algorithm").navigationLink(to: .algorithmSettings, from: self)
+                        Text("Features").navigationLink(to: .featureSettings, from: self)
                         Text("Notifications").navigationLink(to: .notificationSettings, from: self)
                         Text("Services").navigationLink(to: .serviceSettings, from: self)
                     }

+ 51 - 0
FreeAPS/Sources/Modules/Settings/View/Subviews/AlgorithmSettings.swift

@@ -0,0 +1,51 @@
+//
+//  FeatureSettingsView.swift
+//  FreeAPS
+//
+//  Created by Deniz Cengiz on 26.07.24.
+//
+import Foundation
+import SwiftUI
+import Swinject
+
+struct AlgorithmSettings: BaseView {
+    let resolver: Resolver
+
+    @ObservedObject var state: Settings.StateModel
+
+    @Environment(\.colorScheme) var colorScheme
+    var color: LinearGradient {
+        colorScheme == .dark ? LinearGradient(
+            gradient: Gradient(colors: [
+                Color.bgDarkBlue,
+                Color.bgDarkerDarkBlue
+            ]),
+            startPoint: .top,
+            endPoint: .bottom
+        )
+            :
+            LinearGradient(
+                gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
+                startPoint: .top,
+                endPoint: .bottom
+            )
+    }
+
+    var body: some View {
+        Form {
+            Section(
+                header: Text("Oref Algorithm"),
+                content: {
+                    Text("Autosens").navigationLink(to: .autosensSettings, from: self)
+                    Text("Super Micro Bolus").navigationLink(to: .smbSettings, from: self)
+                    Text("Dynamic Sensitivity").navigationLink(to: .dynamicISF, from: self)
+                    Text("Target Behavior").navigationLink(to: .targetBehavior, from: self)
+                    Text("Various").navigationLink(to: .algorithmVarious, from: self)
+                }
+            ).listRowBackground(Color.chart)
+        }
+        .scrollContentBackground(.hidden).background(color)
+        .navigationTitle("Algorithm Settings")
+        .navigationBarTitleDisplayMode(.automatic)
+    }
+}

+ 0 - 10
FreeAPS/Sources/Modules/Settings/View/Subviews/FeatureSettingsView.swift

@@ -34,16 +34,6 @@ struct FeatureSettingsView: BaseView {
     var body: some View {
         Form {
             Section(
-                header: Text("Oref Algorithm"),
-                content: {
-                    Text("Preferences (to be omitted").navigationLink(to: .preferencesEditor, from: self)
-                    Text("Autosens Settings").navigationLink(to: .preferencesEditor, from: self)
-                    Text("Super-Micro-Bolus (SMB) Settings").navigationLink(to: .smbSettings, from: self)
-                    Text("Dynamic Settings").navigationLink(to: .dynamicISF, from: self)
-                }
-            ).listRowBackground(Color.chart)
-
-            Section(
                 header: Text("Trio Personalization"),
                 content: {
                     Text("Bolus Calculator").navigationLink(to: .bolusCalculatorConfig, from: self)

+ 8 - 0
FreeAPS/Sources/Modules/Settings/View/Subviews/TherapySettingsView.swift

@@ -34,6 +34,14 @@ struct TherapySettingsView: BaseView {
     var body: some View {
         Form {
             Section(
+                header: Text("Basic Settings"),
+                content: {
+                    Text("General").navigationLink(to: .generalSettings, from: self)
+                }
+            )
+            .listRowBackground(Color.chart)
+
+            Section(
                 header: Text("Basic Insulin Rates & Targets"),
                 content: {
                     Text("Basal Rates").navigationLink(to: .basalProfileEditor, from: self)

+ 3 - 0
FreeAPS/Sources/Modules/TargetBehavoir/TargetBehaviorProvider.swift

@@ -0,0 +1,3 @@
+extension TargetBehavoir {
+    final class Provider: BaseProvider, TargetBehaviorProvider {}
+}

+ 5 - 0
FreeAPS/Sources/Modules/TargetBehavoir/TargetBehavoirDataFlow.swift

@@ -0,0 +1,5 @@
+enum TargetBehavoir {
+    enum Config {}
+}
+
+protocol TargetBehaviorProvider: Provider {}

+ 56 - 0
FreeAPS/Sources/Modules/TargetBehavoir/TargetBehavoirStateModel.swift

@@ -0,0 +1,56 @@
+import SwiftUI
+
+extension TargetBehavoir {
+    final class StateModel: BaseStateModel<Provider> {
+        @Injected() var settings: SettingsManager!
+        @Injected() var storage: FileStorage!
+
+        @Published var units: GlucoseUnits = .mgdL
+
+        @Published var highTemptargetRaisesSensitivity: Bool = false
+        @Published var lowTemptargetLowersSensitivity: Bool = false
+        @Published var sensitivityRaisesTarget: Bool = false
+        @Published var resistanceLowersTarget: Bool = false
+        @Published var halfBasalExerciseTarget: Decimal = 160
+
+        var preferences: Preferences {
+            settingsManager.preferences
+        }
+
+        override func subscribe() {
+            units = settingsManager.settings.units
+
+            highTemptargetRaisesSensitivity = settings.preferences.highTemptargetRaisesSensitivity
+            lowTemptargetLowersSensitivity = settings.preferences.lowTemptargetLowersSensitivity
+            sensitivityRaisesTarget = settings.preferences.sensitivityRaisesTarget
+            resistanceLowersTarget = settings.preferences.resistanceLowersTarget
+            halfBasalExerciseTarget = settings.preferences.halfBasalExerciseTarget
+
+            halfBasalExerciseTarget = units == .mmolL ? settings.preferences.halfBasalExerciseTarget.asMmolL : settings
+                .preferences.halfBasalExerciseTarget
+        }
+
+        var isSettingUnchanged: Bool {
+            preferences.highTemptargetRaisesSensitivity == highTemptargetRaisesSensitivity &&
+                preferences.lowTemptargetLowersSensitivity == lowTemptargetLowersSensitivity &&
+                preferences.sensitivityRaisesTarget == sensitivityRaisesTarget &&
+                preferences.resistanceLowersTarget == resistanceLowersTarget &&
+                preferences.halfBasalExerciseTarget == halfBasalExerciseTarget
+        }
+
+        func saveIfChanged() {
+            if !isSettingUnchanged {
+                var newSettings = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) ?? Preferences()
+
+                newSettings.highTemptargetRaisesSensitivity = highTemptargetRaisesSensitivity
+                newSettings.lowTemptargetLowersSensitivity = lowTemptargetLowersSensitivity
+                newSettings.sensitivityRaisesTarget = sensitivityRaisesTarget
+                newSettings.resistanceLowersTarget = resistanceLowersTarget
+                newSettings.halfBasalExerciseTarget = halfBasalExerciseTarget
+
+                newSettings.timestamp = Date()
+                storage.save(newSettings, as: OpenAPS.Settings.preferences)
+            }
+        }
+    }
+}

+ 168 - 0
FreeAPS/Sources/Modules/TargetBehavoir/View/TargetBehavoirRootView.swift

@@ -0,0 +1,168 @@
+import SwiftUI
+import Swinject
+
+extension TargetBehavoir {
+    struct RootView: BaseView {
+        let resolver: Resolver
+        @StateObject var state = StateModel()
+        @State private var shouldDisplayHint: Bool = false
+        @State var hintDetent = PresentationDetent.large
+        @State var selectedVerboseHint: String?
+        @State var hintLabel: String?
+        @State private var decimalPlaceholder: Decimal = 0.0
+        @State private var booleanPlaceholder: Bool = false
+
+        @Environment(\.colorScheme) var colorScheme
+        @EnvironmentObject var appIcons: Icons
+
+        private var color: LinearGradient {
+            colorScheme == .dark ? LinearGradient(
+                gradient: Gradient(colors: [
+                    Color.bgDarkBlue,
+                    Color.bgDarkerDarkBlue
+                ]),
+                startPoint: .top,
+                endPoint: .bottom
+            )
+                :
+                LinearGradient(
+                    gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
+                    startPoint: .top,
+                    endPoint: .bottom
+                )
+        }
+
+        var body: some View {
+            List {
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.highTemptargetRaisesSensitivity,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString(
+                                "High Temptarget Raises Sensitivity",
+                                comment: "High Temptarget Raises Sensitivity"
+                            )
+                        }
+                    ),
+                    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"
+                    ),
+                    headerText: "Algorithmic Target Settings"
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.lowTemptargetLowersSensitivity,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString(
+                                "Low Temptarget Lowers Sensitivity",
+                                comment: "Low Temptarget Lowers Sensitivity"
+                            )
+                        }
+                    ),
+                    type: .boolean,
+                    label: NSLocalizedString(
+                        "Low Temptarget Lowers Sensitivity",
+                        comment: "Low Temptarget 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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.sensitivityRaisesTarget,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Sensitivity Raises Target", comment: "Sensitivity Raises Target")
+                        }
+                    ),
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $decimalPlaceholder,
+                    booleanValue: $state.resistanceLowersTarget,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Resistance Lowers Target", comment: "Resistance Lowers Target")
+                        }
+                    ),
+                    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"
+                    )
+                )
+
+                SettingInputSection(
+                    decimalValue: $state.halfBasalExerciseTarget,
+                    booleanValue: $booleanPlaceholder,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    selectedVerboseHint: Binding(
+                        get: { selectedVerboseHint },
+                        set: {
+                            selectedVerboseHint = $0
+                            hintLabel = NSLocalizedString("Half Basal Exercise Target", comment: "Half Basal Exercise Target")
+                        }
+                    ),
+                    type: .decimal,
+                    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"
+                    )
+                )
+            }
+            .sheet(isPresented: $shouldDisplayHint) {
+                SettingInputHintView(
+                    hintDetent: $hintDetent,
+                    shouldDisplayHint: $shouldDisplayHint,
+                    hintLabel: hintLabel ?? "",
+                    hintText: selectedVerboseHint ?? "",
+                    sheetTitle: "Hint"
+                )
+            }
+            .scrollContentBackground(.hidden).background(color)
+            .onAppear(perform: configureView)
+            .navigationTitle("Target Behavior")
+            .navigationBarTitleDisplayMode(.automatic)
+            .onDisappear {
+                state.saveIfChanged()
+            }
+        }
+    }
+}

+ 16 - 1
FreeAPS/Sources/Router/Screen.swift

@@ -37,10 +37,15 @@ enum Screen: Identifiable, Hashable {
     case shortcutsConfig
     case devices
     case therapySettings
+    case algorithmSettings
     case featureSettings
     case notificationSettings
     case serviceSettings
+    case autosensSettings
     case smbSettings
+    case targetBehavior
+    case algorithmVarious
+    case generalSettings
 
     var id: Int { String(reflecting: self).hashValue }
 }
@@ -109,7 +114,7 @@ extension Screen {
         case .bolusCalculatorConfig:
             BolusCalculatorConfig.RootView(resolver: resolver)
         case .dynamicISF:
-            Dynamic.RootView(resolver: resolver)
+            DynamicSettings.RootView(resolver: resolver)
         case .calibrations:
             Calibrations.RootView(resolver: resolver)
         case .shortcutsConfig:
@@ -118,14 +123,24 @@ extension Screen {
             DevicesView(resolver: resolver, state: Settings.StateModel())
         case .therapySettings:
             TherapySettingsView(resolver: resolver, state: Settings.StateModel())
+        case .algorithmSettings:
+            AlgorithmSettings(resolver: resolver, state: Settings.StateModel())
         case .featureSettings:
             FeatureSettingsView(resolver: resolver, state: Settings.StateModel())
         case .notificationSettings:
             NotificationsView(resolver: resolver, state: Settings.StateModel())
         case .serviceSettings:
             ServicesView(resolver: resolver, state: Settings.StateModel())
+        case .autosensSettings:
+            AutosensSettings.RootView(resolver: resolver)
         case .smbSettings:
             SMBSettings.RootView(resolver: resolver)
+        case .targetBehavior:
+            TargetBehavoir.RootView(resolver: resolver)
+        case .algorithmVarious:
+            AlgorithmVarious.RootView(resolver: resolver)
+        case .generalSettings:
+            GeneralSettings.RootView(resolver: resolver)
         }
     }
 

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

@@ -48,7 +48,7 @@ struct SettingInputSection: View {
                             Toggle(isOn: $booleanValue) {
                                 Text(label)
                             }
-                        }
+                        }.padding(.top)
                     } else if type == .conditionalDecimal, let secondLabel = conditionalLabel {
                         HStack {
                             Toggle(isOn: $booleanValue) {
@@ -88,7 +88,7 @@ struct SettingInputSection: View {
                                     Image(systemName: "questionmark.circle")
                                 }
                             }
-                        )
+                        ).buttonStyle(BorderlessButtonStyle())
                     }.padding(type == .boolean ? .vertical : .bottom)
                 }
             },