Jonas Björkert 1 год назад
Родитель
Сommit
15f461bdc1

+ 8 - 24
LoopFollow.xcodeproj/project.pbxproj

@@ -125,7 +125,7 @@
 		DD8316482DE49EE5004467AA /* Storage+Migrate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8316472DE49EE5004467AA /* Storage+Migrate.swift */; };
 		DD83164A2DE4C504004467AA /* SettingsStepperRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8316492DE4C504004467AA /* SettingsStepperRow.swift */; };
 		DD83164C2DE4DB3A004467AA /* BinaryFloatingPoint+localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD83164B2DE4DB3A004467AA /* BinaryFloatingPoint+localized.swift */; };
-		DD83164E2DE4E093004467AA /* WatchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD83164D2DE4E093004467AA /* WatchSettingsView.swift */; };
+		DD83164E2DE4E093004467AA /* CalendarSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD83164D2DE4E093004467AA /* CalendarSettingsView.swift */; };
 		DD8316502DE4E635004467AA /* SettingsMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD83164F2DE4E635004467AA /* SettingsMenuView.swift */; };
 		DD85E9952D739CFE001C8BB7 /* OmnipodDashHeartbeatBluetoothTransmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD85E9942D739CED001C8BB7 /* OmnipodDashHeartbeatBluetoothTransmitter.swift */; };
 		DD91E4DD2BDEC3F8002D9E97 /* GlucoseConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD91E4DC2BDEC3F8002D9E97 /* GlucoseConversion.swift */; };
@@ -492,7 +492,7 @@
 		DD8316472DE49EE5004467AA /* Storage+Migrate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+Migrate.swift"; sourceTree = "<group>"; };
 		DD8316492DE4C504004467AA /* SettingsStepperRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsStepperRow.swift; sourceTree = "<group>"; };
 		DD83164B2DE4DB3A004467AA /* BinaryFloatingPoint+localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BinaryFloatingPoint+localized.swift"; sourceTree = "<group>"; };
-		DD83164D2DE4E093004467AA /* WatchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSettingsView.swift; sourceTree = "<group>"; };
+		DD83164D2DE4E093004467AA /* CalendarSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarSettingsView.swift; sourceTree = "<group>"; };
 		DD83164F2DE4E635004467AA /* SettingsMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMenuView.swift; sourceTree = "<group>"; };
 		DD85E9942D739CED001C8BB7 /* OmnipodDashHeartbeatBluetoothTransmitter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OmnipodDashHeartbeatBluetoothTransmitter.swift; sourceTree = "<group>"; };
 		DD91E4DC2BDEC3F8002D9E97 /* GlucoseConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseConversion.swift; sourceTree = "<group>"; };
@@ -852,11 +852,15 @@
 			isa = PBXGroup;
 			children = (
 				DD83164F2DE4E635004467AA /* SettingsMenuView.swift */,
-				DD83164D2DE4E093004467AA /* WatchSettingsView.swift */,
+				DD2C2E552D3C3913006413A5 /* DexcomSettingsView.swift */,
+				DD2C2E532D3C37D7006413A5 /* DexcomSettingsViewModel.swift */,
+				DD83164D2DE4E093004467AA /* CalendarSettingsView.swift */,
 				DD8316452DE49B09004467AA /* GraphSettingsView.swift */,
 				DD1A97152D4294B2000DDC11 /* AdvancedSettingsViewModel.swift */,
 				DD1A97132D4294A4000DDC11 /* AdvancedSettingsView.swift */,
 				DD8316172DE3633D004467AA /* GeneralSettingsView.swift */,
+				DD50C74F2D0828800057AE6F /* ContactSettingsViewModel.swift */,
+				DD50C7522D0828D10057AE6F /* ContactSettingsView.swift */,
 			);
 			path = Settings;
 			sourceTree = "<group>";
@@ -870,15 +874,6 @@
 			path = Nightscout;
 			sourceTree = "<group>";
 		};
-		DD2C2E522D3C36A8006413A5 /* Dexcom */ = {
-			isa = PBXGroup;
-			children = (
-				DD2C2E552D3C3913006413A5 /* DexcomSettingsView.swift */,
-				DD2C2E532D3C37D7006413A5 /* DexcomSettingsViewModel.swift */,
-			);
-			path = Dexcom;
-			sourceTree = "<group>";
-		};
 		DD4878062C7B2E9E0048F05C /* Settings */ = {
 			isa = PBXGroup;
 			children = (
@@ -932,21 +927,11 @@
 				DDA9ACAB2D6B316F00E6F1A9 /* ContactType.swift */,
 				DDA9ACA92D6A6B8200E6F1A9 /* ContactIncludeOption.swift */,
 				DDA9ACA72D6A66DD00E6F1A9 /* ContactColorOption.swift */,
-				DD50C7512D0828B40057AE6F /* Settings */,
 				DD50C7542D0862770057AE6F /* ContactImageUpdater.swift */,
 			);
 			path = Contact;
 			sourceTree = "<group>";
 		};
-		DD50C7512D0828B40057AE6F /* Settings */ = {
-			isa = PBXGroup;
-			children = (
-				DD50C74F2D0828800057AE6F /* ContactSettingsViewModel.swift */,
-				DD50C7522D0828D10057AE6F /* ContactSettingsView.swift */,
-			);
-			path = Settings;
-			sourceTree = "<group>";
-		};
 		DD5334252C61667700062F9D /* InfoDisplaySettings */ = {
 			isa = PBXGroup;
 			children = (
@@ -1382,7 +1367,6 @@
 				DDC7E5142DBCE1B900EB1127 /* Snoozer */,
 				DDCF9A7E2D85FCE6004DF4DD /* Alarm */,
 				DD1A97122D429495000DDC11 /* Settings */,
-				DD2C2E522D3C36A8006413A5 /* Dexcom */,
 				DD2C2E4D2D3B8ACF006413A5 /* Nightscout */,
 				DD9ED0C62D355225000D2A63 /* Log */,
 				DDEF503D2D32753A00999A5D /* Task */,
@@ -1995,7 +1979,7 @@
 				DDC6CA432DD8CED20060EE25 /* SensorAgeCondition.swift in Sources */,
 				DD7F4C212DD66BB200D449E9 /* FastRiseAlarmEditor.swift in Sources */,
 				FC97881A2485969B00A7906C /* SceneDelegate.swift in Sources */,
-				DD83164E2DE4E093004467AA /* WatchSettingsView.swift in Sources */,
+				DD83164E2DE4E093004467AA /* CalendarSettingsView.swift in Sources */,
 				DD0C0C662C46E54C00DBADDF /* InfoDataSeparator.swift in Sources */,
 				DD58171C2D299F940041FB98 /* BluetoothDevice.swift in Sources */,
 				DD7E198A2ACDA62600DBD158 /* SensorStart.swift in Sources */,

+ 6 - 6
LoopFollow/Alarm/AlarmEditing/AlarmEditor.swift

@@ -17,13 +17,13 @@ struct AlarmEditor: View {
             innerEditor()
                 .navigationBarTitleDisplayMode(.inline)
                 .toolbar {
-                    if isNew {
-                        ToolbarItem(placement: .confirmationAction) {
-                            Button("Done") {
-                                onDone()
-                                dismiss()
-                            }
+                    ToolbarItem(placement: .confirmationAction) {
+                        Button("Done") {
+                            onDone()
+                            dismiss()
                         }
+                    }
+                    if isNew {
                         ToolbarItem(placement: .cancellationAction) {
                             Button("Cancel") {
                                 onCancel()

+ 35 - 49
LoopFollow/Alarm/AlarmListView.swift

@@ -89,57 +89,50 @@ private enum SheetInfo: Identifiable {
 
 struct AlarmListView: View {
     @ObservedObject private var store = Storage.shared.alarms
-    @Environment(\.dismiss) private var dismiss
-
     @State private var sheetInfo: SheetInfo?
     @State private var deleteAfterDismiss: UUID?
+    @State private var selectedAlarm: Alarm?
 
     var body: some View {
-        NavigationStack {
-            List {
-                ForEach(store.value) { alarm in
-                    NavigationLink {
-                        AlarmEditor(alarm: binding(for: alarm))
-                    } label: {
-                        HStack(spacing: 12) {
-                            ZStack {
-                                Image(systemName: alarm.type.icon)
+        List {
+            ForEach(store.value) { alarm in
+                Button(action: {
+                    selectedAlarm = alarm
+                    sheetInfo = .editor(id: alarm.id, isNew: false)
+                }) {
+                    HStack(spacing: 12) {
+                        ZStack {
+                            Image(systemName: alarm.type.icon)
+                                .font(.title3)
+                                .symbolRenderingMode(.hierarchical)
+                                .foregroundStyle(alarm.isEnabled ? Color.accentColor : Color.secondary)
+                                .opacity(iconOpacity(for: alarm))
+
+                            if let until = alarm.snoozedUntil, until > Date() {
+                                Image(systemName: "zzz")
                                     .font(.title3)
-                                    .symbolRenderingMode(.hierarchical)
-                                    .foregroundStyle(alarm.isEnabled ? Color.accentColor : Color.secondary)
-                                    .opacity(iconOpacity(for: alarm))
-
-                                if let until = alarm.snoozedUntil, until > Date() {
-                                    Image(systemName: "zzz")
-                                        .font(.title3)
-                                        .foregroundStyle(Color.secondary)
-                                        .shadow(color: .black.opacity(1), radius: 2, x: 0, y: 0)
-                                        .blendMode(.screen)
-                                        .offset(x: 6, y: 6)
-                                }
+                                    .foregroundStyle(Color.secondary)
+                                    .shadow(color: .black.opacity(1), radius: 2, x: 0, y: 0)
+                                    .blendMode(.screen)
+                                    .offset(x: 6, y: 6)
                             }
-                            .frame(width: 26, height: 26)
-
-                            Text(alarm.name)
-                                .frame(maxWidth: .infinity, alignment: .leading)
                         }
+                        .frame(width: 26, height: 26)
+
+                        Text(alarm.name)
+                            .frame(maxWidth: .infinity, alignment: .leading)
                     }
                 }
-                .onDelete { store.value.remove(atOffsets: $0) }
-            }
-            .navigationTitle("Alarms")
-            .toolbar {
-                ToolbarItem(placement: .navigationBarLeading) {
-                    Button("Done") { dismiss() }
-                }
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button { sheetInfo = .picker } label: { Image(systemName: "plus") }
-                }
             }
-            .sheet(item: $sheetInfo,
-                   onDismiss: handleSheetDismiss)
-            { info in
-                sheetContent(for: info)
+            .onDelete { store.value.remove(atOffsets: $0) }
+        }
+        .sheet(item: $sheetInfo, onDismiss: handleSheetDismiss) { info in
+            sheetContent(for: info)
+        }
+        .navigationBarTitle("Alarms", displayMode: .inline)
+        .toolbar {
+            ToolbarItem(placement: .primaryAction) {
+                Button { sheetInfo = .picker } label: { Image(systemName: "plus") }
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
@@ -171,7 +164,7 @@ struct AlarmListView: View {
                     isNew: isNew,
                     onDone: { sheetInfo = nil },
                     onCancel: {
-                        deleteAfterDismiss = id
+                        if isNew { deleteAfterDismiss = id }
                         sheetInfo = nil
                     }
                 )
@@ -181,13 +174,6 @@ struct AlarmListView: View {
         }
     }
 
-    private func binding(for alarm: Alarm) -> Binding<Alarm> {
-        guard let idx = store.value.firstIndex(where: { $0.id == alarm.id }) else {
-            fatalError("Alarm not found")
-        }
-        return $store.value[idx]
-    }
-
     private func iconOpacity(for alarm: Alarm) -> Double {
         if !alarm.isEnabled { return 0.35 }
         if let until = alarm.snoozedUntil, until > Date() { return 0.55 }

+ 1 - 9
LoopFollow/Alarm/AlarmSettingsView.swift

@@ -6,7 +6,6 @@ import SwiftUI
 
 struct AlarmSettingsView: View {
     @ObservedObject private var cfgStore = Storage.shared.alarmConfiguration
-    @Environment(\.presentationMode) var presentationMode
 
     /// Helper to bind an optional Date? into a non‑optional Date for DatePicker
     private func optDateBinding(_ b: Binding<Date?>) -> Binding<Date> {
@@ -187,15 +186,8 @@ struct AlarmSettingsView: View {
                     )
                 }
             }
-            .navigationTitle("Alarm Settings")
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Alarm Settings", displayMode: .inline)
     }
 }

+ 1 - 9
LoopFollow/BackgroundRefresh/BackgroundRefreshSettingsView.swift

@@ -6,7 +6,6 @@ import SwiftUI
 
 struct BackgroundRefreshSettingsView: View {
     @ObservedObject var viewModel: BackgroundRefreshSettingsViewModel
-    @Environment(\.presentationMode) var presentationMode
     @State private var forceRefresh = false
     @State private var timer: Timer?
 
@@ -22,14 +21,6 @@ struct BackgroundRefreshSettingsView: View {
                     availableDevicesSection
                 }
             }
-            .navigationBarTitle("Background Refresh Settings", displayMode: .inline)
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
             .onAppear {
                 startTimer()
             }
@@ -38,6 +29,7 @@ struct BackgroundRefreshSettingsView: View {
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Background Refresh Settings", displayMode: .inline)
     }
 
     // MARK: - Subviews / Computed Properties

+ 1 - 4
LoopFollow/InfoDisplaySettings/InfoDisplaySettingsView.swift

@@ -6,7 +6,6 @@ import SwiftUI
 
 struct InfoDisplaySettingsView: View {
     @ObservedObject var viewModel: InfoDisplaySettingsViewModel
-    @Environment(\.presentationMode) var presentationMode
 
     var body: some View {
         NavigationView {
@@ -40,13 +39,11 @@ struct InfoDisplaySettingsView: View {
                     .environment(\.editMode, .constant(.active))
                 }
             }
-            .navigationBarItems(trailing: Button("Done") {
-                presentationMode.wrappedValue.dismiss()
-            })
             .onDisappear {
                 NotificationCenter.default.post(name: NSNotification.Name("refresh"), object: nil)
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Information Display Settings", displayMode: .inline)
     }
 }

+ 1 - 9
LoopFollow/Log/LogView.swift

@@ -6,7 +6,6 @@ import SwiftUI
 
 struct LogView: View {
     @ObservedObject var viewModel = LogViewModel()
-    @Environment(\.presentationMode) var presentationMode
 
     var body: some View {
         NavigationView {
@@ -34,18 +33,11 @@ struct LogView: View {
                     .padding(.horizontal)
                 }
             }
-            .navigationBarTitle("Today's Logs", displayMode: .inline)
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
             .onAppear {
                 viewModel.loadLogEntries()
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Today's Logs", displayMode: .inline)
     }
 }

+ 1 - 9
LoopFollow/Nightscout/NightscoutSettingsView.swift

@@ -6,7 +6,6 @@ import SwiftUI
 
 struct NightscoutSettingsView: View {
     @ObservedObject var viewModel: NightscoutSettingsViewModel
-    @Environment(\.presentationMode) var presentationMode
 
     var body: some View {
         NavigationView {
@@ -15,19 +14,12 @@ struct NightscoutSettingsView: View {
                 tokenSection
                 statusSection
             }
-            .navigationBarTitle("Nightscout Settings", displayMode: .inline)
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
             .onDisappear {
                 viewModel.dismiss()
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Nightscout Settings", displayMode: .inline)
     }
 
     // MARK: - Subviews / Computed Properties

+ 1 - 9
LoopFollow/Settings/AdvancedSettingsView.swift

@@ -6,7 +6,6 @@ import SwiftUI
 
 struct AdvancedSettingsView: View {
     @ObservedObject var viewModel: AdvancedSettingsViewModel
-    @Environment(\.presentationMode) var presentationMode
 
     var body: some View {
         NavigationView {
@@ -28,15 +27,8 @@ struct AdvancedSettingsView: View {
                     Toggle("Debug Log Level", isOn: $viewModel.debugLogLevel)
                 }
             }
-            .navigationBarTitle("Advanced Settings", displayMode: .inline)
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Advanced Settings", displayMode: .inline)
     }
 }

+ 4 - 10
LoopFollow/Settings/WatchSettingsView.swift

@@ -1,11 +1,11 @@
 // LoopFollow
-// WatchSettingsView.swift
+// CalendarSettingsView.swift
 // Created by Jonas Björkert on 2025-05-26.
 
 import EventKit
 import SwiftUI
 
-struct WatchSettingsView: View {
+struct CalendarSettingsView: View {
     // MARK: Storage bindings
 
     @ObservedObject private var writeCalendarEvent = Storage.shared.writeCalendarEvent
@@ -15,14 +15,13 @@ struct WatchSettingsView: View {
 
     // MARK: Local state
 
-    @Environment(\.presentationMode) private var presentationMode
     @State private var calendars: [EKCalendar] = []
     @State private var accessDenied = false
 
     // MARK: Body
 
     var body: some View {
-        NavigationStack {
+        NavigationView {
             Form {
                 // ------------- Calendar write -------------
                 Section {
@@ -72,17 +71,12 @@ struct WatchSettingsView: View {
                     }
                 }
             }
-            .navigationTitle("Calendar")
-            .toolbar {
-                ToolbarItem(placement: .confirmationAction) {
-                    Button("Done") { presentationMode.wrappedValue.dismiss() }
-                }
-            }
             .task { // runs once on appear
                 await requestCalendarAccessAndLoad()
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Calendar", displayMode: .inline)
     }
 
     // MARK: - Helpers

+ 1 - 9
LoopFollow/Contact/Settings/ContactSettingsView.swift

@@ -7,7 +7,6 @@ import SwiftUI
 
 struct ContactSettingsView: View {
     @ObservedObject var viewModel: ContactSettingsViewModel
-    @Environment(\.presentationMode) var presentationMode
 
     @State private var showAlert: Bool = false
     @State private var alertTitle: String = ""
@@ -77,19 +76,12 @@ struct ContactSettingsView: View {
                     }
                 }
             }
-            .navigationBarTitle("Contact Settings", displayMode: .inline)
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
             .alert(isPresented: $showAlert) {
                 Alert(title: Text(alertTitle), message: Text(alertMessage), dismissButton: .default(Text("OK")))
             }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Contact", displayMode: .inline)
     }
 
     private func requestContactAccess() {

+ 1 - 1
LoopFollow/Contact/Settings/ContactSettingsViewModel.swift

@@ -1,6 +1,6 @@
 // LoopFollow
 // ContactSettingsViewModel.swift
-// Created by Jonas Björkert on 2024-12-10.
+// Created by Jonas Björkert on 2025-05-23.
 
 import Combine
 import Foundation

+ 2 - 10
LoopFollow/Dexcom/DexcomSettingsView.swift

@@ -1,12 +1,11 @@
 // LoopFollow
 // DexcomSettingsView.swift
-// Created by Jonas Björkert on 2025-01-18.
+// Created by Jonas Björkert on 2025-05-23.
 
 import SwiftUI
 
 struct DexcomSettingsView: View {
     @ObservedObject var viewModel: DexcomSettingsViewModel
-    @Environment(\.presentationMode) var presentationMode
 
     var body: some View {
         NavigationView {
@@ -27,15 +26,8 @@ struct DexcomSettingsView: View {
                     .pickerStyle(SegmentedPickerStyle())
                 }
             }
-            .navigationBarTitle("Dexcom Settings", displayMode: .inline)
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Dexcom Settings", displayMode: .inline)
     }
 }

LoopFollow/Dexcom/DexcomSettingsViewModel.swift → LoopFollow/Settings/DexcomSettingsViewModel.swift


+ 2 - 11
LoopFollow/Settings/GeneralSettingsView.swift

@@ -5,8 +5,6 @@
 import SwiftUI
 
 struct GeneralSettingsView: View {
-    @Environment(\.presentationMode) var presentationMode
-
     @ObservedObject var colorBGText = Storage.shared.colorBGText
     @ObservedObject var appBadge = Storage.shared.appBadge
     @ObservedObject var forceDarkMode = Storage.shared.forceDarkMode
@@ -29,7 +27,7 @@ struct GeneralSettingsView: View {
     @ObservedObject var speakHighBGLimit = Storage.shared.speakHighBGLimit
 
     var body: some View {
-        NavigationStack {
+        NavigationView {
             Form {
                 Section("App Settings") {
                     Toggle("Display App Badge", isOn: $appBadge.value)
@@ -103,15 +101,8 @@ struct GeneralSettingsView: View {
                     }
                 }
             }
-            .navigationTitle("General Settings")
-            .toolbar {
-                ToolbarItem(placement: .confirmationAction) {
-                    Button("Done") {
-                        presentationMode.wrappedValue.dismiss()
-                    }
-                }
-            }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("General Settings", displayMode: .inline)
     }
 }

+ 2 - 11
LoopFollow/Settings/GraphSettingsView.swift

@@ -5,9 +5,6 @@
 import SwiftUI
 
 struct GraphSettingsView: View {
-    @Environment(\.presentationMode) private var presentationMode
-
-    // ── Stored settings ──────────────────────────────────────────────────────
     @ObservedObject private var showDots = Storage.shared.showDots
     @ObservedObject private var showLines = Storage.shared.showLines
     @ObservedObject private var showValues = Storage.shared.showValues
@@ -26,11 +23,10 @@ struct GraphSettingsView: View {
     @ObservedObject private var highLine = Storage.shared.highLine
     @ObservedObject private var downloadDays = Storage.shared.downloadDays
 
-    // ─────────────────────────────────────────────────────────────────────────
     private var nightscoutEnabled: Bool { IsNightscoutEnabled() }
 
     var body: some View {
-        NavigationStack {
+        NavigationView {
             Form {
                 // ── Graph Display ────────────────────────────────────────────
                 Section("Graph Display") {
@@ -136,14 +132,9 @@ struct GraphSettingsView: View {
                     }
                 }
             }
-            .navigationTitle("Graph Settings")
-            .toolbar {
-                ToolbarItem(placement: .confirmationAction) {
-                    Button("Done") { presentationMode.wrappedValue.dismiss() }
-                }
-            }
         }
         .preferredColorScheme(Storage.shared.forceDarkMode.value ? .dark : nil)
+        .navigationBarTitle("Graph Settings", displayMode: .inline)
     }
 
     /// Marks the chart as needing a redraw

+ 28 - 24
LoopFollow/Settings/SettingsMenuView.swift

@@ -12,14 +12,15 @@ struct SettingsMenuView: View {
 
     // MARK: – Local state
 
-    @State private var sheet: Sheet?
+    @State private var path = NavigationPath()
     @State private var latestVersion: String?
     @State private var versionTint: Color = .secondary
+    @State private var navPath = NavigationPath()
 
     // MARK: – Body
 
     var body: some View {
-        NavigationStack {
+        NavigationStack(path: $path) {
             List {
                 // ───────── Data settings ─────────
                 dataSection
@@ -29,26 +30,26 @@ struct SettingsMenuView: View {
                     NavigationRow(title: "Background Refresh Settings",
                                   icon: "arrow.clockwise")
                     {
-                        sheet = .backgroundRefresh
+                        path.append(Sheet.backgroundRefresh)
                     }
 
                     NavigationRow(title: "General Settings",
                                   icon: "gearshape")
                     {
-                        sheet = .general
+                        path.append(Sheet.general)
                     }
 
                     NavigationRow(title: "Graph Settings",
                                   icon: "chart.xyaxis.line")
                     {
-                        sheet = .graph
+                        path.append(Sheet.graph)
                     }
 
                     if IsNightscoutEnabled() {
                         NavigationRow(title: "Information Display Settings",
                                       icon: "info.circle")
                         {
-                            sheet = .infoDisplay
+                            path.append(Sheet.infoDisplay)
                         }
                     }
                 }
@@ -58,13 +59,13 @@ struct SettingsMenuView: View {
                     NavigationRow(title: "Alarms",
                                   icon: "bell")
                     {
-                        sheet = .alarmsList
+                        path.append(Sheet.alarmsList)
                     }
 
                     NavigationRow(title: "Alarm Settings",
                                   icon: "bell.badge")
                     {
-                        sheet = .alarmSettings
+                        path.append(Sheet.alarmSettings)
                     }
                 }
 
@@ -73,13 +74,13 @@ struct SettingsMenuView: View {
                     NavigationRow(title: "Calendar",
                                   icon: "calendar")
                     {
-                        sheet = .calendar
+                        path.append(Sheet.calendar)
                     }
 
                     NavigationRow(title: "Contact",
                                   icon: "person.circle")
                     {
-                        sheet = .contact
+                        path.append(Sheet.contact)
                     }
                 }
 
@@ -88,7 +89,7 @@ struct SettingsMenuView: View {
                     NavigationRow(title: "Advanced Settings",
                                   icon: "exclamationmark.shield")
                     {
-                        sheet = .advanced
+                        path.append(Sheet.advanced)
                     }
                 }
 
@@ -96,14 +97,12 @@ struct SettingsMenuView: View {
                     NavigationRow(title: "View Log",
                                   icon: "doc.text.magnifyingglass")
                     {
-                        sheet = .viewLog
+                        path.append(Sheet.viewLog)
                     }
 
                     ActionRow(title: "Share Logs",
-                              icon: "square.and.arrow.up")
-                    {
-                        shareLogs()
-                    }
+                              icon: "square.and.arrow.up",
+                              action: shareLogs)
                 }
 
                 // ───────── Community ─────────
@@ -117,9 +116,9 @@ struct SettingsMenuView: View {
                 buildInfoSection
             }
             .navigationTitle("Settings")
+            .navigationDestination(for: Sheet.self) { $0.destination }
         }
         .task { await refreshVersionInfo() }
-        .sheet(item: $sheet) { $0.destination }
     }
 
     // MARK: – Section builders
@@ -140,13 +139,13 @@ struct SettingsMenuView: View {
             NavigationRow(title: "Nightscout Settings",
                           icon: "network")
             {
-                sheet = .nightscout
+                path.append(Sheet.nightscout)
             }
 
             NavigationRow(title: "Dexcom Settings",
                           icon: "sensor.tag.radiowaves.forward")
             {
-                sheet = .dexcom
+                path.append(Sheet.dexcom)
             }
         }
         .onAppear {
@@ -162,6 +161,7 @@ struct SettingsMenuView: View {
         Section("Build Information") {
             keyValue("Version", ver, tint: versionTint)
             keyValue("Latest version", latestVersion ?? "Fetching…")
+
             if !(build.isMacApp() || build.isSimulatorBuild()) {
                 keyValue(build.expirationHeaderString,
                          dateTimeUtils.formattedDate(from: build.calculateExpirationDate()))
@@ -212,9 +212,9 @@ struct SettingsMenuView: View {
     }
 }
 
-// MARK: – Sheet routing (unchanged)
+// MARK: – Sheet routing
 
-private enum Sheet: Identifiable {
+private enum Sheet: Hashable, Identifiable {
     case nightscout, dexcom
     case backgroundRefresh
     case general, graph
@@ -225,7 +225,7 @@ private enum Sheet: Identifiable {
     case advanced
     case viewLog
 
-    var id: Int { hashValue }
+    var id: Self { self }
 
     @ViewBuilder
     var destination: some View {
@@ -239,7 +239,7 @@ private enum Sheet: Identifiable {
         case .alarmsList: AlarmListView()
         case .alarmSettings: AlarmSettingsView()
         case .remote: RemoteSettingsView(viewModel: .init())
-        case .calendar: WatchSettingsView()
+        case .calendar: CalendarSettingsView()
         case .contact: ContactSettingsView(viewModel: .init())
         case .advanced: AdvancedSettingsView(viewModel: .init())
         case .viewLog: LogView(viewModel: .init())
@@ -247,6 +247,8 @@ private enum Sheet: Identifiable {
     }
 }
 
+// MARK: – UIKit helpers (unchanged)
+
 import UIKit
 
 extension UIApplication {
@@ -261,7 +263,9 @@ extension UIApplication {
 
 extension UIViewController {
     func presentSimpleAlert(title: String, message: String) {
-        let a = UIAlertController(title: title, message: message, preferredStyle: .alert)
+        let a = UIAlertController(title: title,
+                                  message: message,
+                                  preferredStyle: .alert)
         a.addAction(UIAlertAction(title: "OK", style: .default))
         present(a, animated: true)
     }