118cf86c2STomasz Sapeta // Copyright 2015-present 650 Industries. All rights reserved.
2812d0911STomasz Sapeta 
3cc2b5a7fSGabriel Donadel Dall'Agnol import ExpoModulesCore
4aacdc29aSŁukasz Kosmaty import SafariServices
5812d0911STomasz Sapeta import React
618cf86c2STomasz Sapeta 
7cc2b5a7fSGabriel Donadel Dall'Agnol public class DevMenuInternalModule: Module {
definitionnull8cc2b5a7fSGabriel Donadel Dall'Agnol   public func definition() -> ModuleDefinition {
9cc2b5a7fSGabriel Donadel Dall'Agnol     Name("ExpoDevMenuInternal")
1018cf86c2STomasz Sapeta 
1118cf86c2STomasz Sapeta     // MARK: JavaScript API
12cc2b5a7fSGabriel Donadel Dall'Agnol     Constants {
136aca4c59SŁukasz Kosmaty       #if targetEnvironment(simulator)
14cc0496a6SŁukasz Kosmaty       let doesDeviceSupportKeyCommands = true
156aca4c59SŁukasz Kosmaty       #else
166aca4c59SŁukasz Kosmaty       let doesDeviceSupportKeyCommands = false
17cc0496a6SŁukasz Kosmaty       #endif
18052376e8Sandy       return [
19cc2b5a7fSGabriel Donadel Dall'Agnol         "doesDeviceSupportKeyCommands": doesDeviceSupportKeyCommands
20052376e8Sandy       ]
21cc0496a6SŁukasz Kosmaty     }
22cc0496a6SŁukasz Kosmaty 
23cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("fetchDataSourceAsync") { (dataSourceId: String, promise: Promise) in
24cc2b5a7fSGabriel Donadel Dall'Agnol       for dataSource in DevMenuManager.shared.devMenuDataSources where dataSource.id == dataSourceId {
25221227d5SŁukasz Kosmaty         dataSource.fetchData { data in
26cc2b5a7fSGabriel Donadel Dall'Agnol           promise.resolve(data.map { $0.serialize() })
27221227d5SŁukasz Kosmaty         }
28765b47daSTomasz Sapeta         return
29221227d5SŁukasz Kosmaty       }
30cc2b5a7fSGabriel Donadel Dall'Agnol 
31cc2b5a7fSGabriel Donadel Dall'Agnol       throw Exception(name: "ERR_DEVMENU_DATA_SOURCE_FAILED", description: "DataSource \(dataSourceId) not found.")
32221227d5SŁukasz Kosmaty     }
33221227d5SŁukasz Kosmaty 
34cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("dispatchCallableAsync") { (callableId: String, args: [String: Any]?) in
35cc2b5a7fSGabriel Donadel Dall'Agnol       DevMenuManager.shared.dispatchCallable(withId: callableId, args: args)
36221227d5SŁukasz Kosmaty     }
37221227d5SŁukasz Kosmaty 
38cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("loadFontsAsync") {
39cc2b5a7fSGabriel Donadel Dall'Agnol       DevMenuManager.shared.loadFonts()
4018cf86c2STomasz Sapeta     }
415e3c9f9bSŁukasz Kosmaty 
42cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("hideMenu") {
43cc2b5a7fSGabriel Donadel Dall'Agnol       DevMenuManager.shared.hideMenu()
445e3c9f9bSŁukasz Kosmaty     }
4518cf86c2STomasz Sapeta 
46cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("closeMenu") {
47cc2b5a7fSGabriel Donadel Dall'Agnol       DevMenuManager.shared.closeMenu()
4818cf86c2STomasz Sapeta     }
4918cf86c2STomasz Sapeta 
50cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("setOnboardingFinished") { (finished: Bool) in
51a93c953bSandy       DevMenuPreferences.isOnboardingFinished = finished
5218cf86c2STomasz Sapeta     }
53813cefc1SŁukasz Kosmaty 
54cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("openDevMenuFromReactNative") {
55cc2b5a7fSGabriel Donadel Dall'Agnol       guard let rctDevMenu = DevMenuManager.shared.currentBridge?.devMenu else {
56813cefc1SŁukasz Kosmaty         return
57813cefc1SŁukasz Kosmaty       }
58813cefc1SŁukasz Kosmaty 
59*e3d19369SGabriel Donadel Dall'Agnol       DevMenuManager.shared.closeMenu {
60813cefc1SŁukasz Kosmaty         DispatchQueue.main.async {
61813cefc1SŁukasz Kosmaty           rctDevMenu.show()
62813cefc1SŁukasz Kosmaty         }
63813cefc1SŁukasz Kosmaty       }
64*e3d19369SGabriel Donadel Dall'Agnol     }
6526eb6799SŁukasz Kosmaty 
66cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("onScreenChangeAsync") { (currentScreen: String?) in
67cc2b5a7fSGabriel Donadel Dall'Agnol       DevMenuManager.shared.setCurrentScreen(currentScreen)
6826eb6799SŁukasz Kosmaty     }
6983ade7efSandy 
70cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("fireCallback") { (name: String) in
71cc2b5a7fSGabriel Donadel Dall'Agnol       guard let callback = DevMenuManager.shared.registeredCallbacks.first(where: { $0.name == name }) else {
72cc2b5a7fSGabriel Donadel Dall'Agnol         throw Exception(name: "ERR_DEVMENU_ACTION_FAILED", description: "\(name) is not a registered callback")
7383ade7efSandy       }
7483ade7efSandy 
75cc2b5a7fSGabriel Donadel Dall'Agnol       DevMenuManager.shared.sendEventToDelegateBridge("registeredCallbackFired", data: name)
76169f3220SŁukasz Kosmaty       if callback.shouldCollapse {
77cc2b5a7fSGabriel Donadel Dall'Agnol         DevMenuManager.shared.closeMenu()
78169f3220SŁukasz Kosmaty       }
79cc2b5a7fSGabriel Donadel Dall'Agnol     }
80cc2b5a7fSGabriel Donadel Dall'Agnol 
81cc2b5a7fSGabriel Donadel Dall'Agnol     AsyncFunction("copyToClipboardAsync") { (content: String) in
82cc2b5a7fSGabriel Donadel Dall'Agnol       let clipboard = UIPasteboard.general
83cc2b5a7fSGabriel Donadel Dall'Agnol       clipboard.string = content as String
84cc2b5a7fSGabriel Donadel Dall'Agnol     }
8583ade7efSandy   }
8618cf86c2STomasz Sapeta }
87