Explorar o código

Continue restructuring settings
* Re-Order settings root view
* Introduce sub-level hierarchical navigation views
* Add placeholders and TODOs for settings/section to move
* WIP

Deniz Cengiz hai 1 ano
pai
achega
940b0c6cb5

+ 31 - 6
FreeAPS.xcodeproj/project.pbxproj

@@ -385,8 +385,12 @@
 		D6DEC113821A7F1056C4AA1E /* NightscoutConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F2A13DF0EDEEEDC4106AA2A /* NightscoutConfigDataFlow.swift */; };
 		D76333C9256787610B3B4875 /* AutotuneConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D295A3F870E826BE371C0BB5 /* AutotuneConfigStateModel.swift */; };
 		DBA5254DBB2586C98F61220C /* ISFEditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F9F137F126D9F8DEB799F26 /* ISFEditorProvider.swift */; };
+		DD1745132C54169400211FAC /* DevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745122C54169400211FAC /* DevicesView.swift */; };
+		DD1745152C54388A00211FAC /* TherapySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745142C54388A00211FAC /* TherapySettingsView.swift */; };
+		DD1745172C54389F00211FAC /* FeatureSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745162C54389F00211FAC /* FeatureSettingsView.swift */; };
+		DD1745192C543B5700211FAC /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1745182C543B5700211FAC /* NotificationsView.swift */; };
+		DD17451D2C543C5F00211FAC /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17451C2C543C5F00211FAC /* ServicesView.swift */; };
 		DD1DB7CC2BECCA1F0048B367 /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */; };
-		DD1DB7CE2BED00CF0048B367 /* SettingsRootViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1DB7CD2BED00CF0048B367 /* SettingsRootViewModel.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 */; };
 		DD57C4B32C4C7103001A5B28 /* LoopStatRecord+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD57C4912C4C7103001A5B28 /* LoopStatRecord+CoreDataProperties.swift */; };
@@ -988,8 +992,12 @@
 		D295A3F870E826BE371C0BB5 /* AutotuneConfigStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AutotuneConfigStateModel.swift; sourceTree = "<group>"; };
 		D97F14812C1AFED3621165A5 /* PumpSettingsEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PumpSettingsEditorProvider.swift; sourceTree = "<group>"; };
 		DC2C6489D29ECCCAD78E0721 /* NotificationsConfigStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NotificationsConfigStateModel.swift; sourceTree = "<group>"; };
+		DD1745122C54169400211FAC /* DevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesView.swift; sourceTree = "<group>"; };
+		DD1745142C54388A00211FAC /* TherapySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySettingsView.swift; sourceTree = "<group>"; };
+		DD1745162C54389F00211FAC /* FeatureSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureSettingsView.swift; sourceTree = "<group>"; };
+		DD1745182C543B5700211FAC /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
+		DD17451C2C543C5F00211FAC /* ServicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesView.swift; sourceTree = "<group>"; };
 		DD1DB7CB2BECCA1F0048B367 /* BuildDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildDetails.swift; sourceTree = "<group>"; };
-		DD1DB7CD2BED00CF0048B367 /* SettingsRootViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRootViewModel.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; };
 		DD57C4922C4C7103001A5B28 /* MealPresetStored+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MealPresetStored+CoreDataClass.swift"; sourceTree = SOURCE_ROOT; };
@@ -1458,9 +1466,9 @@
 		3811DE3B25C9D4A100A708ED /* View */ = {
 			isa = PBXGroup;
 			children = (
+				DD1745112C54168300211FAC /* Subviews */,
 				3811DE3C25C9D4A100A708ED /* SettingsRootView.swift */,
 				CE1F6DE82BAF37C90064EB8D /* TidepoolConfigView.swift */,
-				DD1DB7CD2BED00CF0048B367 /* SettingsRootViewModel.swift */,
 				65070A322BFDCB83006F213F /* TidepoolStartView.swift */,
 			);
 			path = View;
@@ -2397,6 +2405,18 @@
 			path = ISFEditor;
 			sourceTree = "<group>";
 		};
+		DD1745112C54168300211FAC /* Subviews */ = {
+			isa = PBXGroup;
+			children = (
+				DD1745122C54169400211FAC /* DevicesView.swift */,
+				DD1745142C54388A00211FAC /* TherapySettingsView.swift */,
+				DD1745162C54389F00211FAC /* FeatureSettingsView.swift */,
+				DD1745182C543B5700211FAC /* NotificationsView.swift */,
+				DD17451C2C543C5F00211FAC /* ServicesView.swift */,
+			);
+			path = Subviews;
+			sourceTree = "<group>";
+		};
 		DD57C46C2C4C7003001A5B28 /* Classes+Properties */ = {
 			isa = PBXGroup;
 			children = (
@@ -2575,7 +2595,7 @@
 				38E8753D27554D5900975559 /* Embed Watch Content */,
 				6B1A8D122B14D88E00E76752 /* Embed Foundation Extensions */,
 				CE95BF582BA5F8F300DC3DE3 /* Install plugins */,
-				DD88C8DF2C4D583900F2D558 /* ShellScript */,
+				DD88C8DF2C4D583900F2D558 /* Run Script: Capture Build Details */,
 			);
 			buildRules = (
 			);
@@ -2835,7 +2855,7 @@
 			shellPath = /bin/sh;
 			shellScript = "\"${SRCROOT}/Scripts/copy-plugins.sh\"\n";
 		};
-		DD88C8DF2C4D583900F2D558 /* ShellScript */ = {
+		DD88C8DF2C4D583900F2D558 /* Run Script: Capture Build Details */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -2844,6 +2864,7 @@
 			);
 			inputPaths = (
 			);
+			name = "Run Script: Capture Build Details";
 			outputFileListPaths = (
 			);
 			outputPaths = (
@@ -2978,6 +2999,7 @@
 				38E98A2725F52C9300C0CED0 /* CollectionIssueReporter.swift in Sources */,
 				E00EEC0427368630002FF094 /* SecurityAssembly.swift in Sources */,
 				3811DEE825CA063400A708ED /* Injected.swift in Sources */,
+				DD1745152C54388A00211FAC /* TherapySettingsView.swift in Sources */,
 				585E2CAE2BE7BF46006ECF1A /* PumpEvent+helper.swift in Sources */,
 				DDD1631F2C4C6F6900CD525A /* TrioCoreDataPersistentContainer.xcdatamodeld in Sources */,
 				3811DEAF25C9D88300A708ED /* KeyValueStorage.swift in Sources */,
@@ -2986,7 +3008,6 @@
 				3811DE0B25C9D32F00A708ED /* BaseView.swift in Sources */,
 				3811DE3225C9D49500A708ED /* HomeDataFlow.swift in Sources */,
 				CE1856F52ADC4858007E39C7 /* AddCarbPresetIntent.swift in Sources */,
-				DD1DB7CE2BED00CF0048B367 /* SettingsRootViewModel.swift in Sources */,
 				38569347270B5DFB0002C50D /* CGMType.swift in Sources */,
 				3821ED4C25DD18BA00BC42AD /* Constants.swift in Sources */,
 				384E803425C385E60086DB71 /* JavaScriptWorker.swift in Sources */,
@@ -3030,6 +3051,7 @@
 				DD57C4D32C4C7103001A5B28 /* StatsData+CoreDataProperties.swift in Sources */,
 				3811DEAE25C9D88300A708ED /* Cache.swift in Sources */,
 				383420D625FFE38C002D46C1 /* LoopView.swift in Sources */,
+				DD1745192C543B5700211FAC /* NotificationsView.swift in Sources */,
 				3811DEAD25C9D88300A708ED /* UserDefaults+Cache.swift in Sources */,
 				CE48C86628CA6B48007C0598 /* OmniPodManagerExtensions.swift in Sources */,
 				CEB434E728B9053300B70274 /* LoopUIColorPalette+Default.swift in Sources */,
@@ -3064,6 +3086,7 @@
 				CE82E02528E867BA00473A9C /* AlertStorage.swift in Sources */,
 				38BF021D25E7E3AF00579895 /* Reservoir.swift in Sources */,
 				583684082BD195A700070A60 /* Determination.swift in Sources */,
+				DD17451D2C543C5F00211FAC /* ServicesView.swift in Sources */,
 				38BF021B25E7D06400579895 /* PumpSettingsView.swift in Sources */,
 				3811DEEA25CA063400A708ED /* SyncAccess.swift in Sources */,
 				190EBCC829FF13AA00BA767D /* StatConfigStateModel.swift in Sources */,
@@ -3143,6 +3166,7 @@
 				389442CB25F65F7100FA1F27 /* NightscoutTreatment.swift in Sources */,
 				CE7CA3512A064973004BE681 /* ApplyTempPresetIntent.swift in Sources */,
 				FA630397F76B582C8D8681A7 /* BasalProfileEditorProvider.swift in Sources */,
+				DD1745172C54389F00211FAC /* FeatureSettingsView.swift in Sources */,
 				63E890B4D951EAA91C071D5C /* BasalProfileEditorStateModel.swift in Sources */,
 				38FEF3FA2737E42000574A46 /* BaseStateModel.swift in Sources */,
 				CC6C406E2ACDD69E009B8058 /* RawFetchedProfile.swift in Sources */,
@@ -3232,6 +3256,7 @@
 				38A00B2325FC2B55006BC0B0 /* LRUCache.swift in Sources */,
 				DDD163122C4C689900CD525A /* OverrideStateModel.swift in Sources */,
 				3083261C4B268E353F36CD0B /* AutotuneConfigDataFlow.swift in Sources */,
+				DD1745132C54169400211FAC /* DevicesView.swift in Sources */,
 				891DECF7BC20968D7F566161 /* AutotuneConfigProvider.swift in Sources */,
 				D76333C9256787610B3B4875 /* AutotuneConfigStateModel.swift in Sources */,
 				A05235B9112E677ED03B6E8E /* AutotuneConfigRootView.swift in Sources */,

+ 165 - 196
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -9,7 +9,6 @@ extension Settings {
         let resolver: Resolver
         @StateObject var state = StateModel()
         @State private var showShareSheet = false
-        @StateObject private var viewModel = SettingsRootViewModel()
 
         @State private var searchText: String = ""
 
@@ -35,228 +34,197 @@ extension Settings {
 
         var body: some View {
             Form {
-//                Section {
-//                    Toggle("Closed loop", isOn: $state.closedLoop)
-//                }
-//                header: {
-//                    Text(viewModel.headerText).textCase(nil)
-//                }.listRowBackground(Color.chart)
+                let buildDetails = BuildDetails.default
 
-                Section {
-                    let buildDetails = BuildDetails.default
-                    let versionNumber = Bundle.main.releaseVersionNumber ?? "Unknown"
-                    let buildNumber = Bundle.main.buildVersionNumber ?? "Unknown"
-                    let branch = buildDetails.branchAndSha
+                Section(
+                    header: Text("BRANCH: \(buildDetails.branchAndSha)").textCase(nil),
+                    content: {
+                        let versionNumber = Bundle.main.releaseVersionNumber ?? "Unknown"
+                        let buildNumber = Bundle.main.buildVersionNumber ?? "Unknown"
 
-                    Group {
-                        HStack {
-                            Image(uiImage: UIImage(named: appIcons.appIcon.rawValue) ?? UIImage())
-                                .resizable()
-                                .aspectRatio(contentMode: .fit)
-                                .frame(width: 50, height: 50)
-                                .padding(.trailing, 10)
-                            VStack(alignment: .leading) {
-                                Text("Trio v\(versionNumber) (\(buildNumber))")
-                                    .font(.headline)
-                                Text("Branch: \(branch)")
-                                    .font(.footnote)
-                                    .foregroundColor(.secondary)
-                                if let expirationDate = buildDetails.calculateExpirationDate() {
-                                    let formattedDate = DateFormatter.localizedString(
-                                        from: expirationDate,
-                                        dateStyle: .medium,
-                                        timeStyle: .none
-                                    )
-                                    Text("\(buildDetails.expirationHeaderString): \(formattedDate)")
-                                        .font(.footnote)
-                                        .foregroundColor(.secondary)
+                        Group {
+                            HStack {
+                                Image(uiImage: UIImage(named: appIcons.appIcon.rawValue) ?? UIImage())
+                                    .resizable()
+                                    .aspectRatio(contentMode: .fit)
+                                    .frame(width: 50, height: 50)
+                                    .padding(.trailing, 10)
+                                VStack(alignment: .leading) {
+                                    Text("Trio v\(versionNumber) (\(buildNumber))")
+                                        .font(.headline)
+                                    if let expirationDate = buildDetails.calculateExpirationDate() {
+                                        let formattedDate = DateFormatter.localizedString(
+                                            from: expirationDate,
+                                            dateStyle: .medium,
+                                            timeStyle: .none
+                                        )
+                                        Text("\(buildDetails.expirationHeaderString): \(formattedDate)")
+                                            .font(.footnote)
+                                            .foregroundColor(.secondary)
+                                    } else {
+                                        Text("Simulator Build has no expiry")
+                                            .font(.footnote)
+                                            .foregroundColor(.secondary)
+                                    }
                                 }
                             }
-                        }
 
-                        Text("Statistics").navigationLink(to: .statistics, from: self)
+                            Text("Statistics").navigationLink(to: .statistics, from: self)
+                        }
                     }
-                }.listRowBackground(Color.chart)
-
-                Section {
-                    VStack {
-                        Toggle("Closed Loop", isOn: $state.closedLoop)
-
-                        Spacer()
-
-                        (
-                            Text("Running Trio in")
-                                +
-                                Text(" closed loop mode ").bold()
-                                +
-                                Text("requires an active CGM session sensor session and a connected pump.")
-                                +
-                                Text("This enables automated insulin delivery.").bold()
-                        )
-                        .foregroundColor(.secondary)
-                        .font(.footnote)
-
-                    }.padding(.vertical)
-                }.listRowBackground(Color.chart)
-
-                Section {
-                    Text("Pump").navigationLink(to: .pumpConfig, from: self)
-                    Text("CGM").navigationLink(to: .cgm, from: self)
-                    Text("Watch").navigationLink(to: .watch, from: self)
-                    // TODO: combine pump + pump settings?!
-                    Text("Pump Settings").navigationLink(to: .pumpSettingsEditor, from: self)
-                } header: { Text("Devices") }.listRowBackground(Color.chart)
+                ).listRowBackground(Color.chart)
 
-                Section {
-                    Text("Basal Profile").navigationLink(to: .basalProfileEditor, from: self)
-                    Text("Insulin Sensitivities").navigationLink(to: .isfEditor, from: self)
-                    Text("Carb Ratios").navigationLink(to: .crEditor, from: self)
-                    Text("Target Glucose").navigationLink(to: .targetsEditor, from: self)
-                    Text("Autotune").navigationLink(to: .autotuneConfig, from: self)
-                } header: { Text("Profiles") }.listRowBackground(Color.chart)
+                Section(
+                    header: Text("Automated Insulin Delivery"),
+                    content: {
+                        VStack {
+                            Toggle("Closed Loop", isOn: $state.closedLoop)
 
-                Section {
-                    Text("Preferences").navigationLink(to: .preferencesEditor, from: self)
-                    Text("Dynamic Settings").navigationLink(to: .dynamicISF, from: self)
-                } header: { Text("Algorithm") }.listRowBackground(Color.chart)
+                            Spacer()
 
-                Section {
-                    Text("UI/UX").navigationLink(to: .statisticsConfig, from: self)
-                    Text("Meal Settings").navigationLink(to: .fpuConfig, from: self)
-                    Text("Bolus Calculator").navigationLink(to: .bolusCalculatorConfig, from: self)
-                    Text("App Icons").navigationLink(to: .iconConfig, from: self)
-                } header: { Text("App Configuration") }.listRowBackground(Color.chart)
+                            (
+                                Text("Running Trio in")
+                                    +
+                                    Text(" closed loop mode ").bold()
+                                    +
+                                    Text("requires an active CGM session sensor session and a connected pump.")
+                                    +
+                                    Text("This enables automated insulin delivery.").bold()
+                            )
+                            .foregroundColor(.secondary)
+                            .font(.footnote)
 
-                Section {
-                    Text("App Notifications").navigationLink(to: .notificationsConfig, from: self)
-                    Text("Live Activity")
-                } header: { Text("Notifications") }.listRowBackground(Color.chart)
-
-                Section {
-                    Text("Nightscout").navigationLink(to: .nighscoutConfig, from: self)
-
-                    NavigationLink(destination: TidepoolStartView(state: state)) {
-                        Text("Tidepool")
+                        }.padding(.vertical)
                     }
+                ).listRowBackground(Color.chart)
 
-                    if HKHealthStore.isHealthDataAvailable() {
-                        Text("Apple Health").navigationLink(to: .healthkit, from: self)
+                Section(
+                    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("Notifications").navigationLink(to: .notificationSettings, from: self)
+                        Text("Services").navigationLink(to: .serviceSettings, from: self)
                     }
+                ).listRowBackground(Color.chart)
 
-                    Text("Shortcuts", tableName: "ShortcutsDetail").navigationLink(to: .shortcutsConfig, from: self)
-                } header: { Text("Services") }.listRowBackground(Color.chart)
-
-                Section {
-                    HStack {
-                        Text("Share Logs")
-                            .onTapGesture {
-                                showShareSheet.toggle()
-                            }
-                        Spacer()
-                        Image(systemName: "chevron.right").foregroundColor(.secondary)
-                    }
+                Section(
+                    header: Text("Support & Community"),
+                    content: {
+                        HStack {
+                            Text("Share Logs")
+                                .onTapGesture {
+                                    showShareSheet.toggle()
+                                }
+                            Spacer()
+                            Image(systemName: "chevron.right").foregroundColor(.secondary)
+                        }
 
-                    HStack {
-                        Text("Submit Ticket on GitHub")
-                            .onTapGesture {
-                                if let url = URL(string: "https://github.com/nightscout/Trio/issues/new/choose") {
-                                    UIApplication.shared.open(url)
+                        HStack {
+                            Text("Submit Ticket on GitHub")
+                                .onTapGesture {
+                                    if let url = URL(string: "https://github.com/nightscout/Trio/issues/new/choose") {
+                                        UIApplication.shared.open(url)
+                                    }
                                 }
-                            }
-                        Spacer()
-                        Image(systemName: "chevron.right").foregroundColor(.secondary)
-                    }
+                            Spacer()
+                            Image(systemName: "chevron.right").foregroundColor(.secondary)
+                        }
 
-                    HStack {
-                        Text("Trio Discord")
-                            .onTapGesture {
-                                if let url = URL(string: "https://discord.gg/FnwFEFUwXE") {
-                                    UIApplication.shared.open(url)
+                        HStack {
+                            Text("Trio Discord")
+                                .onTapGesture {
+                                    if let url = URL(string: "https://discord.gg/FnwFEFUwXE") {
+                                        UIApplication.shared.open(url)
+                                    }
                                 }
-                            }
-                        Spacer()
-                        Image(systemName: "chevron.right").foregroundColor(.secondary)
-                    }
+                            Spacer()
+                            Image(systemName: "chevron.right").foregroundColor(.secondary)
+                        }
 
-                    HStack {
-                        Text("Trio Facebook")
-                            .onTapGesture {
-                                if let url = URL(string: "https://m.facebook.com/groups/1351938092206709/") {
-                                    UIApplication.shared.open(url)
+                        HStack {
+                            Text("Trio Facebook")
+                                .onTapGesture {
+                                    if let url = URL(string: "https://m.facebook.com/groups/1351938092206709/") {
+                                        UIApplication.shared.open(url)
+                                    }
                                 }
-                            }
-                        Spacer()
-                        Image(systemName: "chevron.right").foregroundColor(.secondary)
+                            Spacer()
+                            Image(systemName: "chevron.right").foregroundColor(.secondary)
+                        }
                     }
-                } header: { Text("Support") }.listRowBackground(Color.chart)
+                ).listRowBackground(Color.chart)
 
-                Section {
-                    Toggle("Debug options", isOn: $state.debugOptions)
-                    if state.debugOptions {
-                        Group {
-                            HStack {
-                                Text("NS Upload Profile and Settings")
-                                Button("Upload") { state.uploadProfileAndSettings(true) }
-                                    .frame(maxWidth: .infinity, alignment: .trailing)
-                                    .buttonStyle(.borderedProminent)
-                            }
-                            // Commenting this out for now, as not needed and possibly dangerous for users to be able to nuke their pump pairing informations via the debug menu
-                            // Leaving it in here, as it may be a handy functionality for further testing or developers.
-                            // See https://github.com/nightscout/Trio/pull/277 for more information
-//
+                // TODO: remove this more or less entirely; add build-time flag to enable Middleware; add settings export feature
+//                Section {
+//                    Toggle("Developer Options", isOn: $state.debugOptions)
+//                    if state.debugOptions {
+//                        Group {
 //                            HStack {
-//                                Text("Delete Stored Pump State Binary Files")
-//                                Button("Delete") { state.resetLoopDocuments() }
+//                                Text("NS Upload Profile and Settings")
+//                                Button("Upload") { state.uploadProfileAndSettings(true) }
 //                                    .frame(maxWidth: .infinity, alignment: .trailing)
 //                                    .buttonStyle(.borderedProminent)
 //                            }
-                        }
-                        Group {
-                            Text("Preferences")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.preferences), from: self)
-                            Text("Pump Settings")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.settings), from: self)
-                            Text("Autosense")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.autosense), from: self)
-//                            Text("Pump History")
-//                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.pumpHistory), from: self)
-                            Text("Basal profile")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.basalProfile), from: self)
-                            Text("Targets ranges")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.bgTargets), from: self)
-                            Text("Temp targets")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.tempTargets), from: self)
-                        }
-
-                        Group {
-                            Text("Pump profile")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.pumpProfile), from: self)
-                            Text("Profile")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.profile), from: self)
-//                            Text("Carbs")
-//                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.carbHistory), from: self)
-//                            Text("Announcements")
-//                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcements), from: self)
-//                            Text("Enacted announcements")
-//                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcementsEnacted), from: self)
-                            Text("Autotune")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.autotune), from: self)
-                        }
+//                            // Commenting this out for now, as not needed and possibly dangerous for users to be able to nuke their pump pairing informations via the debug menu
+//                            // Leaving it in here, as it may be a handy functionality for further testing or developers.
+//                            // See https://github.com/nightscout/Trio/pull/277 for more information
+//                            //
+//                            //                            HStack {
+//                            //                                Text("Delete Stored Pump State Binary Files")
+//                            //                                Button("Delete") { state.resetLoopDocuments() }
+//                            //                                    .frame(maxWidth: .infinity, alignment: .trailing)
+//                            //                                    .buttonStyle(.borderedProminent)
+//                            //                            }
+//                        }
+//                        Group {
+//                            Text("Preferences")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.preferences), from: self)
+//                            Text("Pump Settings")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.settings), from: self)
+//                            Text("Autosense")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.autosense), from: self)
+//                            //                            Text("Pump History")
+//                            //                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.pumpHistory), from: self)
+//                            Text("Basal profile")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.basalProfile), from: self)
+//                            Text("Targets ranges")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.bgTargets), from: self)
+//                            Text("Temp targets")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.tempTargets), from: self)
+//                        }
+//
+//                        Group {
+//                            Text("Pump profile")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.pumpProfile), from: self)
+//                            Text("Profile")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.profile), from: self)
+//                            //                            Text("Carbs")
+//                            //                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.carbHistory), from: self)
+//                            //                            Text("Announcements")
+//                            //                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcements), from: self)
+//                            //                            Text("Enacted announcements")
+//                            //                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcementsEnacted), from: self)
+//                            Text("Autotune")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Settings.autotune), from: self)
+//                        }
+//
+//                        Group {
+//                            Text("Target presets")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.tempTargetsPresets), from: self)
+//                            Text("Calibrations")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.calibrations), from: self)
+//                            Text("Middleware")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.Middleware.determineBasal), from: self)
+//                            //                            Text("Statistics")
+//                            //                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.statistics), from: self)
+//                            Text("Edit settings json")
+//                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.settings), from: self)
+//                        }
+//                    }
+//                }.listRowBackground(Color.chart)
 
-                        Group {
-                            Text("Target presets")
-                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.tempTargetsPresets), from: self)
-                            Text("Calibrations")
-                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.calibrations), from: self)
-                            Text("Middleware")
-                                .navigationLink(to: .configEditor(file: OpenAPS.Middleware.determineBasal), from: self)
-//                            Text("Statistics")
-//                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.statistics), from: self)
-                            Text("Edit settings json")
-                                .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.settings), from: self)
-                        }
-                    }
-                } header: { Text("Developer") }.listRowBackground(Color.chart)
             }.scrollContentBackground(.hidden).background(color)
                 .sheet(isPresented: $showShareSheet) {
                     ShareSheet(activityItems: state.logItems())
@@ -281,6 +249,7 @@ extension Settings {
                         )
                     }
                 }
+                // TODO: check how to implement intuitive search
 //                .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
                 .onDisappear(perform: { state.uploadProfileAndSettings(false) })
                 .screenNavigation(self)

+ 52 - 0
FreeAPS/Sources/Modules/Settings/View/Subviews/DevicesView.swift

@@ -0,0 +1,52 @@
+//
+//  FeatureSettingsView.swift
+//  FreeAPS
+//
+//  Created by Deniz Cengiz on 26.07.24.
+//
+import Foundation
+import SwiftUI
+import Swinject
+
+struct DevicesView: 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("Setup & Configuraton"),
+                content: {
+                    Text("Pump").navigationLink(to: .pumpConfig, from: self)
+                    Text("Pump Settings").navigationLink(to: .pumpSettingsEditor, from: self)
+                    Text("TODO: Migrate Settings into Pump 👆")
+                    Text("CGM").navigationLink(to: .cgm, from: self)
+                    Text("Watch").navigationLink(to: .watch, from: self)
+                }
+            )
+            .listRowBackground(Color.chart)
+        }
+        .scrollContentBackground(.hidden).background(color)
+        .navigationTitle("Devices")
+        .navigationBarTitleDisplayMode(.automatic)
+    }
+}

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

@@ -0,0 +1,63 @@
+//
+//  FeatureSettingsView.swift
+//  FreeAPS
+//
+//  Created by Deniz Cengiz on 26.07.24.
+//
+import Foundation
+import SwiftUI
+import Swinject
+
+struct FeatureSettingsView: 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("Preferences (to be omitted").navigationLink(to: .preferencesEditor, from: self)
+                    Text("Autosens Settings")
+                    Text("Super-Micro-Bolus (SMB) Settings")
+                    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)
+                    Text("Meal Settings").navigationLink(to: .fpuConfig, from: self)
+                    Text("Shortcuts").navigationLink(to: .shortcutsConfig, from: self)
+                    Text("UI/UX").navigationLink(to: .statisticsConfig, from: self)
+                    Text("TODO: Move App Icons into UI/UX 👆")
+                    Text("App Icons").navigationLink(to: .iconConfig, from: self)
+                }
+            )
+            .listRowBackground(Color.chart)
+        }
+        .scrollContentBackground(.hidden).background(color)
+        .navigationTitle("Feature Settings")
+        .navigationBarTitleDisplayMode(.automatic)
+    }
+}

+ 50 - 0
FreeAPS/Sources/Modules/Settings/View/Subviews/NotificationsView.swift

@@ -0,0 +1,50 @@
+//
+//  FeatureSettingsView.swift
+//  FreeAPS
+//
+//  Created by Deniz Cengiz on 26.07.24.
+//
+import Foundation
+import SwiftUI
+import Swinject
+
+struct NotificationsView: 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("Notification Center"),
+                content: {
+                    Text("Alerts").navigationLink(to: .notificationsConfig, from: self)
+                    Text("TODO: Live Activity Settings View")
+                    Text("TODO: Calendar Events Settings View")
+                }
+            )
+            .listRowBackground(Color.chart)
+        }
+        .scrollContentBackground(.hidden).background(color)
+        .navigationTitle("Notifications")
+        .navigationBarTitleDisplayMode(.automatic)
+    }
+}

+ 55 - 0
FreeAPS/Sources/Modules/Settings/View/Subviews/ServicesView.swift

@@ -0,0 +1,55 @@
+//
+//  FeatureSettingsView.swift
+//  FreeAPS
+//
+//  Created by Deniz Cengiz on 26.07.24.
+//
+import Foundation
+import HealthKit
+import SwiftUI
+import Swinject
+
+struct ServicesView: 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("Connected Services"),
+                content: {
+                    Text("Nightscout").navigationLink(to: .nighscoutConfig, from: self)
+                    NavigationLink(destination: TidepoolStartView(state: state)) {
+                        Text("Tidepool")
+                    }
+                    if HKHealthStore.isHealthDataAvailable() {
+                        Text("Apple Health").navigationLink(to: .healthkit, from: self)
+                    }
+                }
+            )
+            .listRowBackground(Color.chart)
+        }
+        .scrollContentBackground(.hidden).background(color)
+        .navigationTitle("Services")
+        .navigationBarTitleDisplayMode(.automatic)
+    }
+}

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

@@ -0,0 +1,59 @@
+//
+//  FeatureSettingsView.swift
+//  FreeAPS
+//
+//  Created by Deniz Cengiz on 26.07.24.
+//
+import Foundation
+import SwiftUI
+import Swinject
+
+struct TherapySettingsView: 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("Basic Insulin Rates & Targets"),
+                content: {
+                    Text("Basal Rates").navigationLink(to: .basalProfileEditor, from: self)
+                    Text("Insulin Sensitivities").navigationLink(to: .isfEditor, from: self)
+                    Text("Carb Ratios").navigationLink(to: .crEditor, from: self)
+                    Text("Target Glucose").navigationLink(to: .targetsEditor, from: self)
+                }
+            )
+            .listRowBackground(Color.chart)
+
+            Section(
+                header: Text("Data-Driven Settings Tuning"),
+                content: {
+                    Text("Autotune").navigationLink(to: .autotuneConfig, from: self)
+                }
+            )
+            .listRowBackground(Color.chart)
+        }
+        .scrollContentBackground(.hidden).background(color)
+        .navigationTitle("Therapy Settings")
+        .navigationBarTitleDisplayMode(.automatic)
+    }
+}

+ 15 - 0
FreeAPS/Sources/Router/Screen.swift

@@ -35,6 +35,11 @@ enum Screen: Identifiable, Hashable {
     case dynamicISF
     case calibrations
     case shortcutsConfig
+    case devices
+    case therapySettings
+    case featureSettings
+    case notificationSettings
+    case serviceSettings
 
     var id: Int { String(reflecting: self).hashValue }
 }
@@ -108,6 +113,16 @@ extension Screen {
             Calibrations.RootView(resolver: resolver)
         case .shortcutsConfig:
             ShortcutsConfig.RootView(resolver: resolver)
+        case .devices:
+            DevicesView(resolver: resolver, state: Settings.StateModel())
+        case .therapySettings:
+            TherapySettingsView(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())
         }
     }