105 lines
3.6 KiB
Swift
105 lines
3.6 KiB
Swift
|
//
|
||
|
// 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!
|
||
|
}
|
||
|
}
|