// // LoginViewController.swift // Reader // // Created by Shadowfacts on 11/25/21. // import UIKit import AuthenticationServices import Fervor protocol LoginViewControllerDelegate: AnyObject { func didLogin(with controller: FervorController) } class LoginViewController: UIViewController { weak var delegate: LoginViewControllerDelegate? private var textField: UITextField! private var authSession: ASWebAuthenticationSession? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground textField = UITextField() textField.translatesAutoresizingMaskIntoConstraints = false textField.borderStyle = .roundedRect textField.backgroundColor = .secondarySystemBackground textField.keyboardType = .URL textField.returnKeyType = .next textField.autocorrectionType = .no textField.autocapitalizationType = .none textField.placeholder = "example.com" textField.addTarget(self, action: #selector(doEnteredURL), for: .primaryActionTriggered) view.addSubview(textField) NSLayoutConstraint.activate([ textField.centerYAnchor.constraint(equalTo: view.centerYAnchor), textField.centerXAnchor.constraint(equalTo: view.centerXAnchor), textField.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.75), ]) } @objc private func doEnteredURL() { Task { await enteredURL() } } @MainActor private func enteredURL() async { guard let text = textField.text, let components = URLComponents(string: text) else { let alert = UIAlertController(title: "Invalid URL", message: nil, preferredStyle: .alert) self.present(alert, animated: true) return } 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) present(alert, animated: true) return } var authorizeComponents = components authorizeComponents.path = "/oauth/authorize" authorizeComponents.queryItems = [ URLQueryItem(name: "response_type", value: "code"), URLQueryItem(name: "client_id", value: registration.clientID), URLQueryItem(name: "redirect_uri", value: FervorController.oauthRedirectURI.absoluteString), ] authSession = ASWebAuthenticationSession(url: authorizeComponents.url!, callbackURLScheme: "frenzy") { (callbackURL, error) in let components = URLComponents(url: callbackURL!, resolvingAgainstBaseURL: false) guard let codeItem = components?.queryItems?.first(where: { $0.name == "code" }), let codeValue = codeItem.value else { fatalError() } Task { try! await controller.getToken(authCode: codeValue) DispatchQueue.main.async { self.delegate?.didLogin(with: controller) } } } self.authSession!.presentationContextProvider = self self.authSession!.start() } } extension LoginViewController: ASWebAuthenticationPresentationContextProviding { func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { return self.view.window! } }