1 import ExpoModulesCore
2 
3 struct SharingContext {
4   let pendingPromise: Promise
5   let delegate: SharingDelegate
6 }
7 
8 public final class SharingModule: Module, OnDocumentInteractionResult {
9   private var documentInteractionController: UIDocumentInteractionController?
10   private var sharingContext: SharingContext?
11 
12   public func definition() -> ModuleDefinition {
13     Name("ExpoSharing")
14 
15     AsyncFunction("shareAsync") { (url: URL, options: SharingOptions, promise: Promise) in
16       guard sharingContext == nil else {
17         throw SharingInProgressException()
18       }
19 
20       guard let filePermissions: EXFilePermissionModuleInterface =
21         appContext?.legacyModule(implementing: EXFilePermissionModuleInterface.self)
22       else {
23         throw FilePermissionModuleException()
24       }
25 
26       let grantedPermissions = filePermissions.getPathPermissions(url.absoluteString)
27       guard grantedPermissions.rawValue >= EXFileSystemPermissionFlags.read.rawValue else {
28         throw FilePermissionException()
29       }
30 
31       let sharingDelegate = SharingDelegate(resultHandler: self)
32       documentInteractionController = UIDocumentInteractionController(url: url)
33       documentInteractionController?.delegate = sharingDelegate
34       documentInteractionController?.uti = options.UTI
35 
36       guard let currentViewcontroller = appContext?.utilities?.currentViewController(),
37         let rootView = currentViewcontroller.view,
38         let documentInteractionController = documentInteractionController
39       else {
40         throw MissingCurrentViewControllerException()
41       }
42 
43       if documentInteractionController.presentOpenInMenu(from: .zero, in: rootView, animated: true) {
44         self.sharingContext = SharingContext(pendingPromise: promise, delegate: sharingDelegate)
45       } else {
46         self.documentInteractionController = nil
47         throw UnsupportedTypeException()
48       }
49     }
50     .runOnQueue(.main)
51   }
52 
53   func didDismissOpenInMenu() {
54     guard let promise = self.sharingContext?.pendingPromise else {
55       log.error("SharingModule: sharing context has been lost")
56       return
57     }
58 
59     promise.resolve(nil)
60     self.sharingContext = nil
61     self.documentInteractionController?.dismissMenu(animated: true)
62     self.documentInteractionController = nil
63   }
64 }
65