Fix authentication activity indicators when the authentication server is being slow

* Fetch the OIDC login URL as part of the Server Confirmation screen.

The loading indicator would show and hide while configuring and then immediately show again while fetching the URL.

* Allow the OIDCAuthenticationPresenter to show its own errors.

We no longer need to present errors in the authentication flow coordinator.
This commit is contained in:
Doug
2025-04-10 16:47:11 +01:00
committed by Doug
parent 1557054753
commit 511c4d7bf7
22 changed files with 223 additions and 113 deletions
@@ -144,12 +144,10 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
guard let self else { return }
switch action {
case .continue(let window):
if authenticationService.homeserver.value.loginMode.supportsOIDCFlow, let window {
showOIDCAuthentication(presentationAnchor: window)
} else {
showLoginScreen()
}
case .continueWithOIDC(let oidcData, let window):
showOIDCAuthentication(oidcData: oidcData, presentationAnchor: window)
case .continueWithPassword:
showLoginScreen()
case .changeServer:
showServerSelectionScreen(authenticationFlow: authenticationFlow)
}
@@ -185,29 +183,21 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
navigationStackCoordinator.setSheetCoordinator(navigationCoordinator)
}
private func showOIDCAuthentication(presentationAnchor: UIWindow) {
startLoading()
private func showOIDCAuthentication(oidcData: OIDCAuthorizationDataProxy, presentationAnchor: UIWindow) {
let presenter = OIDCAuthenticationPresenter(authenticationService: authenticationService,
oidcRedirectURL: appSettings.oidcRedirectURL,
presentationAnchor: presentationAnchor,
userIndicatorController: userIndicatorController)
oidcPresenter = presenter
Task {
switch await authenticationService.urlForOIDCLogin() {
case .failure(let error):
stopLoading()
handleError(error)
case .success(let oidcData):
stopLoading()
let presenter = OIDCAuthenticationPresenter(authenticationService: authenticationService,
oidcRedirectURL: appSettings.oidcRedirectURL,
presentationAnchor: presentationAnchor)
self.oidcPresenter = presenter
switch await presenter.authenticate(using: oidcData) {
case .success(let userSession):
userHasSignedIn(userSession: userSession)
case .failure(let error):
handleError(error)
}
oidcPresenter = nil
switch await presenter.authenticate(using: oidcData) {
case .success(let userSession):
userHasSignedIn(userSession: userSession)
case .failure:
break // Nothing to do, the alerts are handled by the presenter.
}
oidcPresenter = nil
}
}
@@ -238,35 +228,4 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
private func userHasSignedIn(userSession: UserSessionProtocol) {
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
}
private static let loadingIndicatorIdentifier = "\(AuthenticationFlowCoordinator.self)-Loading"
private func startLoading() {
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonLoading,
persistent: true))
}
private func stopLoading() {
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
/// Processes an error to either update the flow or display it to the user.
private func handleError(_ error: AuthenticationServiceError) {
MXLog.warning("Error occurred: \(error)")
switch error {
case .oidcError(.notSupported):
// Temporary alert hijacking the use of .notSupported, can be removed when OIDC support is in the SDK.
userIndicatorController.alertInfo = AlertInfo(id: UUID(),
title: L10n.commonError,
message: L10n.commonServerNotSupported)
case .oidcError(.userCancellation):
// No need to show an error, the user cancelled authentication.
break
default:
userIndicatorController.alertInfo = AlertInfo(id: UUID())
}
}
}