From a0e2ad37d1320df438b2d6a4d80e6e7b47578090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B6rkert?= Date: Mon, 12 Oct 2026 14:42:38 +0200 Subject: [PATCH] Show Loop APNS environment as info instead of a toggle The environment is read from the isAPNSProduction value that Loop uploads to the Nightscout profile, so the manual Production toggle is removed from the Loop APNS settings. The current environment is shown under Debug / Info, the same as for Trio. --- LoopFollow/Remote/LoopAPNS/LoopAPNSService.swift | 12 +----------- LoopFollow/Remote/Settings/RemoteSettingsView.swift | 12 +----------- .../Remote/Settings/RemoteSettingsViewModel.swift | 9 --------- 3 files changed, 2 insertions(+), 31 deletions(-) diff --git a/LoopFollow/Remote/LoopAPNS/LoopAPNSService.swift b/LoopFollow/Remote/LoopAPNS/LoopAPNSService.swift index 38dc4fb23..b91901bd9 100644 --- a/LoopFollow/Remote/LoopAPNS/LoopAPNSService.swift +++ b/LoopFollow/Remote/LoopAPNS/LoopAPNSService.swift @@ -305,15 +305,6 @@ class LoopAPNSService { return regex?.firstMatch(in: text, options: [], range: range) != nil } - /// Provides simple environment guidance for APNS configuration - /// - Returns: String with simple guidance to try opposite setting - private func getEnvironmentGuidance() -> String { - let currentSetting = storage.productionEnvironment.value ? "ON" : "OFF" - let trySetting = storage.productionEnvironment.value ? "OFF" : "ON" - - return "Try changing Production Environment from \(currentSetting) to \(trySetting) in your Loop APNS settings." - } - /// Sends an APNS notification /// - Parameters: /// - deviceToken: The device token to send to @@ -424,8 +415,7 @@ class LoopAPNSService { LogManager.shared.log(category: .apns, message: "APNS notification sent successfully") completion(true, nil) case 400: - let environmentGuidance = self.getEnvironmentGuidance() - let errorMessage = "Bad request. The request was invalid or malformed. \(responseBodyMessage)\n\n\(environmentGuidance)" + let errorMessage = "Bad request. The request was invalid or malformed. \(responseBodyMessage)" LogManager.shared.log(category: .apns, message: "APNS error 400: \(responseBodyMessage) - Check device token and environment settings") completion(false, errorMessage) case 403: diff --git a/LoopFollow/Remote/Settings/RemoteSettingsView.swift b/LoopFollow/Remote/Settings/RemoteSettingsView.swift index 6e9b2acaa..c4f8a5c92 100644 --- a/LoopFollow/Remote/Settings/RemoteSettingsView.swift +++ b/LoopFollow/Remote/Settings/RemoteSettingsView.swift @@ -235,17 +235,6 @@ struct RemoteSettingsView: View { .buttonStyle(.borderedProminent) .frame(maxWidth: .infinity) .padding(.vertical, 10) - - HStack { - Text("Environment") - Spacer() - Toggle("Production", isOn: $viewModel.productionEnvironment) - .toggleStyle(SwitchToggleStyle()) - } - - Text("Production is used for browser builders and should be switched off for Xcode builders") - .font(.caption) - .foregroundColor(.secondary) } if let errorMessage = viewModel.loopAPNSErrorMessage, !errorMessage.isEmpty { @@ -258,6 +247,7 @@ struct RemoteSettingsView: View { Section(header: Text("Debug / Info")) { Text("Device Token: \(Storage.shared.deviceToken.value)") + Text("APNS Environment: \(Storage.shared.productionEnvironment.value ? "Production" : "Development")") Text("Bundle ID: \(Storage.shared.bundleId.value)") if let otpCode = TOTPGenerator.extractOTPFromURL(Storage.shared.loopAPNSQrCodeURL.value) { diff --git a/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift b/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift index 2b3ab9af0..04c1a8ce7 100644 --- a/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift +++ b/LoopFollow/Remote/Settings/RemoteSettingsViewModel.swift @@ -25,7 +25,6 @@ class RemoteSettingsViewModel: ObservableObject { @Published var loopDeveloperTeamId: String @Published var loopAPNSQrCodeURL: String - @Published var productionEnvironment: Bool @Published var isShowingLoopAPNSScanner: Bool = false @Published var loopAPNSErrorMessage: String? @@ -103,8 +102,6 @@ class RemoteSettingsViewModel: ObservableObject { loopDeveloperTeamId = storage.teamId.value ?? "" loopAPNSQrCodeURL = storage.loopAPNSQrCodeURL.value - productionEnvironment = storage.productionEnvironment.value - setupBindings() } @@ -188,11 +185,6 @@ class RemoteSettingsViewModel: ObservableObject { .dropFirst() .sink { [weak self] in self?.storage.loopAPNSQrCodeURL.value = $0 } .store(in: &cancellables) - - $productionEnvironment - .dropFirst() - .sink { [weak self] in self?.storage.productionEnvironment.value = $0 } - .store(in: &cancellables) } func handleLoopAPNSQRCodeScanResult(_ result: Result) { @@ -233,7 +225,6 @@ class RemoteSettingsViewModel: ObservableObject { mealWithFatProtein = storage.mealWithFatProtein.value loopDeveloperTeamId = storage.teamId.value ?? "" loopAPNSQrCodeURL = storage.loopAPNSQrCodeURL.value - productionEnvironment = storage.productionEnvironment.value // Update device-related properties isTrioDevice = (storage.device.value == "Trio")