Jelajahi Sumber

Merge pull request #478 from nightscout/onboarding-improvements

Onboarding Part 4 — Improvements, Partial Completion Views
Sam King 1 tahun lalu
induk
melakukan
7ded0d20a7
16 mengubah file dengan 878 tambahan dan 427 penghapusan
  1. 29 9
      Trio.xcodeproj/project.pbxproj
  2. 58 0
      Trio/Sources/Localizations/Main/Localizable.xcstrings
  3. 1 7
      Trio/Sources/Modules/Onboarding/OnboardingStateModel.swift
  4. 290 126
      Trio/Sources/Modules/Onboarding/View/OnboardingRootView.swift
  5. 63 0
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/AlgorithmSettings/AlgorithmSettingsContentsStepView.swift
  6. 62 0
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/AlgorithmSettings/AlgorithmSettingsImportantNotesStepView.swift
  7. 0 70
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/AlgorithmSettings/AlgorithmSettingsStepView.swift
  8. 52 65
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/CompletedStepView.swift
  9. 10 50
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/OverviewStepView.swift
  10. 53 0
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuide/StartupForceCloseWarningStepView.swift
  11. 45 0
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuide/StartupGuideStepView.swift
  12. 67 0
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuide/StartupReturningUserStepView.swift
  13. 0 71
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuideStepView.swift
  14. 22 18
      Trio/Sources/Modules/Onboarding/View/OnboardingSteps/WelcomeStepView.swift
  15. 7 0
      Trio/Sources/Modules/Onboarding/View/OnboardingView+AlgorithmUtil.swift
  16. 119 11
      Trio/Sources/Modules/Onboarding/View/OnboardingView+Util.swift

+ 29 - 9
Trio.xcodeproj/project.pbxproj

@@ -564,7 +564,7 @@
 		DD498F2D2D692BEA00AAEA30 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 8A9134292D63D9A1007F8874 /* Localizable.xcstrings */; };
 		DD4A00212DAEEED800AB7387 /* OnboardingView+AlgorithmUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A00202DAEEEC400AB7387 /* OnboardingView+AlgorithmUtil.swift */; };
 		DD4A00242DAEF5E400AB7387 /* AlgorithmSettingsSubstepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A00232DAEF5DC00AB7387 /* AlgorithmSettingsSubstepView.swift */; };
-		DD4AFFF12DADB59100AB7387 /* AlgorithmSettingsStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AFFF02DADB59100AB7387 /* AlgorithmSettingsStepView.swift */; };
+		DD4AFFF12DADB59100AB7387 /* AlgorithmSettingsContentsStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AFFF02DADB59100AB7387 /* AlgorithmSettingsContentsStepView.swift */; };
 		DD4C57A82D73ADEA001BFF2C /* RestartLiveActivityIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C57A72D73ADEA001BFF2C /* RestartLiveActivityIntent.swift */; };
 		DD4C57AA2D73B3E2001BFF2C /* RestartLiveActivityIntentRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C57A92D73B3D9001BFF2C /* RestartLiveActivityIntentRequest.swift */; };
 		DD4C581F2D73C43D001BFF2C /* LoopStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C581E2D73C43D001BFF2C /* LoopStatsView.swift */; };
@@ -575,6 +575,9 @@
 		DD5DC9F92CF3DAA900AB8703 /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9F82CF3DAA900AB8703 /* RadioButton.swift */; };
 		DD5DC9FB2CF3E1B100AB8703 /* AdjustmentsStateModel+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9FA2CF3E1AA00AB8703 /* AdjustmentsStateModel+Helpers.swift */; };
 		DD68889D2C386E17006E3C44 /* NightscoutExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */; };
+		DD6A4E7E2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E7D2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift */; };
+		DD6A4E802DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E7F2DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift */; };
+		DD6A4E842DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E832DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift */; };
 		DD6B7CB22C7B6F0800B75029 /* Rounding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6B7CB12C7B6F0800B75029 /* Rounding.swift */; };
 		DD6B7CB42C7B71F700B75029 /* ForecastDisplayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6B7CB32C7B71F700B75029 /* ForecastDisplayType.swift */; };
 		DD6D67E42C9C253500660C9B /* ColorSchemeOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6D67E32C9C253500660C9B /* ColorSchemeOption.swift */; };
@@ -660,11 +663,11 @@
 		DDF847E62C5D66490049BB3B /* AddMealPresetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF847E52C5D66490049BB3B /* AddMealPresetView.swift */; };
 		DDF847E82C5DABA30049BB3B /* WatchConfigAppleWatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF847E72C5DABA30049BB3B /* WatchConfigAppleWatchView.swift */; };
 		DDF847EA2C5DABAC0049BB3B /* WatchConfigGarminView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF847E92C5DABAC0049BB3B /* WatchConfigGarminView.swift */; };
+		DDFF202F2DB1D14500AB8A96 /* NotificationPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */; };
+		DDFF20312DB1D15500AB8A96 /* BluetoothPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */; };
 		DDFF204A2DB29EF500AB8A96 /* WatchLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF20492DB29EF500AB8A96 /* WatchLogger.swift */; };
 		DDFF204E2DB2C00B00AB8A96 /* WatchStateSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF204D2DB2C00B00AB8A96 /* WatchStateSnapshot.swift */; };
 		DDFF20502DB2C11900AB8A96 /* WatchStateSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF204F2DB2C11900AB8A96 /* WatchStateSnapshot.swift */; };
-		DDFF202F2DB1D14500AB8A96 /* NotificationPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */; };
-		DDFF20312DB1D15500AB8A96 /* BluetoothPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */; };
 		E00EEC0327368630002FF094 /* ServiceAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00EEBFD27368630002FF094 /* ServiceAssembly.swift */; };
 		E00EEC0427368630002FF094 /* SecurityAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00EEBFE27368630002FF094 /* SecurityAssembly.swift */; };
 		E00EEC0527368630002FF094 /* StorageAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00EEBFF27368630002FF094 /* StorageAssembly.swift */; };
@@ -1363,7 +1366,7 @@
 		DD3F1F8F2D9E153A00DCE7B3 /* NightscoutImportStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutImportStepView.swift; sourceTree = "<group>"; };
 		DD4A00202DAEEEC400AB7387 /* OnboardingView+AlgorithmUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OnboardingView+AlgorithmUtil.swift"; sourceTree = "<group>"; };
 		DD4A00232DAEF5DC00AB7387 /* AlgorithmSettingsSubstepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmSettingsSubstepView.swift; sourceTree = "<group>"; };
-		DD4AFFF02DADB59100AB7387 /* AlgorithmSettingsStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmSettingsStepView.swift; sourceTree = "<group>"; };
+		DD4AFFF02DADB59100AB7387 /* AlgorithmSettingsContentsStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmSettingsContentsStepView.swift; sourceTree = "<group>"; };
 		DD4C57A72D73ADEA001BFF2C /* RestartLiveActivityIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestartLiveActivityIntent.swift; sourceTree = "<group>"; };
 		DD4C57A92D73B3D9001BFF2C /* RestartLiveActivityIntentRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestartLiveActivityIntentRequest.swift; sourceTree = "<group>"; };
 		DD4C581E2D73C43D001BFF2C /* LoopStatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopStatsView.swift; sourceTree = "<group>"; };
@@ -1374,6 +1377,9 @@
 		DD5DC9F82CF3DAA900AB8703 /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
 		DD5DC9FA2CF3E1AA00AB8703 /* AdjustmentsStateModel+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentsStateModel+Helpers.swift"; sourceTree = "<group>"; };
 		DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutExercise.swift; sourceTree = "<group>"; };
+		DD6A4E7D2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupReturningUserStepView.swift; sourceTree = "<group>"; };
+		DD6A4E7F2DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupForceCloseWarningStepView.swift; sourceTree = "<group>"; };
+		DD6A4E832DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmSettingsImportantNotesStepView.swift; sourceTree = "<group>"; };
 		DD6B7CB12C7B6F0800B75029 /* Rounding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rounding.swift; sourceTree = "<group>"; };
 		DD6B7CB32C7B71F700B75029 /* ForecastDisplayType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastDisplayType.swift; sourceTree = "<group>"; };
 		DD6D67E32C9C253500660C9B /* ColorSchemeOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSchemeOption.swift; sourceTree = "<group>"; };
@@ -1462,11 +1468,11 @@
 		DDF847E52C5D66490049BB3B /* AddMealPresetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddMealPresetView.swift; sourceTree = "<group>"; };
 		DDF847E72C5DABA30049BB3B /* WatchConfigAppleWatchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchConfigAppleWatchView.swift; sourceTree = "<group>"; };
 		DDF847E92C5DABAC0049BB3B /* WatchConfigGarminView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchConfigGarminView.swift; sourceTree = "<group>"; };
+		DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionStepView.swift; sourceTree = "<group>"; };
+		DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothPermissionStepView.swift; sourceTree = "<group>"; };
 		DDFF20492DB29EF500AB8A96 /* WatchLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchLogger.swift; sourceTree = "<group>"; };
 		DDFF204D2DB2C00B00AB8A96 /* WatchStateSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchStateSnapshot.swift; sourceTree = "<group>"; };
 		DDFF204F2DB2C11900AB8A96 /* WatchStateSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchStateSnapshot.swift; sourceTree = "<group>"; };
-		DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionStepView.swift; sourceTree = "<group>"; };
-		DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothPermissionStepView.swift; sourceTree = "<group>"; };
 		E00EEBFD27368630002FF094 /* ServiceAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceAssembly.swift; sourceTree = "<group>"; };
 		E00EEBFE27368630002FF094 /* SecurityAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityAssembly.swift; sourceTree = "<group>"; };
 		E00EEBFF27368630002FF094 /* StorageAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageAssembly.swift; sourceTree = "<group>"; };
@@ -2791,11 +2797,11 @@
 		BD47FDD52D8B64AE0043966B /* OnboardingSteps */ = {
 			isa = PBXGroup;
 			children = (
+				DD6A4E4E2DBEBC7B008C4B26 /* StartupGuide */,
 				DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */,
 				DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */,
 				DD4A00222DAEF5CD00AB7387 /* AlgorithmSettings */,
 				DDBD53FB2DAA903100F940A6 /* OverviewStepView.swift */,
-				DDF691362DA30332008BF16C /* StartupGuideStepView.swift */,
 				DDF6905B2DA0AFC5008BF16C /* WelcomeStepView.swift */,
 				DDF6902B2DA028D3008BF16C /* DiagnosticsStepView.swift */,
 				DD3F1F8E2D9E151200DCE7B3 /* Nightscout */,
@@ -3269,8 +3275,9 @@
 		DD4A00222DAEF5CD00AB7387 /* AlgorithmSettings */ = {
 			isa = PBXGroup;
 			children = (
+				DD6A4E832DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift */,
 				DD4A00232DAEF5DC00AB7387 /* AlgorithmSettingsSubstepView.swift */,
-				DD4AFFF02DADB59100AB7387 /* AlgorithmSettingsStepView.swift */,
+				DD4AFFF02DADB59100AB7387 /* AlgorithmSettingsContentsStepView.swift */,
 			);
 			path = AlgorithmSettings;
 			sourceTree = "<group>";
@@ -3303,6 +3310,16 @@
 			path = ViewElements;
 			sourceTree = "<group>";
 		};
+		DD6A4E4E2DBEBC7B008C4B26 /* StartupGuide */ = {
+			isa = PBXGroup;
+			children = (
+				DD6A4E7F2DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift */,
+				DD6A4E7D2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift */,
+				DDF691362DA30332008BF16C /* StartupGuideStepView.swift */,
+			);
+			path = StartupGuide;
+			sourceTree = "<group>";
+		};
 		DD9ECB662CA99EFE00AA7C45 /* RemoteControl */ = {
 			isa = PBXGroup;
 			children = (
@@ -4126,6 +4143,7 @@
 				DDD1631F2C4C6F6900CD525A /* TrioCoreDataPersistentContainer.xcdatamodeld in Sources */,
 				DD1745482C55C61D00211FAC /* AutosensSettingsStateModel.swift in Sources */,
 				DD1745462C55C61500211FAC /* AutosensSettingsProvider.swift in Sources */,
+				DD6A4E802DBEC3EE008C4B26 /* StartupForceCloseWarningStepView.swift in Sources */,
 				DDA6E2852D2361F800C2988C /* LoopStatusView.swift in Sources */,
 				DDF691012DA2CA11008BF16C /* AppDiagnosticsDataFlow.swift in Sources */,
 				DDA6E3202D258E0500C2988C /* OverrideHelpView.swift in Sources */,
@@ -4151,6 +4169,7 @@
 				58D08B222C8DAA8E00AA37D3 /* OverrideView.swift in Sources */,
 				BD0B2EF32C5998E600B3298F /* MealPresetView.swift in Sources */,
 				E592A3702CEEC01E009A472C /* ContactTrickEntry.swift in Sources */,
+				DD6A4E7E2DBEBF0F008C4B26 /* StartupReturningUserStepView.swift in Sources */,
 				DD6D67E42C9C253500660C9B /* ColorSchemeOption.swift in Sources */,
 				582DF9752C8CDB92001F516D /* GlucoseChartView.swift in Sources */,
 				BD432CA12D2F4E3600D1EB79 /* WatchMessageKeys.swift in Sources */,
@@ -4252,6 +4271,7 @@
 				190EBCC429FF136900BA767D /* UserInterfaceSettingsDataFlow.swift in Sources */,
 				CE3EEF9A2D463717001944DD /* CustomCGMOptionsView.swift in Sources */,
 				5A2325582BFCC168003518CA /* NightscoutConnectView.swift in Sources */,
+				DD6A4E842DBEDD39008C4B26 /* AlgorithmSettingsImportantNotesStepView.swift in Sources */,
 				3811DEB025C9D88300A708ED /* BaseKeychain.swift in Sources */,
 				110AEDE42C5193D200615CC9 /* BolusIntentRequest.swift in Sources */,
 				3811DE4325C9D4A100A708ED /* SettingsProvider.swift in Sources */,
@@ -4386,7 +4406,7 @@
 				58A3D5442C96DE11003F90FC /* TempTargetStored+Helper.swift in Sources */,
 				DD6B7CB42C7B71F700B75029 /* ForecastDisplayType.swift in Sources */,
 				BD47FD172D88AAF50043966B /* CompletedStepView.swift in Sources */,
-				DD4AFFF12DADB59100AB7387 /* AlgorithmSettingsStepView.swift in Sources */,
+				DD4AFFF12DADB59100AB7387 /* AlgorithmSettingsContentsStepView.swift in Sources */,
 				DDEBB05C2D89E9050032305D /* TimeInRangeType.swift in Sources */,
 				DD5DC9F32CF3D9DD00AB8703 /* AdjustmentsStateModel+TempTargets.swift in Sources */,
 				BD47FDDB2D8B659B0043966B /* BasalProfileStepView.swift in Sources */,

+ 58 - 0
Trio/Sources/Localizations/Main/Localizable.xcstrings

@@ -2687,6 +2687,9 @@
         }
       }
     },
+    " of usage data and is not yet configurable." : {
+
+    },
     " SMB" : {
       "comment" : "Super Micro Bolus indicator in delete alert",
       "localizations" : {
@@ -2897,6 +2900,7 @@
       }
     },
     " the app before finishing onboarding, " : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -19478,6 +19482,9 @@
         }
       }
     },
+    "7 days" : {
+
+    },
     "10-90" : {
       "localizations" : {
         "bg" : {
@@ -21795,6 +21802,7 @@
       }
     },
     "A few important notes:" : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -21894,6 +21902,9 @@
         }
       }
     },
+    "A few important notes…" : {
+
+    },
     "A generated unique identifier (a random code like \"A7B2C9D3\" that doesn't identify you personally)" : {
       "localizations" : {
         "bg" : {
@@ -32207,6 +32218,9 @@
         }
       }
     },
+    "All entries you made during Onboarding will be saved automatically when you complete the wizard." : {
+
+    },
     "All FPUs and the carbs of the meal will be deleted." : {
       "comment" : "Alert message for meal deletion",
       "localizations" : {
@@ -84929,7 +84943,11 @@
         }
       }
     },
+    "Dynamic ISF requires at least " : {
+
+    },
     "Dynamic ISF requires at least 7 days of usage data and is not yet configurable." : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -95113,7 +95131,11 @@
         }
       }
     },
+    "Even if you’re an updating user, you’ll be guided through the algorithm settings configuration step-by-step." : {
+
+    },
     "Even if you’re an updating user, you’ll be guided through this step-by-step." : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -102936,6 +102958,7 @@
       }
     },
     "force quit" : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -109739,6 +109762,7 @@
       }
     },
     "Got it! I'm ready to continue." : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -111791,6 +111815,9 @@
         }
       }
     },
+    "Here's what you can expect to be preserved:" : {
+
+    },
     "Hi there!" : {
       "localizations" : {
         "bg" : {
@@ -119635,6 +119662,9 @@
         }
       }
     },
+    "Important" : {
+
+    },
     "Important message" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -125966,6 +125996,9 @@
         }
       }
     },
+    "Just be aware: if you force quit the app before finishing onboarding, your progress will not be saved." : {
+
+    },
     "Keep these turned ON in your phone’s settings to ensure you receive Trio Notifications, Critical Alerts, and Time Sensitive Notifications." : {
       "localizations" : {
         "bg" : {
@@ -189848,6 +189881,9 @@
         }
       }
     },
+    "Some helpful reminders:" : {
+
+    },
     "Some other cloud" : {
       "localizations" : {
         "bg" : {
@@ -238551,7 +238587,11 @@
         }
       }
     },
+    "You can pause at any time. If you feel like taking a break, do it and put the phone down!" : {
+
+    },
     "You can pause at any time. Just be aware: if you " : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -238851,6 +238891,9 @@
         }
       }
     },
+    "You will also be guided through re-configuring your algorithm settings, respecting Trio's new guardrails." : {
+
+    },
     "You're All Set!" : {
       "localizations" : {
         "bg" : {
@@ -239051,7 +239094,11 @@
         }
       }
     },
+    "Your algorithm settings (previously called \"OpenAPS settings\") are reset to defaults." : {
+
+    },
     "Your algorithm settings (previously called \"OpenAPS settings\") will be reset to defaults." : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -239975,6 +240022,7 @@
       }
     },
     "your progress will not be saved." : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -240074,6 +240122,9 @@
         }
       }
     },
+    "Your pump and CGM configurations are retained and fully functional." : {
+
+    },
     "Your Rights" : {
       "localizations" : {
         "bg" : {
@@ -240174,7 +240225,11 @@
         }
       }
     },
+    "Your therapy settings (basal rates, carb ratios, insulin sensitivities and glucose targets) are carried over." : {
+
+    },
     "Your therapy settings, pump, and CGM configurations will be carried over." : {
+      "extractionState" : "stale",
       "localizations" : {
         "bg" : {
           "stringUnit" : {
@@ -240274,6 +240329,9 @@
         }
       }
     },
+    "Your treatment data (pump events, carb entries, glucose trace, etc.) are not migrated." : {
+
+    },
     "ZT" : {
       "localizations" : {
         "bg" : {

+ 1 - 7
Trio/Sources/Modules/Onboarding/OnboardingStateModel.swift

@@ -23,10 +23,6 @@ extension Onboarding {
         var diagnosticsSharingOption: DiagnosticsSharingOption = .enabled
         var hasAcceptedPrivacyPolicy: Bool = false
 
-        // MARK: - Important Startup Notes
-
-        var hasReadImportantStartupNotes: Bool = false
-
         // MARK: - Nightscout Setup
 
         var nightscoutSetupOption: NightscoutSetupOption = .noSelection
@@ -102,9 +98,7 @@ extension Onboarding {
         var maxCOB: Decimal = 120
         var minimumSafetyThreshold: Decimal = 60
 
-        // MARK: - Algorithm Settings Defaults & State
-
-        var hasReadAlgorithmSetupInformation: Bool = false
+        // MARK: - Algorithm Settings Defaults
 
         // Autosens Settings
         var autosensMin: Decimal = 0.7

+ 290 - 126
Trio/Sources/Modules/Onboarding/View/OnboardingRootView.swift

@@ -10,13 +10,44 @@ extension Onboarding {
         let onboardingManager: OnboardingManager
 
         // Step management
+        @State private var currentChapter: OnboardingChapter = .prepareTrio
+        @State private var showingChapterCompletion: OnboardingChapter? = nil
+
         @State private var currentStep: OnboardingStep = .welcome
+        @State private var currentStartupSubstep: StartupSubstep = .startupGuide
         @State private var currentNightscoutSubstep: NightscoutSubstep = .setupSelection
         @State private var currentDeliverySubstep: DeliveryLimitSubstep = .maxIOB
+        @State private var currentAlgorithmSettingsOverviewSubstep: AlgorithmSettingsOverviewSubstep = .contents
         @State private var currentAutosensSubstep: AutosensSettingsSubstep = .autosensMin
         @State private var currentSMBSubstep: SMBSettingsSubstep = .enableSMBAlways
         @State private var currentTargetBehaviorSubstep: TargetBehaviorSubstep = .highTempTargetRaisesSensitivity
 
+        private func updateCurrentChapter() {
+            switch currentStep {
+            case .diagnostics,
+                 .nightscout,
+                 .unitSelection:
+                currentChapter = .prepareTrio
+            case .basalRates,
+                 .carbRatio,
+                 .glucoseTarget,
+                 .insulinSensitivity:
+                currentChapter = .therapySettings
+            case .deliveryLimits:
+                currentChapter = .deliveryLimits
+            case .algorithmSettings,
+                 .autosensSettings,
+                 .smbSettings,
+                 .targetBehavior:
+                currentChapter = .algorithmSettings
+            case .bluetooth,
+                 .notifications:
+                currentChapter = .permissionRequests
+            default:
+                break
+            }
+        }
+
         // Animation states
         @State private var animationScale: CGFloat = 1.0
         @State private var animationOpacity: Double = 0
@@ -38,17 +69,13 @@ extension Onboarding {
 
         // Next button conditional
         private var shouldDisableNextButton: Bool {
-            (currentStep == .startupGuide && !state.hasReadImportantStartupNotes)
-                ||
-                (currentStep == .diagnostics && state.diagnosticsSharingOption == .enabled && !state.hasAcceptedPrivacyPolicy)
+            (currentStep == .diagnostics && state.diagnosticsSharingOption == .enabled && !state.hasAcceptedPrivacyPolicy)
                 ||
                 (currentStep == .nightscout && didSelectNightscoutSetupOption)
                 ||
                 (currentStep == .nightscout && hasValidNightscoutConnection)
                 ||
                 (currentStep == .nightscout && didSelectNightscoutImportOption)
-                ||
-                (currentStep == .algorithmSettings && !state.hasReadAlgorithmSetupInformation)
         }
 
         var body: some View {
@@ -66,11 +93,14 @@ extension Onboarding {
                         if (nonInfoOnboardingSteps + [OnboardingStep.overview, OnboardingStep.completed]).contains(currentStep) {
                             // Progress bar
                             OnboardingProgressBar(
+                                currentChapter: currentChapter,
+                                shouldDisplayChapterTitle: showingChapterCompletion == nil,
                                 currentStep: currentStep,
                                 currentSubstep: {
                                     switch currentStep {
                                     case .deliveryLimits: return currentDeliverySubstep.rawValue
                                     case .nightscout: return currentNightscoutSubstep.rawValue
+                                    case .algorithmSettings: return currentAlgorithmSettingsOverviewSubstep.rawValue
                                     case .autosensSettings: return currentAutosensSubstep.rawValue
                                     case .smbSettings: return currentSMBSubstep.rawValue
                                     case .targetBehavior: return currentTargetBehaviorSubstep.rawValue
@@ -80,6 +110,7 @@ extension Onboarding {
                                 stepsWithSubsteps: [
                                     .nightscout: NightscoutSubstep.allCases.count,
                                     .deliveryLimits: DeliveryLimitSubstep.allCases.count,
+                                    .algorithmSettings: AlgorithmSettingsOverviewSubstep.allCases.count,
                                     .autosensSettings: state.filteredAutosensSettingsSubsteps.count,
                                     .smbSettings: SMBSettingsSubstep.allCases.count,
                                     .targetBehavior: TargetBehaviorSubstep.allCases.count
@@ -94,8 +125,11 @@ extension Onboarding {
 
                         OnboardingStepContent(
                             currentStep: $currentStep,
+                            showingChapterCompletion: $showingChapterCompletion,
+                            currentStartupSubstep: $currentStartupSubstep,
                             currentNightscoutSubstep: $currentNightscoutSubstep,
                             currentDeliverySubstep: $currentDeliverySubstep,
+                            currentAlgorithmSettingsOverviewSubstep: $currentAlgorithmSettingsOverviewSubstep,
                             currentAutosensSubstep: $currentAutosensSubstep,
                             currentSMBSubstep: $currentSMBSubstep,
                             currentTargetBehaviorSubstep: $currentTargetBehaviorSubstep,
@@ -107,8 +141,11 @@ extension Onboarding {
 
                         OnboardingNavigationButtons(
                             currentStep: $currentStep,
+                            showingChapterCompletion: $showingChapterCompletion,
+                            currentStartupSubstep: $currentStartupSubstep,
                             currentNightscoutSubstep: $currentNightscoutSubstep,
                             currentDeliverySubstep: $currentDeliverySubstep,
+                            currentAlgorithmSettingsOverviewSubstep: $currentAlgorithmSettingsOverviewSubstep,
                             currentAutosensSubstep: $currentAutosensSubstep,
                             currentSMBSubstep: $currentSMBSubstep,
                             currentTargetBehaviorSubstep: $currentTargetBehaviorSubstep,
@@ -135,6 +172,8 @@ extension Onboarding {
                     }
                     isAnimating = true
                 }
+
+                updateCurrentChapter()
             }
             .onAppear(perform: configureView)
         }
@@ -143,34 +182,62 @@ extension Onboarding {
 
 /// A progress bar that shows the user's progress through the onboarding process.
 struct OnboardingProgressBar: View {
+    let currentChapter: OnboardingChapter
+    let shouldDisplayChapterTitle: Bool
     let currentStep: OnboardingStep
     let currentSubstep: Int?
     let stepsWithSubsteps: [OnboardingStep: Int]
     let nightscoutSetupOption: NightscoutSetupOption
 
+    private let capsuleSize = CGFloat(UIFont.preferredFont(forTextStyle: .subheadline).pointSize) * 1.3
+
+    private var shouldShowCurrentChapter: Bool {
+        shouldDisplayChapterTitle && currentStep != .overview && currentStep != .completed
+    }
+
     var body: some View {
-        HStack(spacing: 4) {
-            ForEach(renderedSteps, id: \.id) { step in
-                ZStack(alignment: .leading) {
-                    Rectangle()
-                        .fill(Color.gray.opacity(0.3))
-                        .frame(height: 4)
-                        .cornerRadius(2)
-
-                    GeometryReader { geo in
+        VStack(alignment: .leading, spacing: 10) {
+            // only show this for the actual chapters, not the overview of chapters or completed view
+            if shouldShowCurrentChapter {
+                HStack(spacing: CGFloat(UIFont.preferredFont(forTextStyle: .subheadline).pointSize)) {
+                    Text("\(currentChapter.rawValue + 1)")
+                        .font(.subheadline)
+                        .fontWeight(.heavy)
+                        .frame(width: capsuleSize, height: capsuleSize, alignment: .center)
+                        .background(Color.blue)
+                        .foregroundStyle(Color.bgDarkBlue)
+                        .clipShape(Capsule())
+                    Text(currentChapter.title)
+                        .font(.subheadline)
+                        .kerning(capsuleSize / 4)
+                        .textCase(.uppercase)
+                        .bold()
+                        .foregroundStyle(Color.secondary)
+                }
+            }
+
+            HStack(spacing: 4) {
+                ForEach(renderedSteps, id: \.id) { step in
+                    ZStack(alignment: .leading) {
                         Rectangle()
-                            .fill(Color.blue)
-                            .frame(
-                                width: geo.size.width * fillFraction(for: step.step, totalSubsteps: step.substeps),
-                                height: 4
-                            )
+                            .fill(Color.gray.opacity(0.3))
+                            .frame(height: 4)
                             .cornerRadius(2)
+
+                        GeometryReader { geo in
+                            Rectangle()
+                                .fill(Color.blue)
+                                .frame(
+                                    width: geo.size.width * fillFraction(for: step.step, totalSubsteps: step.substeps),
+                                    height: 4
+                                )
+                                .cornerRadius(2)
+                        }
                     }
+                    .frame(height: 4)
                 }
-                .frame(height: 4)
             }
-        }
-        .padding(.horizontal)
+        }.padding(.horizontal)
     }
 
     private var renderedSteps: [(id: String, step: OnboardingStep, substeps: Int?)] {
@@ -214,8 +281,11 @@ struct OnboardingProgressBar: View {
 
 struct OnboardingStepContent: View {
     @Binding var currentStep: OnboardingStep
+    @Binding var showingChapterCompletion: OnboardingChapter?
+    @Binding var currentStartupSubstep: StartupSubstep
     @Binding var currentNightscoutSubstep: NightscoutSubstep
     @Binding var currentDeliverySubstep: DeliveryLimitSubstep
+    @Binding var currentAlgorithmSettingsOverviewSubstep: AlgorithmSettingsOverviewSubstep
     @Binding var currentAutosensSubstep: AutosensSettingsSubstep
     @Binding var currentSMBSubstep: SMBSettingsSubstep
     @Binding var currentTargetBehaviorSubstep: TargetBehaviorSubstep
@@ -228,126 +298,154 @@ struct OnboardingStepContent: View {
                 VStack(alignment: .leading, spacing: 20) {
                     Color.clear.frame(height: 0).id("top")
 
-                    if currentStep != .welcome && currentStep != .completed {
-                        HStack {
-                            if currentStep == .nightscout {
-                                Image(currentStep.iconName)
-                                    .resizable()
-                                    .scaledToFit()
-                                    .frame(width: 60, height: 60)
-                            } else if currentStep == .bluetooth {
-                                Image(currentStep.iconName)
-                                    .font(.system(size: 40))
-                                    .foregroundColor(currentStep.accentColor)
-                                    .frame(width: 60, height: 60)
-                                    .background(
-                                        Circle()
-                                            .fill(currentStep.accentColor.opacity(0.2))
-                                    )
-                            } else {
-                                Image(systemName: currentStep.iconName)
-                                    .font(.system(size: 40))
-                                    .foregroundColor(currentStep.accentColor)
-                                    .frame(width: 60, height: 60)
-                                    .background(
-                                        Circle()
-                                            .fill(currentStep.accentColor.opacity(0.2))
-                                    )
-                            }
-
-                            VStack(alignment: .leading) {
-                                Text(currentStep.title)
-                                    .font(.title)
-                                    .fontWeight(.bold)
-                                    .foregroundColor(.primary)
-
-                                Text(currentStep.description)
-                                    .font(.subheadline)
-                                    .foregroundColor(.secondary)
-                                    .fixedSize(horizontal: false, vertical: true)
-                            }
-                        }
-                        .padding([.horizontal, .top])
+                    if currentStep != .welcome, currentStep != .completed, showingChapterCompletion == nil {
+                        contentHeader
                     }
 
-                    Group {
-                        switch currentStep {
-                        case .welcome:
-                            WelcomeStepView()
-                        case .startupGuide:
-                            StartupGuideStepView(state: state)
-                        case .overview:
-                            OverviewStepView()
-                        case .diagnostics:
-                            DiagnosticsStepView(state: state)
-                        case .nightscout:
-                            switch currentNightscoutSubstep {
-                            case .setupSelection:
-                                NightscoutSetupStepView(state: state)
-                            case .connectToNightscout:
-                                NightscoutLoginStepView(state: state)
-                            case .importFromNightscout:
-                                NightscoutImportStepView(state: state)
+                    if let chapter = showingChapterCompletion {
+                        CompletedStepView(isOnboardingCompleted: false, currentChapter: chapter)
+                    } else {
+                        Group {
+                            switch currentStep {
+                            case .welcome:
+                                WelcomeStepView()
+                            case .startupInfo:
+                                switch currentStartupSubstep {
+                                case .startupGuide:
+                                    StartupGuideStepView(state: state)
+                                case .returningUser:
+                                    StartupReturningUserStepView(state: state)
+                                case .forceCloseWarning:
+                                    StartupForceCloseWarningStepView(state: state)
+                                }
+                            case .overview:
+                                OverviewStepView()
+                            case .diagnostics:
+                                DiagnosticsStepView(state: state)
+                            case .nightscout:
+                                switch currentNightscoutSubstep {
+                                case .setupSelection:
+                                    NightscoutSetupStepView(state: state)
+                                case .connectToNightscout:
+                                    NightscoutLoginStepView(state: state)
+                                case .importFromNightscout:
+                                    NightscoutImportStepView(state: state)
+                                }
+                            case .unitSelection:
+                                UnitSelectionStepView(state: state)
+                            case .glucoseTarget:
+                                GlucoseTargetStepView(state: state)
+                            case .basalRates:
+                                BasalProfileStepView(state: state)
+                            case .carbRatio:
+                                CarbRatioStepView(state: state)
+                            case .insulinSensitivity:
+                                InsulinSensitivityStepView(state: state)
+                            case .deliveryLimits:
+                                DeliveryLimitsStepView(state: state, substep: currentDeliverySubstep)
+                            case .algorithmSettings:
+                                switch currentAlgorithmSettingsOverviewSubstep {
+                                case .contents:
+                                    AlgorithmSettingsContentsStepView(state: state)
+                                case .importantNotes:
+                                    AlgorithmSettingsImportantNotesStepView(state: state)
+                                }
+                            case .autosensSettings:
+                                AlgorithmSettingsSubstepView(state: state, substep: currentAutosensSubstep)
+                            case .smbSettings:
+                                AlgorithmSettingsSubstepView(state: state, substep: currentSMBSubstep)
+                            case .targetBehavior:
+                                AlgorithmSettingsSubstepView(state: state, substep: currentTargetBehaviorSubstep)
+                            case .notifications:
+                                NotificationPermissionStepView(state: state, currentStep: $currentStep)
+                            case .bluetooth:
+                                BluetoothPermissionStepView(
+                                    state: state,
+                                    bluetoothManager: state.bluetoothManager,
+                                    currentStep: $currentStep
+                                )
+                            case .completed:
+                                CompletedStepView(isOnboardingCompleted: true, currentChapter: nil)
                             }
-                        case .unitSelection:
-                            UnitSelectionStepView(state: state)
-                        case .glucoseTarget:
-                            GlucoseTargetStepView(state: state)
-                        case .basalRates:
-                            BasalProfileStepView(state: state)
-                        case .carbRatio:
-                            CarbRatioStepView(state: state)
-                        case .insulinSensitivity:
-                            InsulinSensitivityStepView(state: state)
-                        case .deliveryLimits:
-                            DeliveryLimitsStepView(state: state, substep: currentDeliverySubstep)
-                        case .algorithmSettings:
-                            AlgorithmSettingsStepView(state: state)
-                        case .autosensSettings:
-                            AlgorithmSettingsSubstepView(state: state, substep: currentAutosensSubstep)
-                        case .smbSettings:
-                            AlgorithmSettingsSubstepView(state: state, substep: currentSMBSubstep)
-                        case .targetBehavior:
-                            AlgorithmSettingsSubstepView(state: state, substep: currentTargetBehaviorSubstep)
-                        case .notifications:
-                            NotificationPermissionStepView(state: state, currentStep: $currentStep)
-                        case .bluetooth:
-                            BluetoothPermissionStepView(
-                                state: state,
-                                bluetoothManager: state.bluetoothManager,
-                                currentStep: $currentStep
-                            )
-                        case .completed:
-                            CompletedStepView()
                         }
+                        .transition(
+                            navigationDirection == .forward
+                                ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))
+                                : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing))
+                        )
+                        .padding(.horizontal)
+                        .id(currentStep.id)
                     }
-                    .transition(
-                        navigationDirection == .forward
-                            ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))
-                            : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing))
-                    )
-                    .padding(.horizontal)
-                    .id(currentStep.id)
                 }
                 .padding(.bottom, 80)
             }
             .onChange(of: currentStep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
+            .onChange(of: currentStartupSubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
             .onChange(of: currentNightscoutSubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
             .onChange(of: currentDeliverySubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
+            .onChange(of: currentAlgorithmSettingsOverviewSubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
+            .onChange(of: currentAutosensSubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
+            .onChange(of: currentSMBSubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
+            .onChange(of: currentTargetBehaviorSubstep) { _, _ in scrollProxy.scrollTo("top", anchor: .top) }
             .safeAreaInset(edge: .top) {
                 // avoid letting content scroll beneath the status bar / dynamic island for content views with not progress bar (which adds top spacing)
-                if currentStep == .startupGuide || currentStep == .completed {
+                if currentStep == .startupInfo || currentStep == .completed {
                     Color.clear.frame(height: 0)
                 }
             }
         }
     }
+
+    private var contentHeader: some View {
+        HStack {
+            if currentStep == .nightscout {
+                Image(currentStep.iconName)
+                    .resizable()
+                    .scaledToFit()
+                    .frame(width: 60, height: 60)
+            } else if currentStep == .bluetooth {
+                Image(currentStep.iconName)
+                    .font(.system(size: 40))
+                    .foregroundColor(currentStep.accentColor)
+                    .frame(width: 60, height: 60)
+                    .background(
+                        Circle()
+                            .fill(currentStep.accentColor.opacity(0.2))
+                    )
+            } else {
+                Image(systemName: currentStep.iconName)
+                    .font(.system(size: 40))
+                    .foregroundColor(currentStep.accentColor)
+                    .frame(width: 60, height: 60)
+                    .background(
+                        Circle()
+                            .fill(currentStep.accentColor.opacity(0.2))
+                    )
+            }
+
+            VStack(alignment: .leading) {
+                Text(currentStep.title)
+                    .font(.title)
+                    .fontWeight(.bold)
+                    .foregroundColor(.primary)
+
+                Text(currentStep.description)
+                    .font(.subheadline)
+                    .foregroundColor(.secondary)
+                    .fixedSize(horizontal: false, vertical: true)
+            }
+        }
+        .padding(.horizontal)
+    }
 }
 
 struct OnboardingNavigationButtons: View {
     @Binding var currentStep: OnboardingStep
+    @Binding var showingChapterCompletion: OnboardingChapter?
+    @Binding var currentStartupSubstep: StartupSubstep
     @Binding var currentNightscoutSubstep: NightscoutSubstep
     @Binding var currentDeliverySubstep: DeliveryLimitSubstep
+    @Binding var currentAlgorithmSettingsOverviewSubstep: AlgorithmSettingsOverviewSubstep
     @Binding var currentAutosensSubstep: AutosensSettingsSubstep
     @Binding var currentSMBSubstep: SMBSettingsSubstep
     @Binding var currentTargetBehaviorSubstep: TargetBehaviorSubstep
@@ -400,10 +498,26 @@ struct OnboardingNavigationButtons: View {
     // MARK: - Navigation Logic
 
     private func handleBackNavigation() {
+        if showingChapterCompletion != nil {
+            showingChapterCompletion = nil
+            return
+        }
+
         switch currentStep {
-        case .completed:
-            currentStep = .targetBehavior
-            currentTargetBehaviorSubstep = .halfBasalTarget
+        case .startupInfo:
+            if let previousSub = StartupSubstep(rawValue: currentStartupSubstep.rawValue - 1) {
+                currentStartupSubstep = previousSub
+            } else if let previous = currentStep.previous {
+                currentStep = previous
+                currentStartupSubstep = .startupGuide
+            }
+
+        case .overview:
+            currentStartupSubstep = .forceCloseWarning
+
+            if let previous = currentStep.previous {
+                currentStep = previous
+            }
 
         case .nightscout:
             if currentNightscoutSubstep == .setupSelection,
@@ -424,7 +538,12 @@ struct OnboardingNavigationButtons: View {
             }
 
         case .algorithmSettings:
-            if let previous = currentStep.previous {
+            if let previousSub = AlgorithmSettingsOverviewSubstep(
+                rawValue: currentAlgorithmSettingsOverviewSubstep
+                    .rawValue - 1
+            ) {
+                currentAlgorithmSettingsOverviewSubstep = previousSub
+            } else if let previous = currentStep.previous {
                 currentStep = previous
                 currentDeliverySubstep = .minimumSafetyThreshold
                 currentAutosensSubstep = .autosensMin
@@ -442,6 +561,8 @@ struct OnboardingNavigationButtons: View {
             }
 
         case .smbSettings:
+            currentAlgorithmSettingsOverviewSubstep = .importantNotes
+
             if let previous = SMBSettingsSubstep(rawValue: currentSMBSubstep.rawValue - 1) {
                 /// If user has activated setting `.enableSMBAlways`, when navigating backwards
                 /// skip other redundant "Enable SMB"-settings and go straight to `enableSMBAlways`
@@ -474,6 +595,16 @@ struct OnboardingNavigationButtons: View {
                 currentSMBSubstep = .maxDeltaGlucoseThreshold
             }
 
+        case .notifications:
+            currentTargetBehaviorSubstep = .halfBasalTarget
+
+            if let previous = currentStep.previous {
+                currentStep = previous
+            }
+
+        case .completed:
+            currentStep = .bluetooth
+
         default:
             if let previous = currentStep.previous {
                 currentStep = previous
@@ -482,7 +613,28 @@ struct OnboardingNavigationButtons: View {
     }
 
     private func handleNextNavigation() {
+        if showingChapterCompletion != nil {
+            showingChapterCompletion = nil
+            if let next = currentStep.next {
+                currentStep = next
+            }
+            return
+        }
+
+        if let chapter = currentStep.chapterCompletion {
+            showingChapterCompletion = chapter
+            return
+        }
+
         switch currentStep {
+        case .startupInfo:
+            if let next = StartupSubstep(rawValue: currentStartupSubstep.rawValue + 1) {
+                currentStartupSubstep = next
+            } else if let nextStep = currentStep.next {
+                currentStep = nextStep
+                currentStartupSubstep = .startupGuide
+            }
+
         case .nightscout:
             if currentNightscoutSubstep != .importFromNightscout {
                 if currentNightscoutSubstep == .setupSelection,
@@ -506,9 +658,19 @@ struct OnboardingNavigationButtons: View {
         case .deliveryLimits:
             if let next = DeliveryLimitSubstep(rawValue: currentDeliverySubstep.rawValue + 1) {
                 currentDeliverySubstep = next
+            } else {
+                /// Setting delivery substep to the last substep (`.minimumSafetyThreshold`) and `showingChapterCompletion` to non-`nil`
+                /// prompts display of chapter completion screen; if user navigates back, it stays at correct substep.
+                currentDeliverySubstep = .minimumSafetyThreshold
+                showingChapterCompletion = .deliveryLimits
+            }
+
+        case .algorithmSettings:
+            if let next = AlgorithmSettingsOverviewSubstep(rawValue: currentAlgorithmSettingsOverviewSubstep.rawValue + 1) {
+                currentAlgorithmSettingsOverviewSubstep = next
             } else if let nextStep = currentStep.next {
                 currentStep = nextStep
-                currentDeliverySubstep = .maxIOB
+                currentAlgorithmSettingsOverviewSubstep = .contents
             }
 
         case .autosensSettings:
@@ -540,9 +702,11 @@ struct OnboardingNavigationButtons: View {
         case .targetBehavior:
             if let next = TargetBehaviorSubstep(rawValue: currentTargetBehaviorSubstep.rawValue + 1) {
                 currentTargetBehaviorSubstep = next
-            } else if let nextStep = currentStep.next {
-                currentStep = nextStep
-                currentTargetBehaviorSubstep = .highTempTargetRaisesSensitivity
+            } else {
+                /// Setting target behavior substep to the last substep (`.halfBasalTarget`) and `showingChapterCompletion` to non-`nil`
+                /// prompts display of chapter completion screen; if user navigates back, it stays at correct substep.
+                currentTargetBehaviorSubstep = .halfBasalTarget
+                showingChapterCompletion = .algorithmSettings
             }
 
         case .notifications:

+ 63 - 0
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/AlgorithmSettings/AlgorithmSettingsContentsStepView.swift

@@ -0,0 +1,63 @@
+//
+//  AlgorithmSettingsContentsStepView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 14.04.25
+//
+import SwiftUI
+
+struct AlgorithmSettingsContentsStepView: View {
+    @Bindable var state: Onboarding.StateModel
+
+    var body: some View {
+        VStack(alignment: .leading, spacing: 20) {
+            Text("Configure the algorithm…")
+                .padding(.horizontal)
+                .font(.title3)
+                .bold()
+
+            VStack(alignment: .leading, spacing: 10) {
+                HStack(alignment: .top, spacing: 10) {
+                    Image(systemName: "exclamationmark.triangle.fill").foregroundStyle(Color.bgDarkBlue, Color.orange)
+                        .symbolRenderingMode(.palette)
+                    Text("Important").foregroundStyle(Color.orange)
+                }.bold()
+
+                Text("Our strong recommendation is to ")
+                    + Text("leave everything on default").bold()
+                    + Text(" as a beginner.")
+            }
+            .frame(maxWidth: .infinity)
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .overlay(
+                RoundedRectangle(cornerRadius: 10)
+                    .stroke(Color.orange, lineWidth: 2)
+            )
+            .cornerRadius(10)
+
+            VStack(alignment: .leading, spacing: 20) {
+                Text(
+                    "Trio can automatically adapt insulin delivery based on inputs and glucose forecasts. Your algorithm settings play a major part in accurate and effective dosing."
+                ).multilineTextAlignment(.leading)
+
+                VStack(alignment: .leading, spacing: 10) {
+                    Text("In the next few steps, you’ll configure your algorithm settings for")
+                        .font(.headline)
+                        .padding(.bottom, 4)
+                        .multilineTextAlignment(.leading)
+
+                    BulletPoint(String(localized: "Autosens"))
+                    BulletPoint(String(localized: "Super Micro Bolus (SMB)"))
+                    BulletPoint(String(localized: "Target Behavior"))
+                }
+
+                Text("Only adjust these settings if you’re an advanced or returning user who knows what they’re doing.")
+                    .multilineTextAlignment(.leading)
+            }
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .cornerRadius(10)
+        }
+    }
+}

+ 62 - 0
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/AlgorithmSettings/AlgorithmSettingsImportantNotesStepView.swift

@@ -0,0 +1,62 @@
+//
+//  AlgorithmSettingsImportantNotesStepView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 14.04.25
+//
+import SwiftUI
+
+struct AlgorithmSettingsImportantNotesStepView: View {
+    @Bindable var state: Onboarding.StateModel
+
+    var body: some View {
+        VStack(alignment: .leading, spacing: 20) {
+            Text("A few important notes…")
+                .padding(.horizontal)
+                .font(.title3)
+                .bold()
+
+            VStack(alignment: .leading, spacing: 10) {
+                HStack(alignment: .top, spacing: 10) {
+                    Image(systemName: "exclamationmark.triangle.fill").foregroundStyle(Color.bgDarkBlue, Color.orange)
+                        .symbolRenderingMode(.palette)
+                    Text("Important").foregroundStyle(Color.orange)
+                }.bold()
+
+                Text("Dynamic ISF requires at least ") + Text("7 days")
+                    .bold() + Text(" of usage data and is not yet configurable.")
+            }
+            .frame(maxWidth: .infinity)
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .overlay(
+                RoundedRectangle(cornerRadius: 10)
+                    .stroke(Color.orange, lineWidth: 2)
+            )
+            .cornerRadius(10)
+
+            VStack(alignment: .leading, spacing: 10) {
+                Text("Some helpful reminders:")
+                    .font(.headline)
+                    .padding(.bottom, 4)
+                    .multilineTextAlignment(.leading)
+
+                BulletPoint(
+                    String(
+                        localized: "Even if you’re an updating user, you’ll be guided through the algorithm settings configuration step-by-step."
+                    )
+                )
+                BulletPoint(String(localized: "All additional \"advanced settings\" have been reset."))
+                BulletPoint(
+                    String(localized: "The duration of insulin action (DIA) is now locked to Trio’s new default of 10 hours.")
+                )
+                BulletPoint(
+                    String(localized: "We strongly recommend not changing DIA — it’s essential to stable and safe operation.")
+                )
+            }
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .cornerRadius(10)
+        }
+    }
+}

+ 0 - 70
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/AlgorithmSettings/AlgorithmSettingsStepView.swift

@@ -1,70 +0,0 @@
-//
-//  AlgorithmSettingsStepView.swift
-//  Trio
-//
-//  Created by Cengiz Deniz on 14.04.25
-//
-import SwiftUI
-
-struct AlgorithmSettingsStepView: View {
-    @Bindable var state: Onboarding.StateModel
-
-    @State private var shouldDisplayPicker: Bool = false
-    @State private var decimalPlaceholder: Decimal = 0.0
-    @State private var booleanPlaceholder: Bool = false
-
-    private let settingsProvider = PickerSettingsProvider.shared
-
-    var body: some View {
-        VStack(alignment: .leading, spacing: 20) {
-            Text("Configure the algorithm…")
-                .padding(.horizontal)
-                .font(.title3)
-                .bold()
-
-            VStack(alignment: .leading, spacing: 10) {
-                Text(
-                    "Trio can automatically adapt insulin delivery based on inputs and glucose forecasts. Your algorithm settings play a major part in accurate and effective dosing."
-                ).multilineTextAlignment(.leading)
-
-                Text("In the next few steps, you’ll configure your algorithm settings for")
-                BulletPoint(String(localized: "Autosens"))
-                BulletPoint(String(localized: "Super Micro Bolus (SMB)"))
-                BulletPoint(String(localized: "Target Behavior"))
-
-                Text("Our strong recommendation is to ")
-                    + Text("leave everything on default").bold()
-                    + Text(" as a beginner.")
-
-                Text("Only adjust these settings if you’re an advanced or returning user who knows what they’re doing.")
-                    .multilineTextAlignment(.leading)
-            }
-            .padding(.horizontal)
-
-            VStack(alignment: .leading, spacing: 10) {
-                Text("A few important notes:")
-                    .font(.headline)
-                    .padding(.bottom, 4)
-
-                BulletPoint(String(localized: "Dynamic ISF requires at least 7 days of usage data and is not yet configurable."))
-                BulletPoint(String(localized: "Even if you’re an updating user, you’ll be guided through this step-by-step."))
-                BulletPoint(String(localized: "All additional \"advanced settings\" have been reset."))
-                BulletPoint(
-                    String(localized: "The duration of insulin action (DIA) is now locked to Trio’s new default of 10 hours.")
-                )
-                BulletPoint(
-                    String(localized: "We strongly recommend not changing DIA — it’s essential to stable and safe operation.")
-                )
-            }
-            .padding(.horizontal)
-
-            Divider()
-
-            Toggle(isOn: $state.hasReadAlgorithmSetupInformation) {
-                Text("Got it! I'm ready to continue.").padding(.leading, 6).bold()
-            }
-            .toggleStyle(CheckboxToggleStyle(tint: Color.blue))
-            .padding(.horizontal)
-        }
-    }
-}

+ 52 - 65
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/CompletedStepView.swift

@@ -2,91 +2,75 @@ import SwiftUI
 
 /// Completed step view shown at the end of onboarding.
 struct CompletedStepView: View {
+    let isOnboardingCompleted: Bool
+    let currentChapter: OnboardingChapter?
+
     var body: some View {
         VStack(alignment: .center, spacing: 20) {
-            Image(systemName: "checkmark.circle.fill")
-                .font(.system(size: 60))
-                .foregroundColor(.green)
-
-            Text("You're All Set!")
-                .font(.title)
-                .fontWeight(.bold)
+            if isOnboardingCompleted {
+                Image(systemName: "checkmark.circle.fill")
+                    .font(.system(size: 60))
+                    .foregroundColor(.green)
+
+                Text("You're All Set!")
+                    .font(.title)
+                    .fontWeight(.bold)
+                    .multilineTextAlignment(.center)
+
+                Text(
+                    "You've successfully completed the initial setup of Trio. Tap 'Get Started' to save your settings and start using Trio."
+                )
                 .multilineTextAlignment(.center)
-
-            Text(
-                "You've successfully completed the initial setup of Trio. Tap 'Get Started' to save your settings and start using Trio."
-            )
-            .multilineTextAlignment(.center)
-            .foregroundColor(.secondary)
+                .foregroundColor(.secondary)
+            }
 
             VStack(alignment: .leading, spacing: 12) {
-                completedItemsView(
-                    stepIndex: 1,
-                    title: String(localized: "Prepare Trio"),
-                    description: String(
-                        localized: "App diagnostics sharing, Nightscout setup, and unit and pump model selection are all complete."
+                ForEach(Array(OnboardingChapter.allCases.enumerated()), id: \.element.id) { index, chapter in
+                    completedItemsView(
+                        stepIndex: index + 1,
+                        title: chapter.title,
+                        description: chapter.completedDescription,
+                        isCompleted: isChapterCompleted(chapter)
                     )
-                )
-
-                Divider()
 
-                completedItemsView(
-                    stepIndex: 2,
-                    title: String(localized: "Therapy Settings"),
-                    description: String(
-                        localized: "Glucose target, basal rates, carb ratios, and insulin sensitivity match your needs."
-                    )
-                )
-
-                Divider()
-
-                completedItemsView(
-                    stepIndex: 3,
-                    title: String(localized: "Delivery Limits"),
-                    description: String(
-                        localized: "Safety boundaries for insulin delivery and carb entries are set to help Trio keep you safe."
-                    )
-                )
-
-                Divider()
-
-                completedItemsView(
-                    stepIndex: 4,
-                    title: String(localized: "Algorithm Settings"),
-                    description: String(localized: "Trio’s algorithm features are customized to fit your preferences and needs.")
-                )
-
-                Divider()
-
-                completedItemsView(
-                    stepIndex: 5,
-                    title: String(localized: "Permission Requests"),
-                    description: String(localized: "Notifications and Bluetooth permissions are handled to your liking.")
-                )
+                    if index < (OnboardingChapter.allCases.count - 1) {
+                        Divider()
+                    }
+                }
             }
             .padding()
             .background(Color.green.opacity(0.1))
             .cornerRadius(12)
 
-            Text("Remember, you can adjust these settings at any time in the app settings if needed.")
-                .multilineTextAlignment(.center)
-                .foregroundColor(.primary)
-                .bold()
+            if isOnboardingCompleted {
+                Text("Remember, you can adjust these settings at any time in the app settings if needed.")
+                    .multilineTextAlignment(.center)
+                    .foregroundColor(.primary)
+                    .bold()
+            }
         }
         .padding()
         .frame(maxWidth: .infinity)
     }
 
+    /// Determines if a chapter should be marked as completed
+    private func isChapterCompleted(_ chapter: OnboardingChapter) -> Bool {
+        guard let currentChapter else { return isOnboardingCompleted }
+        if isOnboardingCompleted { return true }
+        return chapter.id <= currentChapter.id
+    }
+
     /// A reusable view for displaying setting items in the completed step.
     @ViewBuilder private func completedItemsView(
         stepIndex: Int,
         title: String,
-        description: String
+        description: String,
+        isCompleted: Bool
     ) -> some View {
         VStack(alignment: .leading, spacing: 10) {
             HStack {
                 HStack(spacing: 14) {
-                    stepCount(stepIndex)
+                    stepCount(stepIndex, isCompleted: isCompleted)
                     Text(title)
                         .font(.headline)
                         .bold()
@@ -94,8 +78,8 @@ struct CompletedStepView: View {
 
                 Spacer()
 
-                Image(systemName: "checkmark")
-                    .foregroundStyle(Color.green)
+                Image(systemName: isCompleted ? "checkmark.circle.fill" : "circle")
+                    .foregroundStyle(isCompleted ? Color.green : Color.secondary)
                     .font(.headline)
                     .bold()
             }
@@ -108,16 +92,19 @@ struct CompletedStepView: View {
         }
     }
 
-    @ViewBuilder private func stepCount(_ count: Int) -> some View {
+    @ViewBuilder private func stepCount(_ count: Int, isCompleted: Bool) -> some View {
         Text(count.description)
             .font(.subheadline.bold())
             .frame(width: 26, height: 26, alignment: .center)
-            .background(Color.green)
+            .background(isCompleted ? Color.green : Color.secondary)
             .foregroundStyle(Color.bgDarkerDarkBlue)
             .clipShape(Capsule())
     }
 }
 
 #Preview {
-    CompletedStepView()
+    CompletedStepView(
+        isOnboardingCompleted: true,
+        currentChapter: nil
+    )
 }

+ 10 - 50
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/OverviewStepView.swift

@@ -14,58 +14,18 @@ struct OverviewStepView: View {
                 .padding(.horizontal)
 
             VStack(alignment: .center, spacing: 12) {
-                overviewItem(
-                    stepIndex: 1,
-                    title: String(localized: "Prepare Trio"),
-                    duration: "3-5",
-                    description: String(
-                        localized: "Configure diagnostics sharing, optionally sync with Nightscout, and enter essentials."
+                ForEach(Array(OnboardingChapter.allCases.enumerated()), id: \.element.id) { index, chapter in
+                    overviewItem(
+                        stepIndex: index + 1,
+                        title: chapter.title,
+                        duration: chapter.duration,
+                        description: chapter.overviewDescription
                     )
-                )
 
-                Divider()
-
-                overviewItem(
-                    stepIndex: 2,
-                    title: String(localized: "Therapy Settings"),
-                    duration: "5-10",
-                    description: String(
-                        localized: "Define your glucose targets, basal rates, carb ratios, and insulin sensitivities."
-                    )
-                )
-
-                Divider()
-
-                overviewItem(
-                    stepIndex: 3,
-                    title: String(localized: "Delivery Limits"),
-                    duration: "3-5",
-                    description: String(
-                        localized: "Set boundaries for insulin delivery and carb entries to help Trio keep you safe."
-                    )
-                )
-
-                Divider()
-
-                overviewItem(
-                    stepIndex: 4,
-                    title: String(localized: "Algorithm Settings"),
-                    duration: "5-10",
-                    description: String(
-                        localized: "Customize Trio’s algorithm features. Most users start with the recommended settings."
-                    )
-                )
-
-                Divider()
-
-                overviewItem(
-                    stepIndex: 5,
-                    title: String(localized: "Permission Requests"),
-                    duration: "1",
-                    description: String(
-                        localized: "Authorize Trio to send notifications and use Bluetooth. You must allow both for Trio to work properly."
-                    )
-                )
+                    if index < (OnboardingChapter.allCases.count - 1) {
+                        Divider()
+                    }
+                }
             }
             .padding()
             .background(Color.chart.opacity(0.65))

+ 53 - 0
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuide/StartupForceCloseWarningStepView.swift

@@ -0,0 +1,53 @@
+//
+//  StartupForceCloseWarningStepView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 27.04.25.
+//
+import SwiftUI
+
+struct StartupForceCloseWarningStepView: View {
+    @Bindable var state: Onboarding.StateModel
+
+    @Environment(\.openURL) var openURL
+
+    var body: some View {
+        VStack(alignment: .leading, spacing: 20) {
+            Text("One last thing, before you begin...")
+                .font(.title3)
+                .bold()
+
+            VStack(alignment: .leading, spacing: 10) {
+                BulletPoint(
+                    String(localized: "You can pause at any time. If you feel like taking a break, do it and put the phone down!")
+                )
+                BulletPoint(
+                    String(
+                        localized: "All entries you made during Onboarding will be saved automatically when you complete the wizard."
+                    )
+                )
+            }
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .cornerRadius(10)
+
+            VStack(alignment: .leading, spacing: 10) {
+                HStack(alignment: .top, spacing: 10) {
+                    Image(systemName: "exclamationmark.triangle.fill").foregroundStyle(Color.bgDarkBlue, Color.orange)
+                        .symbolRenderingMode(.palette)
+                    Text("Important").foregroundStyle(Color.orange)
+                }.bold()
+
+                Text("Just be aware: if you force quit the app before finishing onboarding, your progress will not be saved.")
+            }
+            .frame(maxWidth: .infinity)
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .overlay(
+                RoundedRectangle(cornerRadius: 10)
+                    .stroke(Color.orange, lineWidth: 2)
+            )
+            .cornerRadius(10)
+        }
+    }
+}

+ 45 - 0
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuide/StartupGuideStepView.swift

@@ -0,0 +1,45 @@
+//
+//  StartupGuideStepView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 06.04.25.
+//
+import SwiftUI
+
+struct StartupGuideStepView: View {
+    @Bindable var state: Onboarding.StateModel
+
+    @Environment(\.openURL) var openURL
+
+    var body: some View {
+        VStack(alignment: .leading, spacing: 20) {
+            Text("Before you begin…")
+                .padding(.horizontal)
+                .font(.title3)
+                .bold()
+
+            VStack {
+                VStack(alignment: .leading, spacing: 10) {
+                    BulletPoint(String(localized: "Take a deep breath — you've got this."))
+                    BulletPoint(String(localized: "There's no rush. Take all the time you need."))
+                    BulletPoint(String(localized: "Everything you enter here can be adjusted later in the app."))
+                    BulletPoint(String(localized: "Want a hand? You can open our full Startup Guide here:"))
+                }
+
+                Button {
+                    openURL(URL(string: "https://triodocs.org/startup-guide")!)
+                } label: {
+                    Text("https://triodocs.org/startup-guide")
+                        .padding(.horizontal, 12)
+                        .padding(.vertical, 8)
+                        .background(Color.blue.opacity(0.2))
+                        .cornerRadius(8)
+                }
+                .frame(maxWidth: .infinity, alignment: .center)
+                .padding(.horizontal)
+            }.padding()
+                .background(Color.chart.opacity(0.65))
+                .cornerRadius(10)
+        }
+    }
+}

+ 67 - 0
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuide/StartupReturningUserStepView.swift

@@ -0,0 +1,67 @@
+//
+//  StartupReturningUserStepView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 27.04.25.
+//
+import SwiftUI
+
+struct StartupReturningUserStepView: View {
+    @Bindable var state: Onboarding.StateModel
+
+    @Environment(\.openURL) var openURL
+
+    var body: some View {
+        VStack(alignment: .leading, spacing: 20) {
+            Text("Already using Trio and updating from an older version?")
+                .padding(.horizontal)
+                .font(.title3)
+                .bold()
+
+            VStack(alignment: .leading, spacing: 10) {
+                HStack(alignment: .top, spacing: 10) {
+                    Image(systemName: "exclamationmark.triangle.fill").foregroundStyle(Color.bgDarkBlue, Color.orange)
+                        .symbolRenderingMode(.palette)
+                    Text("Important").foregroundStyle(Color.orange)
+                }.bold()
+
+                Text("Your treatment data (pump events, carb entries, glucose trace, etc.) are not migrated.")
+
+                Divider().overlay(Color.orange)
+
+                Text("Your algorithm settings (previously called \"OpenAPS settings\") are reset to defaults.")
+            }
+            .frame(maxWidth: .infinity)
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .overlay(
+                RoundedRectangle(cornerRadius: 10)
+                    .stroke(Color.orange, lineWidth: 2)
+            )
+            .cornerRadius(10)
+
+            VStack(alignment: .leading, spacing: 10) {
+                Text("Here's what you can expect to be preserved:")
+                    .font(.headline)
+                    .padding(.bottom, 4)
+
+                BulletPoint(String(localized: "Your pump and CGM configurations are retained and fully functional."))
+                BulletPoint(
+                    String(
+                        localized: "Your therapy settings (basal rates, carb ratios, insulin sensitivities and glucose targets) are carried over."
+                    )
+                )
+                BulletPoint(String(localized: "We recommend reviewing them carefully — Trio will guide you step-by-step."))
+                BulletPoint(
+                    String(
+                        localized: "You will also be guided through re-configuring your algorithm settings, respecting Trio's new guardrails."
+                    )
+                )
+            }
+            .frame(maxWidth: .infinity)
+            .padding()
+            .background(Color.chart.opacity(0.65))
+            .cornerRadius(10)
+        }
+    }
+}

+ 0 - 71
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/StartupGuideStepView.swift

@@ -1,71 +0,0 @@
-//
-//  StartupGuideStepView.swift
-//  Trio
-//
-//  Created by Cengiz Deniz on 06.04.25.
-//
-import SwiftUI
-
-struct StartupGuideStepView: View {
-    @Bindable var state: Onboarding.StateModel
-
-    @Environment(\.openURL) var openURL
-
-    var body: some View {
-        VStack(alignment: .leading, spacing: 20) {
-            Text("Before you begin…")
-                .padding(.horizontal)
-                .font(.title3)
-                .bold()
-
-            VStack(alignment: .leading, spacing: 10) {
-                BulletPoint(String(localized: "Take a deep breath — you've got this."))
-                BulletPoint(String(localized: "There's no rush. Take all the time you need."))
-                BulletPoint(String(localized: "Everything you enter here can be adjusted later in the app."))
-                BulletPoint(String(localized: "Want a hand? You can open our full Startup Guide here:"))
-
-                Button {
-                    openURL(URL(string: "https://triodocs.org/startup-guide")!)
-                } label: {
-                    Text("https://triodocs.org/startup-guide")
-                        .padding(.horizontal, 12)
-                        .padding(.vertical, 8)
-                        .background(Color.blue.opacity(0.2))
-                        .cornerRadius(8)
-                }
-                .frame(maxWidth: .infinity, alignment: .center)
-                .padding(.horizontal)
-            }.padding(.horizontal)
-
-            VStack(alignment: .leading, spacing: 10) {
-                Text("Already using Trio and updating from an older version?").bold()
-                BulletPoint(String(localized: "Your therapy settings, pump, and CGM configurations will be carried over."))
-                BulletPoint(
-                    String(
-                        localized: "Your algorithm settings (previously called \"OpenAPS settings\") will be reset to defaults."
-                    )
-                )
-                BulletPoint(String(localized: "We recommend reviewing them carefully — Trio will guide you step-by-step."))
-            }.padding(.horizontal)
-
-            VStack(alignment: .leading, spacing: 10) {
-                Text("One last thing, before you begin...").bold()
-                HStack {
-                    Text("You can pause at any time. Just be aware: if you ")
-                        + Text("force quit").bold()
-                        + Text(" the app before finishing onboarding, ")
-                        + Text("your progress will not be saved.").bold()
-                }
-            }.multilineTextAlignment(.leading)
-                .padding(.horizontal)
-
-            Divider()
-
-            Toggle(isOn: $state.hasReadImportantStartupNotes) {
-                Text("Got it! I'm ready to continue.").padding(.leading, 6).bold()
-            }
-            .toggleStyle(CheckboxToggleStyle(tint: Color.blue))
-            .padding(.horizontal)
-        }
-    }
-}

+ 22 - 18
Trio/Sources/Modules/Onboarding/View/OnboardingSteps/WelcomeStepView.swift

@@ -8,27 +8,31 @@ struct WelcomeStepView: View {
 
             Spacer(minLength: 10)
 
-            Text("Hi there!")
-                .font(.title2)
-                .fontWeight(.bold)
-                .multilineTextAlignment(.center)
+            VStack(alignment: .leading, spacing: 20) {
+                Text("Hi there!")
+                    .font(.title2)
+                    .fontWeight(.bold)
+                    .multilineTextAlignment(.center)
 
-            Text(
-                "Welcome to Trio - an automated insulin delivery system for iOS based on the OpenAPS algorithm with adaptations."
-            )
-            .multilineTextAlignment(.center)
-            .foregroundColor(.secondary)
+                Text(
+                    "Welcome to Trio - an automated insulin delivery system for iOS based on the OpenAPS algorithm with adaptations."
+                )
+                .multilineTextAlignment(.leading)
+                .foregroundColor(.secondary)
 
-            Text(
-                "Trio is designed to help manage your diabetes efficiently. To get the most out of the app, we'll guide you through setting up some essential parameters."
-            )
-            .multilineTextAlignment(.center)
-            .foregroundColor(.secondary)
+                Text(
+                    "Trio is designed to help manage your diabetes efficiently. To get the most out of the app, we'll guide you through setting up some essential parameters."
+                )
+                .multilineTextAlignment(.leading)
+                .foregroundColor(.secondary)
 
-            Text("Let's go through a few quick steps to ensure Trio works optimally for you.")
-                .multilineTextAlignment(.center)
-                .foregroundColor(.primary)
-                .bold()
+                Text("Let's go through a few quick steps to ensure Trio works optimally for you.")
+                    .multilineTextAlignment(.leading)
+                    .foregroundColor(.primary)
+                    .bold()
+            }
+            .padding()
+            .frame(maxWidth: .infinity, alignment: .leading)
         }
         .padding()
         .frame(maxWidth: .infinity)

+ 7 - 0
Trio/Sources/Modules/Onboarding/View/OnboardingView+AlgorithmUtil.swift

@@ -68,6 +68,13 @@ extension View {
     }
 }
 
+enum AlgorithmSettingsOverviewSubstep: Int, CaseIterable, Identifiable {
+    case contents
+    case importantNotes
+
+    var id: Int { rawValue }
+}
+
 enum AlgorithmSettingsSubstep: Int, CaseIterable, Identifiable {
     case autosensMin
     case autosensMax

+ 119 - 11
Trio/Sources/Modules/Onboarding/View/OnboardingView+Util.swift

@@ -6,10 +6,96 @@ enum OnboardingNavigationDirection {
     case backward
 }
 
+enum OnboardingChapter: Int, CaseIterable {
+    case prepareTrio
+    case therapySettings
+    case deliveryLimits
+    case algorithmSettings
+    case permissionRequests
+
+    var id: Int { rawValue }
+
+    var title: String {
+        switch self {
+        case .prepareTrio:
+            return String(localized: "Prepare Trio")
+        case .therapySettings:
+            return String(localized: "Therapy Settings")
+        case .deliveryLimits:
+            return String(localized: "Delivery Limits")
+        case .algorithmSettings:
+            return String(localized: "Algorithm Settings")
+        case .permissionRequests:
+            return String(localized: "Permission Requests")
+        }
+    }
+
+    var overviewDescription: String {
+        switch self {
+        case .prepareTrio:
+            return String(
+                localized: "Configure diagnostics sharing, optionally sync with Nightscout, and enter essentials."
+            )
+        case .therapySettings:
+            return String(
+                localized: "Define your glucose targets, basal rates, carb ratios, and insulin sensitivities."
+            )
+        case .deliveryLimits:
+            return String(
+                localized: "Set boundaries for insulin delivery and carb entries to help Trio keep you safe."
+            )
+        case .algorithmSettings:
+            return String(
+                localized: "Customize Trio’s algorithm features. Most users start with the recommended settings."
+            )
+        case .permissionRequests:
+            return String(
+                localized: "Authorize Trio to send notifications and use Bluetooth. You must allow both for Trio to work properly."
+            )
+        }
+    }
+
+    var duration: String {
+        switch self {
+        case .prepareTrio:
+            return "3-5"
+        case .therapySettings:
+            return "5-10"
+        case .deliveryLimits:
+            return "3-5"
+        case .algorithmSettings:
+            return "5-10"
+        case .permissionRequests:
+            return "1"
+        }
+    }
+
+    var completedDescription: String {
+        switch self {
+        case .prepareTrio:
+            return String(
+                localized: "App diagnostics sharing, Nightscout setup, and unit and pump model selection are all complete."
+            )
+        case .therapySettings:
+            return String(
+                localized: "Glucose target, basal rates, carb ratios, and insulin sensitivity match your needs."
+            )
+        case .deliveryLimits:
+            return String(
+                localized: "Safety boundaries for insulin delivery and carb entries are set to help Trio keep you safe."
+            )
+        case .algorithmSettings:
+            return String(localized: "Trio’s algorithm features are customized to fit your preferences and needs.")
+        case .permissionRequests:
+            return String(localized: "Notifications and Bluetooth permissions are handled to your liking.")
+        }
+    }
+}
+
 /// Represents the different steps in the onboarding process.
 enum OnboardingStep: Int, CaseIterable, Identifiable, Equatable {
     case welcome
-    case startupGuide
+    case startupInfo
     case overview
     case diagnostics
     case nightscout
@@ -33,17 +119,12 @@ enum OnboardingStep: Int, CaseIterable, Identifiable, Equatable {
         self == .deliveryLimits
     }
 
-    var substeps: [DeliveryLimitSubstep] {
-        guard hasSubsteps else { return [] }
-        return DeliveryLimitSubstep.allCases
-    }
-
     /// The title to display for this onboarding step.
     var title: String {
         switch self {
         case .welcome:
             return String(localized: "Welcome to Trio")
-        case .startupGuide:
+        case .startupInfo:
             return String(localized: "Startup Guide")
         case .overview:
             return String(localized: "Overview")
@@ -87,7 +168,7 @@ enum OnboardingStep: Int, CaseIterable, Identifiable, Equatable {
             return String(
                 localized: "Trio is a powerful app that helps you manage your diabetes. Let's get started by setting up a few important parameters that will help Trio work effectively for you."
             )
-        case .startupGuide:
+        case .startupInfo:
             return String(
                 localized: "Trio comes with a helpful Startup Guide. We recommend opening it now and following along as you go — side by side."
             )
@@ -159,7 +240,7 @@ enum OnboardingStep: Int, CaseIterable, Identifiable, Equatable {
         switch self {
         case .welcome:
             return "hand.wave.fill"
-        case .startupGuide:
+        case .startupInfo:
             return "list.bullet.clipboard.fill"
         case .overview:
             return "checklist.unchecked"
@@ -225,7 +306,7 @@ enum OnboardingStep: Int, CaseIterable, Identifiable, Equatable {
              .notifications,
              .overview,
              .smbSettings,
-             .startupGuide,
+             .startupInfo,
              .targetBehavior,
              .unitSelection,
              .welcome:
@@ -240,10 +321,37 @@ enum OnboardingStep: Int, CaseIterable, Identifiable, Equatable {
             return Color.red
         }
     }
+
+    var chapterCompletion: OnboardingChapter? {
+        switch self {
+        case .unitSelection:
+            return .prepareTrio
+        case .insulinSensitivity:
+            return .therapySettings
+        case .deliveryLimits:
+            // ❗ Delivery Limits depends on the substep, not just the step.
+            // Skip here
+            return nil
+        case .targetBehavior:
+            // ❗ Target Behavior depends on the substep, not just the step.
+            // Skip here
+            return nil
+        default:
+            return nil
+        }
+    }
 }
 
 var nonInfoOnboardingSteps: [OnboardingStep] { OnboardingStep.allCases
-    .filter { $0 != .welcome && $0 != .startupGuide && $0 != .overview && $0 != .completed }
+    .filter { $0 != .welcome && $0 != .startupInfo && $0 != .overview && $0 != .completed }
+}
+
+enum StartupSubstep: Int, CaseIterable, Identifiable {
+    case startupGuide
+    case returningUser
+    case forceCloseWarning
+
+    var id: Int { rawValue }
 }
 
 enum DeliveryLimitSubstep: Int, CaseIterable, Identifiable {