Skip to content

Commit 5b51fb4

Browse files
timshadeljunying1
andauthored
🎉 Add support for Flutter "add to app" (LinusU#106)
* The current implementation assumes the plugin is used in a pure Flutter app. It casts the app's rootViewController to FlutterViewController. This supports using this plugin in an "add to app" use case. The implementation does not assume the rootViewController is an instance of FlutterViewController, but rather starts with the presented view controller, and navigates up the stack to the root controller. It also handles in the case of a non-modal screen, in which case it would be a UINavigationController. We could probably just use the presented view controller, rather than navigating up the stack to the root to use as the session context provider. * Use guarded cast instead of forced unwrap. * fix(swift): make changes from code review * fix(swift): eliminate !s and unused code Co-authored-by: junying1 <jying@simplec.com>
1 parent a919cb8 commit 5b51fb4

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

ios/Classes/SwiftFlutterWebAuthPlugin.swift

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ public class SwiftFlutterWebAuthPlugin: NSObject, FlutterPlugin {
1111
}
1212

1313
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
14-
if call.method == "authenticate" {
15-
let url = URL(string: (call.arguments as! Dictionary<String, AnyObject>)["url"] as! String)!
16-
let callbackURLScheme = (call.arguments as! Dictionary<String, AnyObject>)["callbackUrlScheme"] as! String
17-
let preferEphemeral = (call.arguments as! Dictionary<String, AnyObject>)["preferEphemeral"] as! Bool
14+
if call.method == "authenticate",
15+
let arguments = call.arguments as? Dictionary<String, AnyObject>,
16+
let urlString = arguments["url"] as? String,
17+
let url = URL(string: urlString),
18+
let callbackURLScheme = arguments["callbackUrlScheme"] as? String,
19+
let preferEphemeral = arguments["preferEphemeral"] as? Bool
20+
{
1821

1922
var sessionToKeepAlive: Any? = nil // if we do not keep the session alive, it will get closed immediately while showing the dialog
2023
let completionHandler = { (url: URL?, err: Error?) in
@@ -39,20 +42,36 @@ public class SwiftFlutterWebAuthPlugin: NSObject, FlutterPlugin {
3942
return
4043
}
4144

42-
result(url!.absoluteString)
45+
guard let url = url else {
46+
result(FlutterError(code: "EUNKNOWN", message: "URL was null, but no error provided.", details: nil))
47+
return
48+
}
49+
50+
result(url.absoluteString)
4351
}
4452

4553
if #available(iOS 12, *) {
4654
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: callbackURLScheme, completionHandler: completionHandler)
4755

4856
if #available(iOS 13, *) {
49-
guard let provider = UIApplication.shared.delegate?.window??.rootViewController as? FlutterViewController else {
50-
result(FlutterError(code: "FAILED", message: "Failed to aquire root FlutterViewController" , details: nil))
57+
guard var topController = UIApplication.shared.keyWindow?.rootViewController else {
58+
result(FlutterError.aquireRootViewControllerFailed)
5159
return
5260
}
5361

62+
while let presentedViewController = topController.presentedViewController {
63+
topController = presentedViewController
64+
}
65+
if let nav = topController as? UINavigationController {
66+
topController = nav.visibleViewController ?? topController
67+
}
68+
69+
guard let contextProvider = topController as? ASWebAuthenticationPresentationContextProviding else {
70+
result(FlutterError.aquireRootViewControllerFailed)
71+
return
72+
}
73+
session.presentationContextProvider = contextProvider
5474
session.prefersEphemeralWebBrowserSession = preferEphemeral
55-
session.presentationContextProvider = provider
5675
}
5776

5877
session.start()
@@ -79,3 +98,9 @@ extension FlutterViewController: ASWebAuthenticationPresentationContextProviding
7998
return self.view.window!
8099
}
81100
}
101+
102+
fileprivate extension FlutterError {
103+
static var aquireRootViewControllerFailed: FlutterError {
104+
return FlutterError(code: "AQUIRE_ROOT_VIEW_CONTROLLER_FAILED", message: "Failed to aquire root view controller" , details: nil)
105+
}
106+
}

0 commit comments

Comments
 (0)