From 4c4044c3825e78f5076c89ba8e0163db23e0d0dc Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Wed, 12 Jan 2022 13:30:49 -0500 Subject: [PATCH] Better login error handling --- .../Screens/Login/LoginViewController.swift | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/Reader/Screens/Login/LoginViewController.swift b/Reader/Screens/Login/LoginViewController.swift index 0d612a9..211c81b 100644 --- a/Reader/Screens/Login/LoginViewController.swift +++ b/Reader/Screens/Login/LoginViewController.swift @@ -9,6 +9,7 @@ import UIKit import AuthenticationServices import Fervor +@MainActor protocol LoginViewControllerDelegate: AnyObject { func didLogin(with controller: FervorController) } @@ -18,6 +19,7 @@ class LoginViewController: UIViewController { weak var delegate: LoginViewControllerDelegate? private var textField: UITextField! + private var activityIndicator: UIActivityIndicatorView! private var authSession: ASWebAuthenticationSession? @@ -37,10 +39,18 @@ class LoginViewController: UIViewController { textField.placeholder = "example.com" textField.addTarget(self, action: #selector(doEnteredURL), for: .primaryActionTriggered) view.addSubview(textField) + + activityIndicator = UIActivityIndicatorView(style: .medium) + activityIndicator.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(activityIndicator) + NSLayoutConstraint.activate([ textField.centerYAnchor.constraint(equalTo: view.centerYAnchor), textField.centerXAnchor.constraint(equalTo: view.centerXAnchor), textField.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.75), + + activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor), + activityIndicator.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 8), ]) } @@ -59,14 +69,22 @@ class LoginViewController: UIViewController { return } + textField.isEnabled = false + activityIndicator.startAnimating() + let controller = FervorController(instanceURL: components.url!) let registration: ClientRegistration do { registration = try await controller.register() } catch { - let alert = UIAlertController(title: "Unable to Register Client", message: error.localizedDescription, preferredStyle: .alert) + let alert = UIAlertController(title: "Unable to register client", message: error.localizedDescription, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil)) present(alert, animated: true) + + textField.isEnabled = true + activityIndicator.stopAnimating() + return } @@ -81,13 +99,29 @@ class LoginViewController: UIViewController { let components = URLComponents(url: callbackURL!, resolvingAgainstBaseURL: false) guard let codeItem = components?.queryItems?.first(where: { $0.name == "code" }), let codeValue = codeItem.value else { - fatalError() + DispatchQueue.main.async { + let alert = UIAlertController(title: "Unable to retrieve authorization code", message: error?.localizedDescription ?? "Unknown Error", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil)) + self.present(alert, animated: true) + + self.textField.isEnabled = true + self.activityIndicator.stopAnimating() + } + return } - Task { - try! await controller.getToken(authCode: codeValue) - DispatchQueue.main.async { - self.delegate?.didLogin(with: controller) + Task { @MainActor in + do { + try await controller.getToken(authCode: codeValue) + } catch { + let alert = UIAlertController(title: "Unable to retrieve access token", message: error.localizedDescription, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil)) + self.present(alert, animated: true) + + self.textField.isEnabled = true + self.activityIndicator.stopAnimating() + return } + self.delegate?.didLogin(with: controller) } }