1 // Copyright 2022-present 650 Industries. All rights reserved.
2 
3 import SafariServices
4 import ABI47_0_0ExpoModulesCore
5 
6 internal class WebBrowserSession: NSObject, SFSafariViewControllerDelegate, UIAdaptivePresentationControllerDelegate {
7   let viewController: SFSafariViewController
8   var promise: Promise?
9   var isOpen: Bool {
10     promise != nil
11   }
12 
13   init(url: URL, options: WebBrowserOptions) {
14     let configuration = SFSafariViewController.Configuration()
15     configuration.barCollapsingEnabled = options.enableBarCollapsing
16     configuration.entersReaderIfAvailable = options.readerMode
17 
18     viewController = SFSafariViewController(url: url, configuration: configuration)
19     viewController.modalPresentationStyle = options.presentationStyle.toPresentationStyle()
20     viewController.dismissButtonStyle = options.dismissButtonStyle.toSafariDismissButtonStyle()
21     viewController.preferredBarTintColor = options.toolbarColor
22     viewController.preferredControlTintColor = options.controlsColor
23 
24     super.init()
25     viewController.delegate = self
26     viewController.presentationController?.delegate = self
27   }
28 
29   func open(_ promise: Promise) {
30     var currentViewController = UIApplication.shared.keyWindow?.rootViewController
31     while currentViewController?.presentedViewController != nil {
32       currentViewController = currentViewController?.presentedViewController
33     }
34     currentViewController?.present(viewController, animated: true, completion: nil)
35 
36     self.promise = promise
37   }
38 
39   func dismiss() {
40     viewController.dismiss(animated: true) {
41       self.finish(type: "dismiss")
42     }
43   }
44 
45   // MARK: - SFSafariViewControllerDelegate
46 
47   func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
48     finish(type: "cancel")
49   }
50 
51   // MARK: - UIAdaptivePresentationControllerDelegate
52 
53   func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
54     finish(type: "cancel")
55   }
56 
57   // MARK: - Private
58 
59   private func finish(type: String) {
60     promise?.resolve(["type": type])
61     promise = nil
62   }
63 }
64