Skip to content

Commit

Permalink
feat: create window manager
Browse files Browse the repository at this point in the history
  • Loading branch information
FranAlarza committed Dec 23, 2024
1 parent f517237 commit bbd93d1
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 94 deletions.
4 changes: 2 additions & 2 deletions AppliverySDK/Applivery/AppliverySDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ public class AppliverySDK: NSObject {

When implementing SAML-based authentication, your app may receive a redirect URL
after the user completes their authentication on an external SAML identity provider.
By calling this method, you pass that redirect URL to `AppliveryWebViewManager` to
By calling this method, you pass that redirect URL to `AppliverySafariManager` to
proceed with the final steps of the authentication flow.

- Parameter url: The redirect `URL` returned by the SAML provider.
Expand All @@ -393,7 +393,7 @@ public class AppliverySDK: NSObject {
*/

@objc public func handleRedirectURL(url: URL) {
let webview = AppliveryWebViewManager.shared
let webview = AppliverySafariManager.shared
webview.urlReceived(url: url)
}

Expand Down
12 changes: 6 additions & 6 deletions AppliverySDK/Interactors/StartInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protocol StartInteractorOutput {
func credentialError(message: String)
}

class StartInteractor {
final class StartInteractor {

private let app: AppProtocol
private let configService: ConfigServiceProtocol
Expand All @@ -26,7 +26,7 @@ class StartInteractor {
private let sessionPersister: SessionPersister
private let keychain: KeychainAccessible
private let updateService: UpdateServiceProtocol
private let webViewManager: AppliveryWebViewManagerProtocol
private let safariManager: AppliverySafariManagerProtocol
private let loginService: LoginServiceProtocol
private var cancellables = Set<AnyCancellable>()

Expand All @@ -40,7 +40,7 @@ class StartInteractor {
sessionPersister: SessionPersister = SessionPersister(userDefaults: UserDefaults.standard),
keychain: KeychainAccessible = Keychain(),
updateService: UpdateServiceProtocol = UpdateService(),
webViewManager: AppliveryWebViewManagerProtocol = AppliveryWebViewManager.shared,
webViewManager: AppliverySafariManagerProtocol = AppliverySafariManager.shared,
loginService: LoginServiceProtocol = LoginService()
) {
self.app = app
Expand All @@ -50,7 +50,7 @@ class StartInteractor {
self.sessionPersister = sessionPersister
self.keychain = keychain
self.updateService = updateService
self.webViewManager = webViewManager
self.safariManager = webViewManager
self.loginService = loginService
}

Expand Down Expand Up @@ -102,7 +102,7 @@ class StartInteractor {
private extension StartInteractor {

func setupBindings() {
webViewManager.tokenPublisher.sink { token in
safariManager.tokenPublisher.sink { token in
guard let token else { return }
do {
try self.keychain.store(token, for: self.app.bundleId())
Expand All @@ -128,7 +128,7 @@ private extension StartInteractor {
let redirectURL = try await loginService.getRedirectURL()
await MainActor.run {
if let url = redirectURL {
webViewManager.showWebView(url: url)
safariManager.openSafari(from: url)
}
}
} catch {
Expand Down
82 changes: 82 additions & 0 deletions AppliverySDK/Managers/AppliverySafariManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// WebViewManager.swift
// Applivery
//
// Created by Fran Alarza on 29/11/24.
//


import SafariServices
import Combine

protocol AppliverySafariManagerProtocol {
func openSafari(from url: URL)
var tokenPublisher: AnyPublisher<String?, Never> { get }
}

final class AppliverySafariManager: NSObject, AppliverySafariManagerProtocol {

static let shared = AppliverySafariManager()

private let windowPresenter: WindowPresentable

private var safariViewController: SFSafariViewController?

private let tokenSubject = CurrentValueSubject<String?, Never>(nil)
var tokenPublisher: AnyPublisher<String?, Never> {
tokenSubject.eraseToAnyPublisher()
}

// MARK: - Init
init(
windowPresenter: WindowPresentable = WindowManager()
) {
self.windowPresenter = windowPresenter
super.init()
}

// MARK: - Public Methods
func openSafari(from url: URL) {
let safariVC = SFSafariViewController(url: url)
safariVC.delegate = self
windowPresenter.present(viewController: safariVC)
safariViewController = safariVC
}

func urlReceived(url: URL) {
guard let token = getTokenFromURL(url: url) else { return }

removeWindow()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
self?.tokenSubject.send(token)
}
}

// MARK: - Private Helpers

private func getTokenFromURL(url: URL) -> String? {
guard
let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let bearer = components.queryItems?.first(where: { $0.name == "bearer" })?.value
else {
return nil
}
return bearer
}

private func removeWindow() {
if let safariVC = safariViewController {
windowPresenter.dismiss(viewController: safariVC)
}
safariViewController = nil
windowPresenter.hide()
}
}

// MARK: - SafariViewControllerDelegate
extension AppliverySafariManager: SFSafariViewControllerDelegate {
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
tokenSubject.send(nil)
removeWindow()
}
}
82 changes: 0 additions & 82 deletions AppliverySDK/Managers/AppliveryWebViewManager.swift

This file was deleted.

42 changes: 42 additions & 0 deletions AppliverySDK/Managers/WindowManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// WindowManager.swift
// Applivery
//
// Created by Fran Alarza on 23/12/24.
//

import UIKit


protocol WindowPresentable: AnyObject {
func present(viewController: UIViewController)
func dismiss(viewController: UIViewController)
func hide()
}

final class WindowManager: WindowPresentable {

private var window: UIWindow?

init() {}

func present(viewController: UIViewController) {
let hostingViewController = UIViewController()
let newWindow = UIWindow(frame: UIScreen.main.bounds)
newWindow.rootViewController = hostingViewController
newWindow.windowLevel = UIWindow.Level(rawValue: CGFloat.greatestFiniteMagnitude)
newWindow.makeKeyAndVisible()

hostingViewController.present(viewController, animated: true)
self.window = newWindow
}

func dismiss(viewController: UIViewController) {
viewController.dismiss(animated: true)
}

func hide() {
window?.isHidden = true
window = nil
}
}
8 changes: 4 additions & 4 deletions AppliverySDK/Services/LoginService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class LoginService: LoginServiceProtocol {
let downloadService: DownloadServiceProtocol
let globalConfig: GlobalConfig
let sessionPersister: SessionPersister
let webViewManager: AppliveryWebViewManagerProtocol
let safariManager: AppliverySafariManagerProtocol
let app: AppProtocol
let keychain: KeychainAccessible

Expand All @@ -35,7 +35,7 @@ final class LoginService: LoginServiceProtocol {
downloadService: DownloadServiceProtocol = DownloadService(),
globalConfig: GlobalConfig = GlobalConfig.shared,
sessionPersister: SessionPersister = SessionPersister(userDefaults: UserDefaults.standard),
webViewManager: AppliveryWebViewManagerProtocol = AppliveryWebViewManager.shared,
webViewManager: AppliverySafariManagerProtocol = AppliverySafariManager.shared,
app: AppProtocol = App(),
keychain: KeychainAccessible = Keychain()
) {
Expand All @@ -44,7 +44,7 @@ final class LoginService: LoginServiceProtocol {
self.configService = configService
self.globalConfig = globalConfig
self.sessionPersister = sessionPersister
self.webViewManager = webViewManager
self.safariManager = webViewManager
self.app = app
self.keychain = keychain
}
Expand Down Expand Up @@ -88,7 +88,7 @@ final class LoginService: LoginServiceProtocol {
logInfo("Opening auth web view...")
let redirectURL = try await loginRepository.getRedirctURL()
if let url = redirectURL {
webViewManager.showWebView(url: url)
safariManager.openSafari(from: url)
}
} catch {
log("Error obtaining redirect URL: \(error.localizedDescription)")
Expand Down

0 comments on commit bbd93d1

Please sign in to comment.