From 49cfe9f0299f1f58dcb4c861c55ea675da8b2a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B6rkert?= Date: Mon, 27 Apr 2026 10:50:01 +0200 Subject: [PATCH] Remove the Nightscout-based remote command path Trio dev's APNS-based remote command support has merged to main, so the Nightscout treatment-posting variant of remote commands is no longer needed. Drop the .nightscout case from RemoteType, the Nightscout remote view and controller, the unused NoRemoteView fallback, and all .nightscout switch arms in the remote settings, import/export, and device validation paths. Storage keys are reused by the TRC and LoopAPNS variants and remain untouched. Existing users with remoteType set to "Nightscout" automatically fall back to .none on next launch: StorageValue's JSONDecoder fails on the removed enum case and returns the default value. --- LoopFollow.xcodeproj/project.pbxproj | 20 -- .../Nightscout/TrioNightscoutRemoteView.swift | 303 ------------------ LoopFollow/Remote/NoRemoteView.swift | 18 -- LoopFollow/Remote/RemoteType.swift | 1 - LoopFollow/Remote/RemoteViewController.swift | 22 +- .../Settings/RemoteCommandSettings.swift | 6 - .../Remote/Settings/RemoteSettingsView.swift | 12 +- .../Settings/RemoteSettingsViewModel.swift | 2 +- .../TRC/TrioNightscoutRemoteController.swift | 51 --- .../ImportExport/ExportableSettings.swift | 6 - .../ViewControllers/MainViewController.swift | 3 +- 11 files changed, 4 insertions(+), 440 deletions(-) delete mode 100644 LoopFollow/Remote/Nightscout/TrioNightscoutRemoteView.swift delete mode 100644 LoopFollow/Remote/NoRemoteView.swift delete mode 100644 LoopFollow/Remote/TRC/TrioNightscoutRemoteController.swift diff --git a/LoopFollow.xcodeproj/project.pbxproj b/LoopFollow.xcodeproj/project.pbxproj index 4c2444734..868a221f2 100644 --- a/LoopFollow.xcodeproj/project.pbxproj +++ b/LoopFollow.xcodeproj/project.pbxproj @@ -87,7 +87,6 @@ DD0C0C6B2C48562000DBADDF /* InsulinMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C6A2C48562000DBADDF /* InsulinMetric.swift */; }; DD0C0C6D2C48606200DBADDF /* CarbMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C6C2C48606200DBADDF /* CarbMetric.swift */; }; DD0C0C702C4AFFE800DBADDF /* RemoteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C6F2C4AFFE800DBADDF /* RemoteViewController.swift */; }; - DD0C0C722C4B000800DBADDF /* TrioNightscoutRemoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C712C4B000800DBADDF /* TrioNightscoutRemoteView.swift */; }; DD12D4852E1705D9004E0112 /* AlarmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD12D4842E1705D9004E0112 /* AlarmViewController.swift */; }; DD12D4872E1705E6004E0112 /* AlarmsContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD12D4862E1705E6004E0112 /* AlarmsContainerView.swift */; }; DD13BC752C3FD6210062313B /* InfoType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD13BC742C3FD6200062313B /* InfoType.swift */; }; @@ -112,7 +111,6 @@ DD4878132C7B750D0048F05C /* TempTargetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878122C7B750D0048F05C /* TempTargetView.swift */; }; DD4878152C7B75230048F05C /* MealView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878142C7B75230048F05C /* MealView.swift */; }; DD4878172C7B75350048F05C /* BolusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878162C7B75350048F05C /* BolusView.swift */; }; - DD4878192C7C56D60048F05C /* TrioNightscoutRemoteController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878182C7C56D60048F05C /* TrioNightscoutRemoteController.swift */; }; DD48781E2C7DAF2F0048F05C /* PushNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD48781D2C7DAF2F0048F05C /* PushNotificationManager.swift */; }; DD4878202C7DAF890048F05C /* PushMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD48781F2C7DAF890048F05C /* PushMessage.swift */; }; DD493AD52ACF2109009A6922 /* ResumePump.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD493AD42ACF2109009A6922 /* ResumePump.swift */; }; @@ -250,7 +248,6 @@ DDDC01DD2E244B3100D9975C /* JWTManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC01DC2E244B3100D9975C /* JWTManager.swift */; }; DDDC31CC2E13A7DF009EA0F3 /* AddAlarmSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */; }; DDDC31CE2E13A811009EA0F3 /* AlarmTile.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */; }; - DDDF6F492D479AF000884336 /* NoRemoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDF6F482D479AEF00884336 /* NoRemoteView.swift */; }; DDE69ED22C7256260013EAEC /* RemoteType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE69ED12C7256260013EAEC /* RemoteType.swift */; }; DDE75D232DE5E505007C1FC1 /* Glyph.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE75D222DE5E505007C1FC1 /* Glyph.swift */; }; DDE75D272DE5E539007C1FC1 /* ActionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE75D262DE5E539007C1FC1 /* ActionRow.swift */; }; @@ -537,7 +534,6 @@ DD0C0C6A2C48562000DBADDF /* InsulinMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinMetric.swift; sourceTree = ""; }; DD0C0C6C2C48606200DBADDF /* CarbMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbMetric.swift; sourceTree = ""; }; DD0C0C6F2C4AFFE800DBADDF /* RemoteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteViewController.swift; sourceTree = ""; }; - DD0C0C712C4B000800DBADDF /* TrioNightscoutRemoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioNightscoutRemoteView.swift; sourceTree = ""; }; DD12D4842E1705D9004E0112 /* AlarmViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmViewController.swift; sourceTree = ""; }; DD12D4862E1705E6004E0112 /* AlarmsContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmsContainerView.swift; sourceTree = ""; }; DD13BC742C3FD6200062313B /* InfoType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoType.swift; sourceTree = ""; }; @@ -562,7 +558,6 @@ DD4878122C7B750D0048F05C /* TempTargetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetView.swift; sourceTree = ""; }; DD4878142C7B75230048F05C /* MealView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealView.swift; sourceTree = ""; }; DD4878162C7B75350048F05C /* BolusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusView.swift; sourceTree = ""; }; - DD4878182C7C56D60048F05C /* TrioNightscoutRemoteController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioNightscoutRemoteController.swift; sourceTree = ""; }; DD48781D2C7DAF2F0048F05C /* PushNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationManager.swift; sourceTree = ""; }; DD48781F2C7DAF890048F05C /* PushMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushMessage.swift; sourceTree = ""; }; DD493AD42ACF2109009A6922 /* ResumePump.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResumePump.swift; sourceTree = ""; }; @@ -702,7 +697,6 @@ DDDC01DC2E244B3100D9975C /* JWTManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTManager.swift; sourceTree = ""; }; DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAlarmSheet.swift; sourceTree = ""; }; DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmTile.swift; sourceTree = ""; }; - DDDF6F482D479AEF00884336 /* NoRemoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoRemoteView.swift; sourceTree = ""; }; DDE69ED12C7256260013EAEC /* RemoteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteType.swift; sourceTree = ""; }; DDE75D222DE5E505007C1FC1 /* Glyph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Glyph.swift; sourceTree = ""; }; DDE75D262DE5E539007C1FC1 /* ActionRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionRow.swift; sourceTree = ""; }; @@ -1039,8 +1033,6 @@ DD0C0C6E2C4AFFB800DBADDF /* Remote */ = { isa = PBXGroup; children = ( - DDDF6F4A2D479B6A00884336 /* Nightscout */, - DDDF6F482D479AEF00884336 /* NoRemoteView.swift */, DDEF503E2D479B8A00884336 /* LoopAPNS */, DD4878112C7B74F90048F05C /* TRC */, DD4878062C7B2E9E0048F05C /* Settings */, @@ -1094,7 +1086,6 @@ DD48780D2C7B74A40048F05C /* TrioRemoteControlViewModel.swift */, DD4878162C7B75350048F05C /* BolusView.swift */, DDD10F022C518A6500D76A8E /* TreatmentResponse.swift */, - DD4878182C7C56D60048F05C /* TrioNightscoutRemoteController.swift */, DDFD5C522CB167DA00D3FD68 /* TRCCommandType.swift */, DDBE3ABC2CB5A961006B37DC /* OverrideView.swift */, ); @@ -1335,14 +1326,6 @@ path = AddAlarm; sourceTree = ""; }; - DDDF6F4A2D479B6A00884336 /* Nightscout */ = { - isa = PBXGroup; - children = ( - DD0C0C712C4B000800DBADDF /* TrioNightscoutRemoteView.swift */, - ); - path = Nightscout; - sourceTree = ""; - }; DDEF503D2D32753A00999A5D /* Task */ = { isa = PBXGroup; children = ( @@ -2136,7 +2119,6 @@ DD7F4C072DD5042F00D449E9 /* OverrideStartAlarmEditor.swift in Sources */, DDCC3A4B2DDBB5E4006F1C10 /* BatteryCondition.swift in Sources */, DDCC3A502DDED000006F1C10 /* PumpBatteryCondition.swift in Sources */, - DDDF6F492D479AF000884336 /* NoRemoteView.swift in Sources */, 656F8C142E49F3D20008DC1D /* RemoteCommandSettings.swift in Sources */, DD12D4872E1705E6004E0112 /* AlarmsContainerView.swift in Sources */, DD83164A2DE4C504004467AA /* SettingsStepperRow.swift in Sources */, @@ -2253,7 +2235,6 @@ DDC6CA3F2DD7C6340060EE25 /* TemporaryAlarmEditor.swift in Sources */, DDF699992C5AA3060058A8D9 /* TempTargetPresetManager.swift in Sources */, DDC6CA452DD8D8E60060EE25 /* PumpChangeCondition.swift in Sources */, - DD0C0C722C4B000800DBADDF /* TrioNightscoutRemoteView.swift in Sources */, DD493ADB2ACF21A3009A6922 /* Bolus.swift in Sources */, DDF9676E2AD08C6E00C5EB95 /* SiteChange.swift in Sources */, DDCC3A542DDC5D62006F1C10 /* BatteryDropAlarmEditor.swift in Sources */, @@ -2332,7 +2313,6 @@ DD026E5B2EA2C9C300A39CB5 /* InsulinFormatter.swift in Sources */, DD5334B02D1447C500CDD6EA /* BLEManager.swift in Sources */, DD4878032C7B297E0048F05C /* StorageValue.swift in Sources */, - DD4878192C7C56D60048F05C /* TrioNightscoutRemoteController.swift in Sources */, FC1BDD2B24A22650001B652C /* Stats.swift in Sources */, DDA9ACAC2D6B317100E6F1A9 /* ContactType.swift in Sources */, DDD10F052C529DA200D76A8E /* ObservableValue.swift in Sources */, diff --git a/LoopFollow/Remote/Nightscout/TrioNightscoutRemoteView.swift b/LoopFollow/Remote/Nightscout/TrioNightscoutRemoteView.swift deleted file mode 100644 index b0e1dfe01..000000000 --- a/LoopFollow/Remote/Nightscout/TrioNightscoutRemoteView.swift +++ /dev/null @@ -1,303 +0,0 @@ -// LoopFollow -// TrioNightscoutRemoteView.swift - -import HealthKit -import SwiftUI - -struct TrioNightscoutRemoteView: View { - private let remoteController = TrioNightscoutRemoteController() - - @ObservedObject var nightscoutURL = Storage.shared.url - @ObservedObject var device = Storage.shared.device - @ObservedObject var nsWriteAuth = Storage.shared.nsWriteAuth - @ObservedObject var tempTarget = Observable.shared.tempTarget - - @State private var newHKTarget = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 0.0) - @State private var duration = HKQuantity(unit: .minute(), doubleValue: 0.0) - @State private var showAlert: Bool = false - @State private var alertType: AlertType? = nil - @State private var alertMessage: String? = nil - @State private var isLoading: Bool = false - @State private var statusMessage: String? = nil - - @State private var showPresetSheet: Bool = false - @State private var presetName = "" - @ObservedObject var presetManager = TempTargetPresetManager.shared - - @FocusState private var targetFieldIsFocused: Bool - @FocusState private var durationFieldIsFocused: Bool - - enum AlertType { - case confirmCommand - case status - case validation - case confirmCancellation - } - - var body: some View { - NavigationView { - VStack { - if nightscoutURL.value.isEmpty { - ErrorMessageView( - message: "Remote commands are currently only available for Trio. It requires you to enter your Nightscout address and a token with the careportal role in the settings." - ) - } else if device.value != "Trio" { - ErrorMessageView( - message: "Remote commands are currently only available for Trio." - ) - } else if !nsWriteAuth.value { - ErrorMessageView( - message: "Please update your token to include the 'careportal' and 'readable' roles in order to do remote commands with Trio." - ) - } else { - Form { - if let tempTargetValue = tempTarget.value { - Section(header: Text("Existing Temp Target")) { - HStack { - Text("Current Target") - Spacer() - Text(Localizer.formatQuantity(tempTargetValue)) - Text(Localizer.getPreferredUnit().localizedShortUnitString).foregroundColor(.secondary) - } - Button { - alertType = .confirmCancellation - showAlert = true - } label: { - HStack { - Text("Cancel Temp Target") - Spacer() - Image(systemName: "xmark.app") - .font(.title) - } - } - .tint(.red) - } - } - Section(header: Text("Temporary Target")) { - HStack { - Text("Target") - Spacer() - TextFieldWithToolBar( - quantity: $newHKTarget, - maxLength: 4, - unit: Localizer.getPreferredUnit(), - minValue: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 80), - maxValue: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 200), - onValidationError: { message in - handleValidationError(message) - } - ) - .focused($targetFieldIsFocused) - Text(Localizer.getPreferredUnit().localizedShortUnitString).foregroundColor(.secondary) - } - HStack { - Text("Duration") - Spacer() - TextFieldWithToolBar( - quantity: $duration, - maxLength: 4, - unit: HKUnit.minute(), - minValue: HKQuantity(unit: .minute(), doubleValue: 5), - onValidationError: { message in - handleValidationError(message) - } - ) - .focused($durationFieldIsFocused) - Text("minutes").foregroundColor(.secondary) - } - HStack { - Button { - alertType = .confirmCommand - showAlert = true - targetFieldIsFocused = false - durationFieldIsFocused = false - } label: { - Text("Enact") - } - .disabled(isButtonDisabled) - .buttonStyle(BorderlessButtonStyle()) - .font(.callout) - .controlSize(.mini) - - Spacer() - - Button { - showPresetSheet = true - targetFieldIsFocused = false - durationFieldIsFocused = false - } label: { - Text("Save as Preset") - } - .disabled(isButtonDisabled) - .buttonStyle(BorderlessButtonStyle()) - .font(.callout) - .controlSize(.mini) - } - } - - if !presetManager.presets.isEmpty { - Section(header: Text("Presets")) { - ForEach(presetManager.presets) { preset in - HStack { - Text(preset.name) - Spacer() - } - .contentShape(Rectangle()) - .onTapGesture { - alertType = .confirmCommand - newHKTarget = preset.target - duration = preset.duration - showAlert = true - targetFieldIsFocused = false - durationFieldIsFocused = false - } - .swipeActions { - Button(role: .destructive) { - if let index = presetManager.presets.firstIndex(where: { $0.id == preset.id }) { - presetManager.deletePreset(at: index) - } - targetFieldIsFocused = false - durationFieldIsFocused = false - } label: { - Label("Delete", systemImage: "trash") - } - } - } - } - } - } - - if isLoading { - ProgressView("Please wait...") - .padding() - } - } - } - .navigationTitle("Remote") - .navigationBarTitleDisplayMode(.inline) - .alert(isPresented: $showAlert) { - switch alertType { - case .confirmCommand: - return Alert( - title: Text("Confirm Command"), - message: Text("New Target: \(Localizer.formatQuantity(newHKTarget)) \(Localizer.getPreferredUnit().localizedShortUnitString)\nDuration: \(Int(duration.doubleValue(for: HKUnit.minute()))) minutes"), - primaryButton: .default(Text("Confirm"), action: { - enactTempTarget() - }), - secondaryButton: .cancel() - ) - case .status: - return Alert( - title: Text("Status"), - message: Text(statusMessage ?? ""), - dismissButton: .default(Text("OK"), action: { - showAlert = false - }) - ) - case .confirmCancellation: - return Alert( - title: Text("Confirm Cancellation"), - message: Text("Are you sure you want to cancel the existing temp target?"), - primaryButton: .default(Text("Confirm"), action: { - cancelTempTarget() - }), - secondaryButton: .cancel() - ) - case .validation: - return Alert( - title: Text("Validation Error"), - message: Text(alertMessage ?? "Invalid input."), - dismissButton: .default(Text("OK")) - ) - case .none: - return Alert(title: Text("Unknown Alert")) - } - } - .sheet(isPresented: $showPresetSheet) { - VStack { - Text("Save Preset") - .font(.headline) - .padding() - TextField("Preset Name", text: $presetName) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .padding() - HStack { - Button("Cancel") { - showPresetSheet = false - } - .padding() - Spacer() - Button("Save") { - presetManager.addPreset(name: presetName, target: newHKTarget, duration: duration) - presetName = "" - showPresetSheet = false - } - .disabled(presetName.isEmpty) - .padding() - } - Spacer() - } - .padding() - } - } - } - - private var isButtonDisabled: Bool { - return newHKTarget.doubleValue(for: Localizer.getPreferredUnit()) == 0 || - duration.doubleValue(for: HKUnit.minute()) == 0 || isLoading - } - - private func enactTempTarget() { - isLoading = true - remoteController.sendTempTarget(newTarget: newHKTarget, duration: duration) { success in - DispatchQueue.main.async { - self.isLoading = false - if success { - self.statusMessage = "Command successfully sent to Nightscout." - LogManager.shared.log( - category: .nightscout, - message: "sendTempTarget succeeded - New Target: \(Localizer.formatQuantity(newHKTarget)) \(Localizer.getPreferredUnit().localizedShortUnitString), Duration: \(Int(duration.doubleValue(for: HKUnit.minute()))) minutes" - ) - } else { - self.statusMessage = "Failed to enact target." - LogManager.shared.log( - category: .nightscout, - message: "sendTempTarget failed - New Target: \(Localizer.formatQuantity(newHKTarget)) \(Localizer.getPreferredUnit().localizedShortUnitString), Duration: \(Int(duration.doubleValue(for: HKUnit.minute()))) minutes" - ) - } - self.alertType = .status - self.showAlert = true - } - } - } - - private func cancelTempTarget() { - isLoading = true - remoteController.cancelExistingTarget { success in - DispatchQueue.main.async { - self.isLoading = false - if success { - self.statusMessage = "Cancellation request successfully sent to Nightscout." - LogManager.shared.log( - category: .nightscout, - message: "cancelExistingTarget succeeded" - ) - } else { - self.statusMessage = "Failed to cancel temp target." - LogManager.shared.log( - category: .nightscout, - message: "cancelExistingTarget failed" - ) - } - self.alertType = .status - self.showAlert = true - } - } - } - - private func handleValidationError(_ message: String) { - alertMessage = message - alertType = .validation - showAlert = true - } -} diff --git a/LoopFollow/Remote/NoRemoteView.swift b/LoopFollow/Remote/NoRemoteView.swift deleted file mode 100644 index 9daf12c51..000000000 --- a/LoopFollow/Remote/NoRemoteView.swift +++ /dev/null @@ -1,18 +0,0 @@ -// LoopFollow -// NoRemoteView.swift - -import SwiftUI - -struct NoRemoteView: View { - private let remoteController = TrioNightscoutRemoteController() - - var body: some View { - NavigationView { - VStack { - ErrorMessageView( - message: "Remote commands are currently only available for Trio and Loop." - ) - } - } - } -} diff --git a/LoopFollow/Remote/RemoteType.swift b/LoopFollow/Remote/RemoteType.swift index 1e4b958dd..4ace7c41f 100644 --- a/LoopFollow/Remote/RemoteType.swift +++ b/LoopFollow/Remote/RemoteType.swift @@ -5,7 +5,6 @@ import Foundation enum RemoteType: String, Codable { case none = "None" - case nightscout = "Nightscout" case trc = "Trio Remote Control" case loopAPNS = "Loop APNS" } diff --git a/LoopFollow/Remote/RemoteViewController.swift b/LoopFollow/Remote/RemoteViewController.swift index 56e317da3..4e02fe079 100644 --- a/LoopFollow/Remote/RemoteViewController.swift +++ b/LoopFollow/Remote/RemoteViewController.swift @@ -53,18 +53,7 @@ class RemoteViewController: UIViewController { existingHostingController.removeFromParent() } - if remoteType == .nightscout { - var remoteView: AnyView - - switch Storage.shared.device.value { - case "Trio": - remoteView = AnyView(TrioNightscoutRemoteView()) - default: - remoteView = AnyView(NoRemoteView()) - } - - hostingController = UIHostingController(rootView: remoteView) - } else if remoteType == .trc { + if remoteType == .trc { if Storage.shared.device.value != "Trio" { hostingController = UIHostingController( rootView: AnyView( @@ -96,15 +85,6 @@ class RemoteViewController: UIViewController { hostingController.didMove(toParent: self) } - - if remoteType == .nightscout, !Storage.shared.nsWriteAuth.value { - NightscoutUtils.verifyURLAndToken { _, _, nsWriteAuth, nsAdminAuth in - DispatchQueue.main.async { - Storage.shared.nsWriteAuth.value = nsWriteAuth - Storage.shared.nsAdminAuth.value = nsAdminAuth - } - } - } } override func viewWillAppear(_ animated: Bool) { diff --git a/LoopFollow/Remote/Settings/RemoteCommandSettings.swift b/LoopFollow/Remote/Settings/RemoteCommandSettings.swift index 56c5686fb..ddfe9203b 100644 --- a/LoopFollow/Remote/Settings/RemoteCommandSettings.swift +++ b/LoopFollow/Remote/Settings/RemoteCommandSettings.swift @@ -111,10 +111,6 @@ struct RemoteCommandSettings: Codable { storage.device.value = "Loop" case .trc: storage.device.value = "Trio" - case .nightscout: - // For Nightscout, we don't automatically set device type - // as it should be determined by the actual connection - break case .none: // For none, we don't change the device type break @@ -149,8 +145,6 @@ struct RemoteCommandSettings: Codable { switch remoteType { case .none: return true - case .nightscout: - return !user.isEmpty case .trc: return !user.isEmpty && !sharedSecret.isEmpty && !remoteApnsKey.isEmpty && !remoteKeyId.isEmpty case .loopAPNS: diff --git a/LoopFollow/Remote/Settings/RemoteSettingsView.swift b/LoopFollow/Remote/Settings/RemoteSettingsView.swift index c9d1878ba..d798d507f 100644 --- a/LoopFollow/Remote/Settings/RemoteSettingsView.swift +++ b/LoopFollow/Remote/Settings/RemoteSettingsView.swift @@ -51,16 +51,6 @@ struct RemoteSettingsView: View { label: "Trio Remote Control", isEnabled: viewModel.isTrioDevice ) - - remoteTypeRow( - type: .nightscout, - label: "Nightscout", - isEnabled: viewModel.isTrioDevice - ) - - Text("Nightscout should be used for Trio 0.2.x.") - .font(.footnote) - .foregroundColor(.secondary) } // MARK: - Import/Export Settings Section @@ -123,7 +113,7 @@ struct RemoteSettingsView: View { // MARK: - User Information Section - if viewModel.remoteType != .none && viewModel.remoteType != .loopAPNS { + if viewModel.remoteType == .trc { Section(header: Text("User Information")) { HStack { Text("User") diff --git a/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift b/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift index d5ea2fc4e..3a0aacac6 100644 --- a/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift +++ b/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift @@ -57,7 +57,7 @@ class RemoteSettingsViewModel: ObservableObject { } return loopFollowTeamID != targetTeamId - case .none, .nightscout: + case .none: return false } } diff --git a/LoopFollow/Remote/TRC/TrioNightscoutRemoteController.swift b/LoopFollow/Remote/TRC/TrioNightscoutRemoteController.swift deleted file mode 100644 index 594619690..000000000 --- a/LoopFollow/Remote/TRC/TrioNightscoutRemoteController.swift +++ /dev/null @@ -1,51 +0,0 @@ -// LoopFollow -// TrioNightscoutRemoteController.swift - -import Foundation -import HealthKit - -class TrioNightscoutRemoteController { - func cancelExistingTarget(completion: @escaping (Bool) -> Void) { - Task { - let tempTargetBody: [String: Any] = [ - "enteredBy": "LoopFollow", - "eventType": "Temporary Target", - "reason": "Manual", - "duration": 0, - "created_at": ISO8601DateFormatter().string(from: Date()), - ] - - do { - let response: [TreatmentCancelResponse] = try await NightscoutUtils.executePostRequest(eventType: .treatments, body: tempTargetBody) - Observable.shared.tempTarget.value = nil - NotificationCenter.default.post(name: NSNotification.Name("refresh"), object: nil) - completion(true) - } catch { - completion(false) - } - } - } - - func sendTempTarget(newTarget: HKQuantity, duration: HKQuantity, completion: @escaping (Bool) -> Void) { - let tempTargetBody: [String: Any] = [ - "enteredBy": "LoopFollow", - "eventType": "Temporary Target", - "reason": "Manual", - "targetTop": newTarget.doubleValue(for: .milligramsPerDeciliter), - "targetBottom": newTarget.doubleValue(for: .milligramsPerDeciliter), - "duration": Int(duration.doubleValue(for: .minute())), - "created_at": ISO8601DateFormatter().string(from: Date()), - ] - - Task { - do { - let response: [TreatmentResponse] = try await NightscoutUtils.executePostRequest(eventType: .treatments, body: tempTargetBody) - Observable.shared.tempTarget.value = newTarget - NotificationCenter.default.post(name: NSNotification.Name("refresh"), object: nil) - completion(true) - } catch { - completion(false) - } - } - } -} diff --git a/LoopFollow/Settings/ImportExport/ExportableSettings.swift b/LoopFollow/Settings/ImportExport/ExportableSettings.swift index 0425528c9..a311a22c3 100644 --- a/LoopFollow/Settings/ImportExport/ExportableSettings.swift +++ b/LoopFollow/Settings/ImportExport/ExportableSettings.swift @@ -211,10 +211,6 @@ struct RemoteSettingsExport: Codable { storage.device.value = "Loop" case .trc: storage.device.value = "Trio" - case .nightscout: - // For Nightscout, we don't automatically set device type - // as it should be determined by the actual connection - break case .none: break } @@ -234,8 +230,6 @@ struct RemoteSettingsExport: Codable { switch remoteType { case .none: return true - case .nightscout: - return !user.isEmpty case .trc: return !user.isEmpty && !sharedSecret.isEmpty && !remoteApnsKey.isEmpty && !remoteKeyId.isEmpty case .loopAPNS: diff --git a/LoopFollow/ViewControllers/MainViewController.swift b/LoopFollow/ViewControllers/MainViewController.swift index ddfb2f3f0..3b1ed7cd6 100644 --- a/LoopFollow/ViewControllers/MainViewController.swift +++ b/LoopFollow/ViewControllers/MainViewController.swift @@ -418,8 +418,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele // Check if current remote type is invalid for the device let shouldReset = (currentRemoteType == .loopAPNS && !isLoopDevice) || - (currentRemoteType == .trc && !isTrioDevice) || - (currentRemoteType == .nightscout && !isTrioDevice) + (currentRemoteType == .trc && !isTrioDevice) if shouldReset { Storage.shared.remoteType.value = .none