diff --git a/flutter_web_auth_2/CHANGELOG.md b/flutter_web_auth_2/CHANGELOG.md index 2abcf4be..2d3b40e0 100644 --- a/flutter_web_auth_2/CHANGELOG.md +++ b/flutter_web_auth_2/CHANGELOG.md @@ -1,3 +1,14 @@ +## 6.0.0-alpha.0 + +- 💥 Bump Flutter and Dart SDK constraints to `3.44.0` and `3.12.0` betas, respectively +- 💥 Regenerate entire project skeleton (also migrates to built-in Kotlin) +- 💥 Rename `cleanUpDanglingCalls` -> `clearAllDanglingCalls` (unification) +- 🍎 Migrate iOS plugin to UIScene lifecycle (fixes [#192](https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/192)) + +## 5.0.2 + +- 🐛 Fix possible NPE on Android (Thanks to [@henry11996](https://github.com/henry11996) in [#196](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/196)) +- 🌹 Dummy implementation for `cleanUpDanglingCalls` on web to prevent unneeded crashes ## 5.0.1 - 🐛 Fix crash on Android and implement proper feedback if no browser is installed (Thanks to [@Mino5531](https://github.com/Mino5531) in [#190](https://github.com/ThexXTURBOXx/flutter_web_auth_2/pull/190)) diff --git a/flutter_web_auth_2/ios/flutter_web_auth_2/Sources/flutter_web_auth_2/FlutterWebAuth2Plugin.swift b/flutter_web_auth_2/ios/flutter_web_auth_2/Sources/flutter_web_auth_2/FlutterWebAuth2Plugin.swift index d30d4218..3712e910 100644 --- a/flutter_web_auth_2/ios/flutter_web_auth_2/Sources/flutter_web_auth_2/FlutterWebAuth2Plugin.swift +++ b/flutter_web_auth_2/ios/flutter_web_auth_2/Sources/flutter_web_auth_2/FlutterWebAuth2Plugin.swift @@ -3,16 +3,23 @@ import Flutter import SafariServices import UIKit -public class FlutterWebAuth2Plugin: NSObject, FlutterPlugin { +public class FlutterWebAuth2Plugin: NSObject, FlutterPlugin, FlutterSceneLifeCycleDelegate { public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "flutter_web_auth_2", binaryMessenger: registrar.messenger()) - let instance = FlutterWebAuth2Plugin() + let instance = FlutterWebAuth2Plugin(registrar: registrar) registrar.addMethodCallDelegate(instance, channel: channel) registrar.addApplicationDelegate(instance) + registrar.addSceneDelegate(instance) } + private weak var registrar: FlutterPluginRegistrar? var completionHandler: ((URL?, Error?) -> Void)? + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + super.init() + } + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { if call.method == "authenticate", let arguments = call.arguments as? [String: AnyObject], @@ -105,19 +112,8 @@ public class FlutterWebAuth2Plugin: NSObject, FlutterPlugin { let session = _session! if #available(iOS 13, *) { - var rootViewController: UIViewController? = nil - - // FlutterViewController - if (rootViewController == nil) { - rootViewController = UIApplication.shared.delegate?.window??.rootViewController as? FlutterViewController - } + var rootViewController = acquireRootViewController() - // UIViewController - if (rootViewController == nil) { - rootViewController = UIApplication.shared.keyWindow?.rootViewController - } - - // ACQUIRE_ROOT_VIEW_CONTROLLER_FAILED if (rootViewController == nil) { result(FlutterError.acquireRootViewControllerFailed) return @@ -162,15 +158,43 @@ public class FlutterWebAuth2Plugin: NSObject, FlutterPlugin { continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]) -> Void) -> Bool { - switch userActivity.activityType { - case NSUserActivityTypeBrowsingWeb: - guard let url = userActivity.webpageURL, let completionHandler = completionHandler else { - return false - } - completionHandler(url, nil) - return true - default: return false + return handleUserActivity(userActivity) + } + + @available(iOS 13.0, *) + public func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + handleUserActivity(userActivity) + } + + @discardableResult + private func handleUserActivity(_ userActivity: NSUserActivity) -> Bool { + guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, + let url = userActivity.webpageURL, + let completionHandler = completionHandler else { + return false + } + completionHandler(url, nil) + return true + } + + @available(iOS 13.0, *) + private func acquireRootViewController() -> UIViewController? { + if let vc = registrar?.viewController { + return vc + } + + let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene } + let scene = scenes.first(where: { $0.activationState == .foregroundActive }) ?? scenes.first + guard let windowScene = scene else { return nil } + + var keyWindow: UIWindow? = nil + if #available(iOS 15.0, *) { + keyWindow = windowScene.keyWindow + } + if keyWindow == nil { + keyWindow = windowScene.windows.first(where: { $0.isKeyWindow }) ?? windowScene.windows.first } + return keyWindow?.rootViewController } }