From 2571bd7a4f668bb0171d1b74dc768bed4cb69f74 Mon Sep 17 00:00:00 2001 From: Ancil Maxwell Hoffman Date: Tue, 29 Sep 2026 08:05:28 +0200 Subject: [PATCH 1/2] Ask to sign in when the Apple data source returns 401 Refreshing with the Apple data source while signed out showed the raw "NetworkError.non200StatusCode(statusCode: 401...)" error. Show an alert explaining that this source needs an Apple Developer sign-in, with a Login button, instead. Co-Authored-By: Claude Opus 5.5 --- Xcodes/Backend/AppState+Update.swift | 8 ++++++-- Xcodes/Frontend/Common/XcodesAlert.swift | 2 ++ Xcodes/Frontend/MainWindow.swift | 14 ++++++++++++++ Xcodes/Resources/Localizable.xcstrings | 20 ++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Xcodes/Backend/AppState+Update.swift b/Xcodes/Backend/AppState+Update.swift index cd2952c9..c5588690 100644 --- a/Xcodes/Backend/AppState+Update.swift +++ b/Xcodes/Backend/AppState+Update.swift @@ -58,8 +58,12 @@ extension AppState { Current.defaults.setDate(Current.date(), forKey: "lastUpdated") } catch is CancellationError { } catch { - // Prevent setting the app state error if it is an invalid session, we will present the sign in view instead - if error as? AuthenticationError != .invalidSession { + if self.dataSource == .apple, Self.isUnauthorizedInstallError(error) || error as? AuthenticationError == .invalidSession { + // The Apple data source needs a developer session; ask the user to sign in rather than + // showing a raw 401. + self.presentedAlert = .unauthenticatedDataSource + } else if error as? AuthenticationError != .invalidSession { + // Prevent setting the app state error if it is an invalid session, we will present the sign in view instead self.error = error self.presentedAlert = .generic(title: localizeString("Alert.Update.Error.Title"), message: error.legibleLocalizedDescription) } diff --git a/Xcodes/Frontend/Common/XcodesAlert.swift b/Xcodes/Frontend/Common/XcodesAlert.swift index 710668f9..4a98c665 100644 --- a/Xcodes/Frontend/Common/XcodesAlert.swift +++ b/Xcodes/Frontend/Common/XcodesAlert.swift @@ -8,6 +8,7 @@ enum XcodesAlert: Identifiable { case generic(title: String, message: String) case checkMinSupportedVersion(xcode: AvailableXcode, macOS: String) case unauthenticated + case unauthenticatedDataSource var id: Int { switch self { @@ -17,6 +18,7 @@ enum XcodesAlert: Identifiable { case .checkMinSupportedVersion: return 4 case .cancelRuntimeInstall: return 5 case .unauthenticated: return 6 + case .unauthenticatedDataSource: return 7 } } } diff --git a/Xcodes/Frontend/MainWindow.swift b/Xcodes/Frontend/MainWindow.swift index b108f053..ece8fe81 100644 --- a/Xcodes/Frontend/MainWindow.swift +++ b/Xcodes/Frontend/MainWindow.swift @@ -204,6 +204,20 @@ struct MainWindow: View { Text("Cancel") ) ) + case .unauthenticatedDataSource: + return Alert( + title: Text("Alert.Update.AuthError.Title"), + message: Text("Alert.Update.AuthError.Message"), + primaryButton: .default( + Text("Login"), + action: { + appState.presentedSheet = .signIn + } + ), + secondaryButton: .cancel( + Text("Cancel") + ) + ) case let .checkMinSupportedVersion(xcode, deviceVersion): return Alert( title: Text("Alert.MinSupported.Title"), diff --git a/Xcodes/Resources/Localizable.xcstrings b/Xcodes/Resources/Localizable.xcstrings index 6608a149..2ce39dd5 100644 --- a/Xcodes/Resources/Localizable.xcstrings +++ b/Xcodes/Resources/Localizable.xcstrings @@ -4414,6 +4414,26 @@ } } }, + "Alert.Update.AuthError.Title" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sign in to refresh from Apple" + } + } + } + }, + "Alert.Update.AuthError.Message" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The Apple data source lists Xcode releases from your Apple Developer account, so it needs you to be signed in. Sign in to refresh the list, or switch the data source to Xcode Releases in Settings." + } + } + } + }, "Alert.Update.Error.Title" : { "comment" : "Update", "extractionState" : "manual", From 5317465f332980bb27de8fb69e30690e4c6eb8a6 Mon Sep 17 00:00:00 2001 From: Ancil Maxwell Hoffman Date: Tue, 29 Sep 2026 17:05:07 +0200 Subject: [PATCH 2/2] Order the new sign-in strings like Xcode does Xcode keeps string catalog keys sorted case-insensitively and rewrote the file on build because the two new keys were out of order. Co-Authored-By: Claude Opus 5.5 --- Xcodes/Resources/Localizable.xcstrings | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Xcodes/Resources/Localizable.xcstrings b/Xcodes/Resources/Localizable.xcstrings index 2ce39dd5..fd4cbda1 100644 --- a/Xcodes/Resources/Localizable.xcstrings +++ b/Xcodes/Resources/Localizable.xcstrings @@ -4414,22 +4414,22 @@ } } }, - "Alert.Update.AuthError.Title" : { + "Alert.Update.AuthError.Message" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "Sign in to refresh from Apple" + "value" : "The Apple data source lists Xcode releases from your Apple Developer account, so it needs you to be signed in. Sign in to refresh the list, or switch the data source to Xcode Releases in Settings." } } } }, - "Alert.Update.AuthError.Message" : { + "Alert.Update.AuthError.Title" : { "localizations" : { "en" : { "stringUnit" : { "state" : "translated", - "value" : "The Apple data source lists Xcode releases from your Apple Developer account, so it needs you to be signed in. Sign in to refresh the list, or switch the data source to Xcode Releases in Settings." + "value" : "Sign in to refresh from Apple" } } }