mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
184 lines
5.0 KiB
Swift
184 lines
5.0 KiB
Swift
//
|
|
// EnableExtensionViewModel.swift
|
|
// NetNewsWire-iOS
|
|
//
|
|
// Created by Stuart Breckenridge on 19/12/2022.
|
|
// Copyright © 2022 Ranchero Software. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import AuthenticationServices
|
|
import Account
|
|
import OAuthSwift
|
|
import Secrets
|
|
import RSCore
|
|
|
|
|
|
public final class EnableExtensionViewModel: NSObject, ObservableObject, OAuthSwiftURLHandlerType, ASWebAuthenticationPresentationContextProviding, Logging {
|
|
|
|
@Published public var showExtensionError: (Error?, Bool) = (nil, false)
|
|
private var extensionPointType: ExtensionPoint.Type?
|
|
private var oauth: OAuthSwift?
|
|
private var callbackURL: URL? = nil
|
|
|
|
|
|
func configure(_ extensionPointType: ExtensionPoint.Type) {
|
|
self.extensionPointType = extensionPointType
|
|
}
|
|
|
|
func enableExtension() async throws {
|
|
guard let extensionPointType = extensionPointType else { return }
|
|
if let oauth1 = extensionPointType as? OAuth1SwiftProvider.Type {
|
|
try await enableOAuth1(oauth1)
|
|
} else if let oauth2 = extensionPointType as? OAuth2SwiftProvider.Type {
|
|
try await enableOAuth2(oauth2)
|
|
} else {
|
|
try await activateExtensionPoint(extensionPointType)
|
|
}
|
|
}
|
|
|
|
private func activateExtensionPoint(_ point: ExtensionPoint.Type) async throws {
|
|
return try await withCheckedThrowingContinuation { continuation in
|
|
ExtensionPointManager.shared.activateExtensionPoint(point) { result in
|
|
switch result {
|
|
case .success(_):
|
|
continuation.resume()
|
|
return
|
|
case .failure(let failure):
|
|
continuation.resume(throwing: failure)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Enable OAuth
|
|
private func enableOAuth1(_ provider: OAuth1SwiftProvider.Type) async throws {
|
|
callbackURL = provider.callbackURL
|
|
|
|
let oauth1 = provider.oauth1Swift
|
|
self.oauth = oauth1
|
|
oauth1.authorizeURLHandler = self
|
|
|
|
return try await withCheckedThrowingContinuation { continuation in
|
|
oauth1.authorize(withCallbackURL: callbackURL!) { [weak self] result in
|
|
|
|
guard let self = self, let extensionPointType = self.extensionPointType else { return }
|
|
|
|
switch result {
|
|
case .success(let tokenSuccess):
|
|
ExtensionPointManager.shared.activateExtensionPoint(extensionPointType, tokenSuccess: tokenSuccess) { result in
|
|
switch result {
|
|
case .success(_):
|
|
continuation.resume()
|
|
return
|
|
case .failure(let failure):
|
|
continuation.resume(throwing: failure)
|
|
return
|
|
}
|
|
}
|
|
case .failure(let error):
|
|
continuation.resume(throwing: error)
|
|
return
|
|
}
|
|
|
|
self.oauth?.cancel()
|
|
self.oauth = nil
|
|
}
|
|
continuation.resume()
|
|
}
|
|
|
|
}
|
|
|
|
private func enableOAuth2(_ provider: OAuth2SwiftProvider.Type) async throws {
|
|
|
|
callbackURL = provider.callbackURL
|
|
|
|
let oauth2 = provider.oauth2Swift
|
|
self.oauth = oauth2
|
|
oauth2.authorizeURLHandler = self
|
|
|
|
let oauth2Vars = provider.oauth2Vars
|
|
|
|
return try await withCheckedThrowingContinuation { continuation in
|
|
oauth2.authorize(withCallbackURL: callbackURL!, scope: oauth2Vars.scope, state: oauth2Vars.state, parameters: oauth2Vars.params) { [weak self] result in
|
|
guard let self = self, let extensionPointType = self.extensionPointType else { return }
|
|
|
|
switch result {
|
|
case .success(let tokenSuccess):
|
|
ExtensionPointManager.shared.activateExtensionPoint(extensionPointType, tokenSuccess: tokenSuccess) { [weak self] result in
|
|
switch result {
|
|
case .success(_):
|
|
self?.logger.debug("Enabled extension successfully.")
|
|
case .failure(let failure):
|
|
continuation.resume(throwing: failure)
|
|
return
|
|
}
|
|
|
|
}
|
|
case .failure(let oauthSwiftError):
|
|
continuation.resume(throwing: oauthSwiftError)
|
|
return
|
|
}
|
|
|
|
self.oauth?.cancel()
|
|
self.oauth = nil
|
|
}
|
|
continuation.resume()
|
|
}
|
|
}
|
|
|
|
public func handle(_ url: URL) {
|
|
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: callbackURL!.scheme, completionHandler: { (url, error) in
|
|
if let callbackedURL = url {
|
|
OAuth1Swift.handle(url: callbackedURL)
|
|
}
|
|
|
|
guard let error = error else { return }
|
|
|
|
self.oauth?.cancel()
|
|
self.oauth = nil
|
|
|
|
DispatchQueue.main.async {
|
|
//self.dismiss(animated: true, completion: nil)
|
|
//self.delegate?.dismiss()
|
|
}
|
|
|
|
if case ASWebAuthenticationSessionError.canceledLogin = error {
|
|
self.logger.debug("Login cancelled.")
|
|
} else {
|
|
self.showExtensionError = (error, true)
|
|
}
|
|
})
|
|
|
|
session.presentationContextProvider = self
|
|
if !session.start() {
|
|
logger.debug("Session failed to start!!!")
|
|
}
|
|
}
|
|
|
|
|
|
public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
|
|
return rootViewController!.view.window!
|
|
}
|
|
|
|
public var rootViewController: UIViewController? {
|
|
var currentKeyWindow: UIWindow? {
|
|
UIApplication.shared.connectedScenes
|
|
.filter { $0.activationState == .foregroundActive }
|
|
.map { $0 as? UIWindowScene }
|
|
.compactMap { $0 }
|
|
.first?.windows
|
|
.filter { $0.isKeyWindow }
|
|
.first
|
|
}
|
|
|
|
var rootViewController: UIViewController? {
|
|
currentKeyWindow?.rootViewController
|
|
}
|
|
|
|
return rootViewController
|
|
}
|
|
|
|
}
|