1 import ExpoModulesCore 2 3 public final class SharingModule: Module { 4 definitionnull5 public func definition() -> ModuleDefinition { 6 Name("ExpoSharing") 7 8 AsyncFunction("shareAsync") { (url: URL, options: SharingOptions, promise: Promise) in 9 guard let filePermissions: EXFilePermissionModuleInterface = 10 appContext?.legacyModule(implementing: EXFilePermissionModuleInterface.self) 11 else { 12 throw FilePermissionModuleException() 13 } 14 15 let grantedPermissions = filePermissions.getPathPermissions(url.relativePath) 16 guard grantedPermissions.rawValue >= EXFileSystemPermissionFlags.read.rawValue else { 17 throw FilePermissionException() 18 } 19 20 let activityController = UIActivityViewController(activityItems: [url], applicationActivities: nil) 21 activityController.title = options.dialogTitle 22 23 activityController.completionWithItemsHandler = { type, completed, _, _ in 24 // user shared an item 25 if type != nil && completed { 26 promise.resolve(nil) 27 } 28 29 // dismissed without action 30 if type == nil && !completed { 31 promise.resolve(nil) 32 } 33 } 34 35 guard let currentViewcontroller = appContext?.utilities?.currentViewController() else { 36 throw MissingCurrentViewControllerException() 37 } 38 39 // Apple docs state that `UIActivityViewController` must be presented in a 40 // popover on iPad https://developer.apple.com/documentation/uikit/uiactivityviewcontroller 41 if UIDevice.current.userInterfaceIdiom == .pad { 42 let viewFrame = currentViewcontroller.view.frame 43 activityController.popoverPresentationController?.sourceRect = CGRect( 44 x: viewFrame.midX, 45 y: viewFrame.maxY, 46 width: 0, 47 height: 0 48 ) 49 activityController.popoverPresentationController?.sourceView = currentViewcontroller.view 50 activityController.modalPresentationStyle = .pageSheet 51 } 52 53 currentViewcontroller.present(activityController, animated: true) 54 } 55 .runOnQueue(.main) 56 } 57 } 58