1 // Copyright 2015-present 650 Industries. All rights reserved. 2 3 import ExpoModulesCore 4 import SafariServices 5 import React 6 7 public class DevMenuInternalModule: Module { 8 public func definition() -> ModuleDefinition { 9 Name("ExpoDevMenuInternal") 10 11 // MARK: JavaScript API 12 Constants { 13 #if targetEnvironment(simulator) 14 let doesDeviceSupportKeyCommands = true 15 #else 16 let doesDeviceSupportKeyCommands = false 17 #endif 18 return [ 19 "doesDeviceSupportKeyCommands": doesDeviceSupportKeyCommands 20 ] 21 } 22 23 AsyncFunction("fetchDataSourceAsync") { (dataSourceId: String, promise: Promise) in 24 for dataSource in DevMenuManager.shared.devMenuDataSources where dataSource.id == dataSourceId { 25 dataSource.fetchData { data in 26 promise.resolve(data.map { $0.serialize() }) 27 } 28 return 29 } 30 31 throw Exception(name: "ERR_DEVMENU_DATA_SOURCE_FAILED", description: "DataSource \(dataSourceId) not found.") 32 } 33 34 AsyncFunction("dispatchCallableAsync") { (callableId: String, args: [String: Any]?) in 35 DevMenuManager.shared.dispatchCallable(withId: callableId, args: args) 36 } 37 38 AsyncFunction("loadFontsAsync") { 39 DevMenuManager.shared.loadFonts() 40 } 41 42 AsyncFunction("hideMenu") { 43 DevMenuManager.shared.hideMenu() 44 } 45 46 AsyncFunction("closeMenu") { 47 DevMenuManager.shared.closeMenu() 48 } 49 50 AsyncFunction("setOnboardingFinished") { (finished: Bool) in 51 DevMenuPreferences.isOnboardingFinished = finished 52 } 53 54 AsyncFunction("openDevMenuFromReactNative") { 55 guard let rctDevMenu = DevMenuManager.shared.currentBridge?.devMenu else { 56 return 57 } 58 59 DispatchQueue.main.async { 60 rctDevMenu.show() 61 } 62 } 63 64 AsyncFunction("onScreenChangeAsync") { (currentScreen: String?) in 65 DevMenuManager.shared.setCurrentScreen(currentScreen) 66 } 67 68 AsyncFunction("fireCallback") { (name: String) in 69 guard let callback = DevMenuManager.shared.registeredCallbacks.first(where: { $0.name == name }) else { 70 throw Exception(name: "ERR_DEVMENU_ACTION_FAILED", description: "\(name) is not a registered callback") 71 } 72 73 DevMenuManager.shared.sendEventToDelegateBridge("registeredCallbackFired", data: name) 74 if callback.shouldCollapse { 75 DevMenuManager.shared.closeMenu() 76 } 77 } 78 79 AsyncFunction("copyToClipboardAsync") { (content: String) in 80 let clipboard = UIPasteboard.general 81 clipboard.string = content as String 82 } 83 } 84 } 85