expo-dev-menu-interface 1.8.4 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/interfaces/devmenu/DevMenuManagerInterface.kt +0 -31
- package/android/src/main/java/expo/interfaces/devmenu/ReactHostWrapper.kt +7 -1
- package/ios/expo-dev-menu-interface.podspec +3 -9
- package/package.json +2 -2
- package/android/src/main/java/expo/interfaces/devmenu/DevMenuExtensionInterface.kt +0 -32
- package/android/src/main/java/expo/interfaces/devmenu/DevMenuManagerProviderInterface.kt +0 -9
- package/android/src/main/java/expo/interfaces/devmenu/annotations/ContainsDevMenuExtension.kt +0 -5
- package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuDataSource.kt +0 -22
- package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuExportedCallable.kt +0 -34
- package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuItemImportance.kt +0 -12
- package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuItems.kt +0 -182
- package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuItemsContainer.kt +0 -53
- package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuItemsContainerInterface.kt +0 -30
- package/ios/DevMenuExtensionProtocol.swift +0 -39
- package/ios/EXDevExtensions.swift +0 -10
- package/ios/MenuItems/DevMenuAction.swift +0 -105
- package/ios/MenuItems/DevMenuDataSource.swift +0 -33
- package/ios/MenuItems/DevMenuExportedCallable.swift +0 -64
- package/ios/MenuItems/DevMenuGroup.swift +0 -37
- package/ios/MenuItems/DevMenuItem.swift +0 -29
- package/ios/MenuItems/DevMenuItemsContainer.swift +0 -32
- package/ios/MenuItems/DevMenuItemsContainerProtocol.swift +0 -12
- package/ios/MenuItems/DevMenuLink.swift +0 -28
- package/ios/MenuItems/DevMenuScreen.swift +0 -37
- package/ios/MenuItems/DevMenuScreenItem.swift +0 -26
- package/ios/MenuItems/DevMenuSelectionList.swift +0 -91
- package/ios/Tests/DevMenuActionTest.swift +0 -42
- package/ios/Tests/DevMenuItemsContainerTest.swift +0 -63
- package/ios/Tests/DevMenuLinkTest.swift +0 -20
- package/ios/Tests/DevMenuScreenTest.swift +0 -17
- package/ios/Tests/DevMenuSelectionListTest.swift +0 -17
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'host.exp.exponent'
|
|
4
|
-
version = '1.
|
|
4
|
+
version = '1.9.1'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -13,7 +13,7 @@ android {
|
|
|
13
13
|
namespace "expo.interfaces.devmenu"
|
|
14
14
|
defaultConfig {
|
|
15
15
|
versionCode 6
|
|
16
|
-
versionName '1.
|
|
16
|
+
versionName '1.9.1'
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
package expo.interfaces.devmenu
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
|
-
import android.os.Bundle
|
|
5
4
|
import android.view.KeyEvent
|
|
6
5
|
import android.view.MotionEvent
|
|
7
|
-
import com.facebook.react.bridge.ReadableMap
|
|
8
|
-
import expo.interfaces.devmenu.items.DevMenuDataSourceItem
|
|
9
6
|
import kotlinx.coroutines.CoroutineScope
|
|
10
7
|
|
|
11
8
|
interface DevMenuManagerInterface {
|
|
@@ -51,27 +48,6 @@ interface DevMenuManagerInterface {
|
|
|
51
48
|
*/
|
|
52
49
|
fun initializeWithReactHost(reactHost: ReactHostWrapper)
|
|
53
50
|
|
|
54
|
-
/**
|
|
55
|
-
* Finds and dispatches action with provided [actionId].
|
|
56
|
-
* If such action doesn't exist, ignore it.
|
|
57
|
-
*/
|
|
58
|
-
fun dispatchCallable(actionId: String, args: ReadableMap?)
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Registers an extra [DevMenuExtensionInterface] to the manager.
|
|
62
|
-
*/
|
|
63
|
-
fun registerExtensionInterface(extensionInterface: DevMenuExtensionInterface)
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @return a list of dev menu items serialized to the [Bundle].
|
|
67
|
-
*/
|
|
68
|
-
fun serializedItems(): List<Bundle>
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @return a list of dev menu screens serialized to the [Bundle].
|
|
72
|
-
*/
|
|
73
|
-
fun serializedScreens(): List<Bundle>
|
|
74
|
-
|
|
75
51
|
/**
|
|
76
52
|
* @return a instance of [DevMenuPreferencesInterface] that keeps all settings for current dev menu delegate,
|
|
77
53
|
* or `null` if delegate wasn't provided.
|
|
@@ -88,11 +64,6 @@ interface DevMenuManagerInterface {
|
|
|
88
64
|
*/
|
|
89
65
|
fun synchronizeDelegate()
|
|
90
66
|
|
|
91
|
-
/**
|
|
92
|
-
* Set the current screen on which all action will be dispatched.
|
|
93
|
-
*/
|
|
94
|
-
fun setCurrentScreen(screen: String?)
|
|
95
|
-
|
|
96
67
|
/**
|
|
97
68
|
* Sends an event to the delegate's bridge if exists.
|
|
98
69
|
*/
|
|
@@ -108,7 +79,5 @@ interface DevMenuManagerInterface {
|
|
|
108
79
|
*/
|
|
109
80
|
fun setCanLaunchDevMenuOnStart(shouldAutoLaunch: Boolean)
|
|
110
81
|
|
|
111
|
-
suspend fun fetchDataSource(id: String): List<DevMenuDataSourceItem>
|
|
112
|
-
|
|
113
82
|
val coroutineScope: CoroutineScope
|
|
114
83
|
}
|
|
@@ -11,6 +11,7 @@ import com.facebook.react.common.LifecycleState
|
|
|
11
11
|
import com.facebook.react.config.ReactFeatureFlags
|
|
12
12
|
import com.facebook.react.devsupport.interfaces.DevSupportManager
|
|
13
13
|
import com.facebook.react.runtime.ReactHostImpl
|
|
14
|
+
import java.lang.reflect.Field
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* An abstract wrapper to host [ReactNativeHost] and [ReactHost],
|
|
@@ -68,7 +69,12 @@ class ReactHostWrapper(reactNativeHost: ReactNativeHost, reactHostProvider: () -
|
|
|
68
69
|
val jsExecutorName: String
|
|
69
70
|
get() {
|
|
70
71
|
if (isBridgelessMode) {
|
|
71
|
-
|
|
72
|
+
// Access private field using reflection
|
|
73
|
+
val jsEngineResolutionAlgorithmField: Field = reactHost::class.java.getDeclaredField("mJSEngineResolutionAlgorithm")
|
|
74
|
+
jsEngineResolutionAlgorithmField.isAccessible = true
|
|
75
|
+
val jsEngineResolutionAlgorithm = jsEngineResolutionAlgorithmField.get(reactHost) as? JSEngineResolutionAlgorithm
|
|
76
|
+
|
|
77
|
+
return if (jsEngineResolutionAlgorithm == JSEngineResolutionAlgorithm.JSC) {
|
|
72
78
|
"JSC"
|
|
73
79
|
} else {
|
|
74
80
|
"Hermes"
|
|
@@ -10,13 +10,14 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.license = package['license']
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.homepage = package['homepage']
|
|
13
|
-
s.
|
|
13
|
+
s.platforms = {
|
|
14
|
+
:ios => '15.1'
|
|
15
|
+
}
|
|
14
16
|
s.swift_version = '5.2'
|
|
15
17
|
s.source = { git: 'https://github.com/expo/expo.git' }
|
|
16
18
|
s.static_framework = true
|
|
17
19
|
s.source_files = '**/*.{h,m,swift}'
|
|
18
20
|
s.preserve_paths = '**/*.{h,m,swift}'
|
|
19
|
-
s.exclude_files = 'Tests/**/*.{h,m,swift}'
|
|
20
21
|
s.requires_arc = true
|
|
21
22
|
s.header_dir = 'EXDevMenuInterface'
|
|
22
23
|
|
|
@@ -26,11 +27,4 @@ Pod::Spec.new do |s|
|
|
|
26
27
|
|
|
27
28
|
# Swift/Objective-C compatibility
|
|
28
29
|
s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" }
|
|
29
|
-
|
|
30
|
-
s.test_spec 'Tests' do |test_spec|
|
|
31
|
-
test_spec.platform = :ios, '13.4'
|
|
32
|
-
test_spec.source_files = 'Tests/**/*.{h,m,swift}'
|
|
33
|
-
test_spec.dependency 'Quick'
|
|
34
|
-
test_spec.dependency 'Nimble'
|
|
35
|
-
end
|
|
36
30
|
end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-dev-menu-interface",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Interface for expo-dev-menu",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"expo": "*"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "c0899e56c5be08b0142f06f05aa7bac8d6bc18b8"
|
|
29
29
|
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu
|
|
2
|
-
|
|
3
|
-
import expo.interfaces.devmenu.items.DevMenuDataSourceInterface
|
|
4
|
-
import expo.interfaces.devmenu.items.DevMenuItemsContainerInterface
|
|
5
|
-
import expo.interfaces.devmenu.items.DevMenuScreen
|
|
6
|
-
|
|
7
|
-
interface DevMenuExtensionSettingsInterface {
|
|
8
|
-
fun wasRunOnDevelopmentBridge(): Boolean
|
|
9
|
-
val manager: DevMenuManagerInterface
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A native extension to provide extra dev-menu items.
|
|
14
|
-
* The implementation should call [DevMenuManagerInterface.registerExtensionInterface]
|
|
15
|
-
* to register its instance to the manager.
|
|
16
|
-
*/
|
|
17
|
-
interface DevMenuExtensionInterface {
|
|
18
|
-
/**
|
|
19
|
-
* Returns a name of the module and the extension. Also required by [com.facebook.react.bridge.ReactContextBaseJavaModule].
|
|
20
|
-
*/
|
|
21
|
-
fun getName(): String
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Returns a `DevMenuItemsContainer` that contains the dev menu items to show on the main screen.
|
|
25
|
-
* It's called only once for the extension instance — results are being cached on first dev menu launch.
|
|
26
|
-
*/
|
|
27
|
-
fun devMenuItems(settings: DevMenuExtensionSettingsInterface): DevMenuItemsContainerInterface?
|
|
28
|
-
|
|
29
|
-
fun devMenuScreens(settings: DevMenuExtensionSettingsInterface): List<DevMenuScreen>? = null
|
|
30
|
-
|
|
31
|
-
fun devMenuDataSources(settings: DevMenuExtensionSettingsInterface): List<DevMenuDataSourceInterface>? = null
|
|
32
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu.items
|
|
2
|
-
|
|
3
|
-
import android.os.Bundle
|
|
4
|
-
|
|
5
|
-
interface DevMenuDataSourceItem {
|
|
6
|
-
fun serialize(): Bundle
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface DevMenuDataSourceInterface {
|
|
10
|
-
val id: String
|
|
11
|
-
|
|
12
|
-
suspend fun fetchData(): List<DevMenuDataSourceItem>
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
class DevMenuListDataSource(
|
|
16
|
-
override val id: String,
|
|
17
|
-
val dataFetcher: suspend () -> List<DevMenuSelectionList.Item>
|
|
18
|
-
) : DevMenuDataSourceInterface {
|
|
19
|
-
override suspend fun fetchData(): List<DevMenuDataSourceItem> {
|
|
20
|
-
return dataFetcher()
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu.items
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.ReadableMap
|
|
4
|
-
|
|
5
|
-
interface DevMenuCallableProvider {
|
|
6
|
-
fun registerCallable(): DevMenuExportedCallable?
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
sealed class DevMenuExportedCallable(val id: String)
|
|
10
|
-
|
|
11
|
-
class DevMenuExportedFunction(
|
|
12
|
-
id: String,
|
|
13
|
-
val function: (ReadableMap?) -> Unit
|
|
14
|
-
) : DevMenuExportedCallable(id) {
|
|
15
|
-
fun call(args: ReadableMap?) {
|
|
16
|
-
function(args)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class DevMenuExportedAction(
|
|
21
|
-
id: String,
|
|
22
|
-
val action: () -> Unit
|
|
23
|
-
) : DevMenuExportedCallable(id) {
|
|
24
|
-
var keyCommand: KeyCommand? = null
|
|
25
|
-
var isAvailable = { true }
|
|
26
|
-
|
|
27
|
-
fun registerKeyCommand(keyCommand: KeyCommand?) {
|
|
28
|
-
this.keyCommand = keyCommand
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
fun call() {
|
|
32
|
-
action()
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu.items
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Tells how important the dev menu item is. To use it with [DevMenuItem], you need to pass its [value].
|
|
5
|
-
*/
|
|
6
|
-
enum class DevMenuItemImportance(val value: Int) {
|
|
7
|
-
LOWEST(-200),
|
|
8
|
-
LOW(-100),
|
|
9
|
-
MEDIUM(0),
|
|
10
|
-
HIGH(100),
|
|
11
|
-
HIGHEST(200)
|
|
12
|
-
}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu.items
|
|
2
|
-
|
|
3
|
-
import android.os.Bundle
|
|
4
|
-
import android.view.KeyCharacterMap
|
|
5
|
-
import com.facebook.react.bridge.ReadableMap
|
|
6
|
-
|
|
7
|
-
val keyCharacterMap: KeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD)
|
|
8
|
-
|
|
9
|
-
// Android virtual keyboard only supports `SHIFT` as a modifier.
|
|
10
|
-
data class KeyCommand(val code: Int, val withShift: Boolean = false)
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* An abstract representation of the single dev menu item.
|
|
14
|
-
*/
|
|
15
|
-
sealed class DevMenuItem {
|
|
16
|
-
/**
|
|
17
|
-
* Represent how this item will be treated by the js.
|
|
18
|
-
* 1 - [DevMenuAction]
|
|
19
|
-
* 2 - [DevMenuGroup]
|
|
20
|
-
* 3 - [DevMenuScreen]
|
|
21
|
-
* 4 - [DevMenuLink]
|
|
22
|
-
* 5 - [DevMenuSelectionList]
|
|
23
|
-
*/
|
|
24
|
-
abstract fun getExportedType(): Int
|
|
25
|
-
|
|
26
|
-
open fun serialize() = Bundle().apply {
|
|
27
|
-
putInt("type", getExportedType())
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
abstract class DevMenuScreenItem : DevMenuItem() {
|
|
32
|
-
var importance = DevMenuItemImportance.MEDIUM.value
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
class DevMenuScreen(
|
|
36
|
-
val screenName: String,
|
|
37
|
-
itemsContainer: DevMenuDSLItemsContainerInterface = DevMenuItemsContainer()
|
|
38
|
-
) : DevMenuItem(), DevMenuDSLItemsContainerInterface by itemsContainer {
|
|
39
|
-
override fun getExportedType() = 3
|
|
40
|
-
|
|
41
|
-
override fun serialize() = super.serialize().apply {
|
|
42
|
-
putString("screenName", screenName)
|
|
43
|
-
putParcelableArray("items", serializeItems())
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
class DevMenuGroup(
|
|
48
|
-
itemsContainer: DevMenuDSLItemsContainerInterface = DevMenuItemsContainer()
|
|
49
|
-
) : DevMenuScreenItem(), DevMenuDSLItemsContainerInterface by itemsContainer {
|
|
50
|
-
override fun getExportedType() = 2
|
|
51
|
-
|
|
52
|
-
override fun serialize() = super.serialize().apply {
|
|
53
|
-
putParcelableArray("items", serializeItems())
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
class DevMenuAction(
|
|
58
|
-
actionId: String,
|
|
59
|
-
action: () -> Unit
|
|
60
|
-
) : DevMenuScreenItem(), DevMenuCallableProvider {
|
|
61
|
-
val callable = DevMenuExportedAction(actionId, action)
|
|
62
|
-
var isAvailable: () -> Boolean
|
|
63
|
-
get() = callable.isAvailable
|
|
64
|
-
set(value) {
|
|
65
|
-
callable.isAvailable = value
|
|
66
|
-
}
|
|
67
|
-
var isEnabled = { false }
|
|
68
|
-
var label = { "" }
|
|
69
|
-
var detail = { "" }
|
|
70
|
-
var glyphName = { "" }
|
|
71
|
-
|
|
72
|
-
var keyCommand: KeyCommand?
|
|
73
|
-
get() = callable.keyCommand
|
|
74
|
-
set(value) {
|
|
75
|
-
callable.registerKeyCommand(value)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
override fun getExportedType() = 1
|
|
79
|
-
|
|
80
|
-
override fun serialize() = super.serialize().apply {
|
|
81
|
-
putString("actionId", callable.id)
|
|
82
|
-
putBoolean("isAvailable", isAvailable())
|
|
83
|
-
putBoolean("isEnabled", isEnabled())
|
|
84
|
-
putString("label", label())
|
|
85
|
-
putString("detail", detail())
|
|
86
|
-
putString("glyphName", glyphName())
|
|
87
|
-
|
|
88
|
-
putBundle(
|
|
89
|
-
"keyCommand",
|
|
90
|
-
keyCommand?.let { keyCommand ->
|
|
91
|
-
Bundle().apply {
|
|
92
|
-
putString("input", keyCharacterMap.getDisplayLabel(keyCommand.code).toString())
|
|
93
|
-
putInt("modifiers", exportKeyCommandModifiers())
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private fun exportKeyCommandModifiers(): Int {
|
|
100
|
-
if (keyCommand?.withShift == true) {
|
|
101
|
-
return 1 shl 3
|
|
102
|
-
}
|
|
103
|
-
return 0
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
override fun registerCallable(): DevMenuExportedCallable {
|
|
107
|
-
return callable
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
class DevMenuLink(private val target: String) : DevMenuScreenItem() {
|
|
112
|
-
var label = { "" }
|
|
113
|
-
var glyphName = { "" }
|
|
114
|
-
|
|
115
|
-
override fun getExportedType() = 4
|
|
116
|
-
|
|
117
|
-
override fun serialize() = super.serialize().apply {
|
|
118
|
-
putString("target", target)
|
|
119
|
-
putString("label", label())
|
|
120
|
-
putString("glyphName", glyphName())
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
class DevMenuSelectionList : DevMenuScreenItem(), DevMenuCallableProvider {
|
|
125
|
-
class Item : DevMenuDataSourceItem {
|
|
126
|
-
class Tag {
|
|
127
|
-
var glyphName = { "" }
|
|
128
|
-
var text = { "" }
|
|
129
|
-
|
|
130
|
-
internal fun serialize() = Bundle().apply {
|
|
131
|
-
putString("text", text())
|
|
132
|
-
putString("glyphName", glyphName())
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
var title = { "" }
|
|
137
|
-
var tags: () -> List<Tag> = { emptyList() }
|
|
138
|
-
var warning: () -> String? = { null }
|
|
139
|
-
var isChecked = { false }
|
|
140
|
-
var onClickData: () -> Bundle? = { null }
|
|
141
|
-
|
|
142
|
-
override fun serialize() = Bundle().apply {
|
|
143
|
-
putString("title", title())
|
|
144
|
-
putString("warning", warning())
|
|
145
|
-
putBoolean("isChecked", isChecked())
|
|
146
|
-
putBundle("onClickData", onClickData())
|
|
147
|
-
putParcelableArray("tags", tags().map { it.serialize() }.toTypedArray())
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private var items = ArrayList<Item>()
|
|
152
|
-
private var callable: DevMenuExportedFunction? = null
|
|
153
|
-
var dataSourceId: () -> String? = { null }
|
|
154
|
-
|
|
155
|
-
fun addOnClick(handler: (ReadableMap?) -> Unit) {
|
|
156
|
-
callable = DevMenuExportedFunction("expo-dev-menu.selection-list.#${ActionID++}", handler)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
fun addItem(item: Item) {
|
|
160
|
-
items.add(item)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
override fun getExportedType(): Int {
|
|
164
|
-
return 5
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
override fun serialize() = super.serialize().apply {
|
|
168
|
-
callable?.let {
|
|
169
|
-
putString("actionId", it.id)
|
|
170
|
-
}
|
|
171
|
-
putString("dataSourceId", dataSourceId())
|
|
172
|
-
putParcelableArray("items", items.map { it.serialize() }.toTypedArray())
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
companion object {
|
|
176
|
-
private var ActionID = 0
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
override fun registerCallable(): DevMenuExportedCallable? {
|
|
180
|
-
return callable
|
|
181
|
-
}
|
|
182
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu.items
|
|
2
|
-
|
|
3
|
-
import java.util.*
|
|
4
|
-
|
|
5
|
-
open class DevMenuItemsContainer : DevMenuDSLItemsContainerInterface {
|
|
6
|
-
private val items = mutableListOf<DevMenuScreenItem>()
|
|
7
|
-
|
|
8
|
-
override fun getRootItems(): List<DevMenuScreenItem> {
|
|
9
|
-
items.sortedWith(compareBy { it.importance })
|
|
10
|
-
return items
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
override fun getAllItems(): List<DevMenuScreenItem> {
|
|
14
|
-
val result = LinkedList<DevMenuScreenItem>()
|
|
15
|
-
|
|
16
|
-
items.forEach {
|
|
17
|
-
result.add(it)
|
|
18
|
-
|
|
19
|
-
if (it is DevMenuItemsContainerInterface) {
|
|
20
|
-
result.addAll(it.getAllItems())
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return result
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private fun addItem(item: DevMenuScreenItem) {
|
|
27
|
-
items.add(item)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
override fun group(init: DevMenuGroup.() -> Unit) = addItem(DevMenuGroup(), init)
|
|
31
|
-
|
|
32
|
-
override fun action(actionId: String, action: () -> Unit, init: DevMenuAction.() -> Unit) =
|
|
33
|
-
addItem(DevMenuAction(actionId, action), init)
|
|
34
|
-
|
|
35
|
-
override fun link(target: String, init: DevMenuLink.() -> Unit) = addItem(DevMenuLink(target), init)
|
|
36
|
-
|
|
37
|
-
override fun selectionList(init: DevMenuSelectionList.() -> Unit) = addItem(DevMenuSelectionList(), init)
|
|
38
|
-
|
|
39
|
-
private fun <T : DevMenuScreenItem> addItem(item: T, init: T.() -> Unit): T {
|
|
40
|
-
item.init()
|
|
41
|
-
addItem(item)
|
|
42
|
-
return item
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
companion object {
|
|
46
|
-
@JvmStatic
|
|
47
|
-
fun export(init: DevMenuDSLItemsContainerInterface.() -> Unit): DevMenuItemsContainer {
|
|
48
|
-
val container = DevMenuItemsContainer()
|
|
49
|
-
container.init()
|
|
50
|
-
return container
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
package/android/src/main/java/expo/interfaces/devmenu/items/DevMenuItemsContainerInterface.kt
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
package expo.interfaces.devmenu.items
|
|
2
|
-
|
|
3
|
-
import android.os.Bundle
|
|
4
|
-
|
|
5
|
-
interface DevMenuItemsContainerInterface {
|
|
6
|
-
fun getRootItems(): List<DevMenuScreenItem>
|
|
7
|
-
fun getAllItems(): List<DevMenuScreenItem>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
fun DevMenuItemsContainerInterface.serializeItems(): Array<Bundle> =
|
|
11
|
-
getRootItems()
|
|
12
|
-
.map { it.serialize() }
|
|
13
|
-
.toTypedArray()
|
|
14
|
-
|
|
15
|
-
inline fun <reified T> DevMenuItemsContainerInterface.getItemsOfType(): List<T> {
|
|
16
|
-
return getAllItems().filterIsInstance<T>()
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface DevMenuDSLItemsContainerInterface : DevMenuItemsContainerInterface {
|
|
20
|
-
fun group(init: DevMenuGroup.() -> Unit): DevMenuGroup
|
|
21
|
-
fun action(actionId: String, action: () -> Unit, init: DevMenuAction.() -> Unit): DevMenuAction
|
|
22
|
-
fun link(target: String, init: DevMenuLink.() -> Unit): DevMenuLink
|
|
23
|
-
fun selectionList(init: DevMenuSelectionList.() -> Unit): DevMenuSelectionList
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
fun screen(name: String, init: DevMenuScreen.() -> Unit): DevMenuScreen {
|
|
27
|
-
val screen = DevMenuScreen(name)
|
|
28
|
-
screen.init()
|
|
29
|
-
return screen
|
|
30
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
public protocol DevMenuExtensionSettingsProtocol {
|
|
7
|
-
func wasRunOnDevelopmentBridge() -> Bool
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
A protocol for React Native bridge modules that want to provide their own dev menu actions.
|
|
12
|
-
*/
|
|
13
|
-
@objc
|
|
14
|
-
public protocol DevMenuExtensionProtocol {
|
|
15
|
-
/**
|
|
16
|
-
Returns a name of the module and the extension. Required by `RCTBridgeModule`.
|
|
17
|
-
This function is optional because otherwise we end up with linker warning:
|
|
18
|
-
`method '+moduleName' in category from /.../expo-dev-menu/libexpo-dev-menu.a(DevMenuExtensions-....o)
|
|
19
|
-
overrides method from class in /.../expo-dev-menu/libexpo-dev-menu.a(DevMenuExtensions-....o`
|
|
20
|
-
|
|
21
|
-
So we assume that this method will be implemented by `RCTBridgeModule`.
|
|
22
|
-
In theory we can remove it. However, we leave it to get easy access to the module name.
|
|
23
|
-
*/
|
|
24
|
-
@objc
|
|
25
|
-
optional static func moduleName() -> String!
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
Returns an array of the dev menu items to show.
|
|
29
|
-
It's called only once for the extension instance — results are being cached on first dev menu launch.
|
|
30
|
-
*/
|
|
31
|
-
@objc
|
|
32
|
-
optional func devMenuItems(_ settings: DevMenuExtensionSettingsProtocol) -> DevMenuItemsContainerProtocol?
|
|
33
|
-
|
|
34
|
-
@objc
|
|
35
|
-
optional func devMenuScreens(_ settings: DevMenuExtensionSettingsProtocol) -> [DevMenuScreen]?
|
|
36
|
-
|
|
37
|
-
@objc
|
|
38
|
-
optional func devMenuDataSources(_ settings: DevMenuExtensionSettingsProtocol) -> [DevMenuDataSourceProtocol]?
|
|
39
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
// A protocol for determining if a given bridge module is a "DevExtension"
|
|
6
|
-
// DevExtensions are passed through to the dev-menu and dev-launcher JS runtimes
|
|
7
|
-
// This protocol has no fields on it as of yet but could be extended if additional functionality is needed in the future
|
|
8
|
-
|
|
9
|
-
@objc
|
|
10
|
-
public protocol EXDevExtensionProtocol {}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
import UIKit
|
|
5
|
-
|
|
6
|
-
@objc
|
|
7
|
-
open class DevMenuAction: DevMenuScreenItem, DevMenuCallableProvider {
|
|
8
|
-
@objc
|
|
9
|
-
public var callable: DevMenuExportedAction
|
|
10
|
-
|
|
11
|
-
@objc
|
|
12
|
-
public var action: () -> Void {
|
|
13
|
-
get { return self.callable.action }
|
|
14
|
-
set { self.callable.action = newValue }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@objc
|
|
18
|
-
open var isAvailable: () -> Bool {
|
|
19
|
-
get {
|
|
20
|
-
return self.callable.isAvailable
|
|
21
|
-
}
|
|
22
|
-
set {
|
|
23
|
-
self.callable.isAvailable = newValue
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@objc
|
|
28
|
-
open var isEnabled: () -> Bool = { false }
|
|
29
|
-
|
|
30
|
-
@objc
|
|
31
|
-
open var label: () -> String = { "" }
|
|
32
|
-
|
|
33
|
-
@objc
|
|
34
|
-
open var detail: () -> String = { "" }
|
|
35
|
-
|
|
36
|
-
@objc
|
|
37
|
-
open var glyphName: () -> String = { "" }
|
|
38
|
-
|
|
39
|
-
@objc
|
|
40
|
-
public init(withId id: String) {
|
|
41
|
-
self.callable = DevMenuExportedAction(withId: id, withAction: {})
|
|
42
|
-
super.init(type: .Action)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@objc
|
|
46
|
-
public convenience init(withId id: String, action: @escaping () -> Void) {
|
|
47
|
-
self.init(withId: id)
|
|
48
|
-
self.callable.action = action
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@objc
|
|
52
|
-
public convenience init(withId id: String, _ action: @escaping () -> Void) {
|
|
53
|
-
self.init(withId: id, action: action)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public func registerCallable() -> DevMenuExportedCallable? {
|
|
57
|
-
return self.callable
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@objc
|
|
61
|
-
open func registerKeyCommand(input: String, modifiers: UIKeyModifierFlags) {
|
|
62
|
-
self.callable.registerKeyCommand(input: input, modifiers: modifiers)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
@objc
|
|
66
|
-
open override func serialize() -> [String: Any] {
|
|
67
|
-
var dict = super.serialize()
|
|
68
|
-
dict["actionId"] = self.callable.id
|
|
69
|
-
dict["keyCommand"] = self.callable.keyCommand == nil ? nil : [
|
|
70
|
-
"input": self.callable.keyCommand!.input!,
|
|
71
|
-
"modifiers": exportKeyCommandModifiers()
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
dict["isAvailable"] = isAvailable()
|
|
75
|
-
dict["isEnabled"] = isAvailable()
|
|
76
|
-
dict["label"] = label()
|
|
77
|
-
dict["detail"] = detail()
|
|
78
|
-
dict["glyphName"] = glyphName()
|
|
79
|
-
|
|
80
|
-
return dict
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private func exportKeyCommandModifiers() -> Int {
|
|
84
|
-
var exportedValue = 0
|
|
85
|
-
let keyCommand = self.callable.keyCommand!
|
|
86
|
-
|
|
87
|
-
if keyCommand.modifierFlags.contains(.control) {
|
|
88
|
-
exportedValue += 1 << 0
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if keyCommand.modifierFlags.contains(.alternate) {
|
|
92
|
-
exportedValue += 1 << 1
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if keyCommand.modifierFlags.contains(.command) {
|
|
96
|
-
exportedValue += 1 << 2
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if keyCommand.modifierFlags.contains(.shift) {
|
|
100
|
-
exportedValue += 1 << 3
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return exportedValue
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
public protocol DevMenuDataSourceItem {
|
|
7
|
-
@objc
|
|
8
|
-
func serialize() -> [String: Any]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
public typealias DevMenuDataSourceResolver = ([DevMenuDataSourceItem]) -> Void
|
|
12
|
-
|
|
13
|
-
@objc
|
|
14
|
-
public protocol DevMenuDataSourceProtocol {
|
|
15
|
-
var id: String { get }
|
|
16
|
-
|
|
17
|
-
func fetchData(resolve: @escaping DevMenuDataSourceResolver)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
@objc
|
|
21
|
-
public class DevMenuListDataSource: NSObject, DevMenuDataSourceProtocol {
|
|
22
|
-
public var id: String
|
|
23
|
-
private var dataFetcher: (@escaping ([DevMenuSelectionList.Item]) -> Void) -> Void
|
|
24
|
-
|
|
25
|
-
public init(id: String, dataFetcher: @escaping (@escaping ([DevMenuSelectionList.Item]) -> Void) -> Void) {
|
|
26
|
-
self.id = id
|
|
27
|
-
self.dataFetcher = dataFetcher
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public func fetchData(resolve: @escaping ([DevMenuDataSourceItem]) -> Void) {
|
|
31
|
-
dataFetcher(resolve)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
import UIKit
|
|
5
|
-
|
|
6
|
-
@objc
|
|
7
|
-
public protocol DevMenuCallableProvider {
|
|
8
|
-
@objc
|
|
9
|
-
optional func registerCallable() -> DevMenuExportedCallable?
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
@objc
|
|
13
|
-
public class DevMenuExportedCallable: NSObject {
|
|
14
|
-
@objc
|
|
15
|
-
public let id: String
|
|
16
|
-
|
|
17
|
-
@objc
|
|
18
|
-
init(withId id: String) {
|
|
19
|
-
self.id = id
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@objc
|
|
24
|
-
public class DevMenuExportedFunction: DevMenuExportedCallable {
|
|
25
|
-
@objc
|
|
26
|
-
public var function: ([String: Any]?) -> Void
|
|
27
|
-
|
|
28
|
-
@objc
|
|
29
|
-
public init(withId id: String, withFunction function: @escaping ([String: Any]?) -> Void) {
|
|
30
|
-
self.function = function
|
|
31
|
-
super.init(withId: id)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
public func call(args: [String: Any]?) {
|
|
35
|
-
function(args)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@objc
|
|
40
|
-
public class DevMenuExportedAction: DevMenuExportedCallable {
|
|
41
|
-
@objc
|
|
42
|
-
public var action: () -> Void
|
|
43
|
-
|
|
44
|
-
@objc
|
|
45
|
-
public private(set) var keyCommand: UIKeyCommand?
|
|
46
|
-
|
|
47
|
-
@objc
|
|
48
|
-
public var isAvailable: () -> Bool = { true }
|
|
49
|
-
|
|
50
|
-
@objc
|
|
51
|
-
public init(withId id: String, withAction action: @escaping () -> Void) {
|
|
52
|
-
self.action = action
|
|
53
|
-
super.init(withId: id)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public func call() {
|
|
57
|
-
action()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@objc
|
|
61
|
-
public func registerKeyCommand(input: String, modifiers: UIKeyModifierFlags) {
|
|
62
|
-
keyCommand = UIKeyCommand(input: input, modifierFlags: modifiers, action: #selector(DevMenuUIResponderExtensionProtocol.EXDevMenu_handleKeyCommand(_:)))
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
open class DevMenuGroup: DevMenuScreenItem, DevMenuItemsContainerProtocol {
|
|
7
|
-
let container = DevMenuItemsContainer()
|
|
8
|
-
|
|
9
|
-
@objc
|
|
10
|
-
public init() {
|
|
11
|
-
super.init(type: .Group)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@objc
|
|
15
|
-
public func addItem(_ item: DevMenuScreenItem) {
|
|
16
|
-
container.addItem(item)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public func getRootItems() -> [DevMenuScreenItem] {
|
|
20
|
-
return container.getRootItems()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public func getAllItems() -> [DevMenuScreenItem] {
|
|
24
|
-
return container.getAllItems()
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
public func serializeItems() -> [[String: Any]] {
|
|
28
|
-
return container.serializeItems()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
@objc
|
|
32
|
-
public override func serialize() -> [String: Any] {
|
|
33
|
-
var dict = super.serialize()
|
|
34
|
-
dict["items"] = serializeItems()
|
|
35
|
-
return dict
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
open class DevMenuItem: NSObject {
|
|
7
|
-
@objc(DevMenuItemType)
|
|
8
|
-
public enum ItemType: Int {
|
|
9
|
-
case Action = 1
|
|
10
|
-
case Group = 2
|
|
11
|
-
case Screen = 3
|
|
12
|
-
case Link = 4
|
|
13
|
-
case SelectionList = 5
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
@objc
|
|
17
|
-
public let type: ItemType
|
|
18
|
-
|
|
19
|
-
init(type: ItemType) {
|
|
20
|
-
self.type = type
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@objc
|
|
24
|
-
open func serialize() -> [String: Any] {
|
|
25
|
-
return [
|
|
26
|
-
"type": type.rawValue
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
public class DevMenuItemsContainer: NSObject, DevMenuItemsContainerProtocol {
|
|
7
|
-
private var items: [DevMenuScreenItem] = []
|
|
8
|
-
|
|
9
|
-
public func getRootItems() -> [DevMenuScreenItem] {
|
|
10
|
-
return items.sorted { $0.importance > $1.importance }
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public func getAllItems() -> [DevMenuScreenItem] {
|
|
14
|
-
var result: [DevMenuScreenItem] = []
|
|
15
|
-
for item in items {
|
|
16
|
-
result.append(item)
|
|
17
|
-
if let container = item as? DevMenuItemsContainerProtocol {
|
|
18
|
-
result.append(contentsOf: container.getAllItems())
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return result.sorted { $0.importance > $1.importance }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@objc
|
|
25
|
-
public func addItem(_ item: DevMenuScreenItem) {
|
|
26
|
-
items.append(item)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
func serializeItems() -> [[String: Any]] {
|
|
30
|
-
return getRootItems().map({ $0.serialize() })
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
public protocol DevMenuItemsContainerProtocol {
|
|
7
|
-
@objc
|
|
8
|
-
func getRootItems() -> [DevMenuScreenItem]
|
|
9
|
-
|
|
10
|
-
@objc
|
|
11
|
-
func getAllItems() -> [DevMenuScreenItem]
|
|
12
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
public class DevMenuLink: DevMenuScreenItem {
|
|
7
|
-
var target: String
|
|
8
|
-
|
|
9
|
-
@objc
|
|
10
|
-
open var label: () -> String = { "" }
|
|
11
|
-
|
|
12
|
-
@objc
|
|
13
|
-
open var glyphName: () -> String = { "" }
|
|
14
|
-
|
|
15
|
-
public init(withTarget target: String) {
|
|
16
|
-
self.target = target
|
|
17
|
-
super.init(type: .Link)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
@objc
|
|
21
|
-
open override func serialize() -> [String: Any] {
|
|
22
|
-
var dict = super.serialize()
|
|
23
|
-
dict["target"] = target
|
|
24
|
-
dict["label"] = label()
|
|
25
|
-
dict["glyphName"] = glyphName()
|
|
26
|
-
return dict
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
public class DevMenuScreen: DevMenuItem, DevMenuItemsContainerProtocol {
|
|
7
|
-
let container = DevMenuItemsContainer()
|
|
8
|
-
public private(set) var screenName: String
|
|
9
|
-
|
|
10
|
-
public func getRootItems() -> [DevMenuScreenItem] {
|
|
11
|
-
return container.getRootItems()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public func getAllItems() -> [DevMenuScreenItem] {
|
|
15
|
-
return container.getAllItems()
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public func addItem(_ item: DevMenuScreenItem) {
|
|
19
|
-
container.addItem(item)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
func serializeItems() -> [[String: Any]] {
|
|
23
|
-
return container.serializeItems()
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public init(_ screenName: String) {
|
|
27
|
-
self.screenName = screenName
|
|
28
|
-
super.init(type: .Screen)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public override func serialize() -> [String: Any] {
|
|
32
|
-
var dict = super.serialize()
|
|
33
|
-
dict["screenName"] = screenName
|
|
34
|
-
dict["items"] = serializeItems()
|
|
35
|
-
return dict
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc
|
|
6
|
-
open class DevMenuScreenItem: DevMenuItem {
|
|
7
|
-
// Static members fit better than enum as we allow any other number.
|
|
8
|
-
static public let ImportanceLowest = -200
|
|
9
|
-
static public let ImportanceLow = -100
|
|
10
|
-
static public let ImportanceMedium = 0
|
|
11
|
-
static public let ImportanceHigh = 100
|
|
12
|
-
static public let ImportanceHighest = 200
|
|
13
|
-
|
|
14
|
-
// This enum is just for Objective-C compatibility, where values are automatically casted to integers.
|
|
15
|
-
@objc(DevMenuItemImportance)
|
|
16
|
-
public enum ItemImportance: Int {
|
|
17
|
-
case Lowest = -200
|
|
18
|
-
case Low = -100
|
|
19
|
-
case Medium = 0
|
|
20
|
-
case High = 100
|
|
21
|
-
case Highest = 200
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@objc
|
|
25
|
-
open var importance: Int = ItemImportance.Medium.rawValue
|
|
26
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
import Foundation
|
|
4
|
-
|
|
5
|
-
@objc(EXDevMenuSelectionList)
|
|
6
|
-
public class DevMenuSelectionList: DevMenuScreenItem, DevMenuCallableProvider {
|
|
7
|
-
@objc(EXDevMenuItem)
|
|
8
|
-
public class Item: NSObject, DevMenuDataSourceItem {
|
|
9
|
-
@objc(EXDevMenuTag)
|
|
10
|
-
public class Tag: NSObject {
|
|
11
|
-
@objc
|
|
12
|
-
public var text: () -> String = { "" }
|
|
13
|
-
|
|
14
|
-
@objc
|
|
15
|
-
public var glyphName: () -> String? = { nil }
|
|
16
|
-
|
|
17
|
-
fileprivate func serialize() -> [String: Any] {
|
|
18
|
-
return [
|
|
19
|
-
"text": text(),
|
|
20
|
-
"glyphName": glyphName() ?? NSNull()
|
|
21
|
-
]
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@objc
|
|
26
|
-
public var onClickData: () -> [String: Any]? = { nil }
|
|
27
|
-
|
|
28
|
-
@objc
|
|
29
|
-
public var title: () -> String = { "" }
|
|
30
|
-
|
|
31
|
-
@objc
|
|
32
|
-
public var warning: () -> String? = { nil }
|
|
33
|
-
|
|
34
|
-
@objc
|
|
35
|
-
public var isChecked: () -> Bool = { false }
|
|
36
|
-
|
|
37
|
-
@objc
|
|
38
|
-
public var tags: () -> [Tag] = { [] }
|
|
39
|
-
|
|
40
|
-
public func serialize() -> [String: Any] {
|
|
41
|
-
return [
|
|
42
|
-
"title": title(),
|
|
43
|
-
"warning": warning() ?? NSNull(),
|
|
44
|
-
"isChecked": isChecked(),
|
|
45
|
-
"tags": tags().map { $0.serialize() },
|
|
46
|
-
"onClickData": onClickData() ?? NSNull()
|
|
47
|
-
]
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public static var ActionID = 1
|
|
52
|
-
private let callable: DevMenuExportedFunction
|
|
53
|
-
private var items: [Item] = []
|
|
54
|
-
private let dataSourceId: String?
|
|
55
|
-
|
|
56
|
-
@objc
|
|
57
|
-
public func addItem(_ item: Item) {
|
|
58
|
-
items.append(item)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
@objc
|
|
62
|
-
public convenience init() {
|
|
63
|
-
self.init(dataSourceId: nil)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
@objc
|
|
67
|
-
public init(dataSourceId: String?) {
|
|
68
|
-
self.dataSourceId = dataSourceId
|
|
69
|
-
self.callable = DevMenuExportedFunction(withId: "expo-dev-menu.selection-list.#\(DevMenuSelectionList.ActionID)", withFunction: { _ in })
|
|
70
|
-
DevMenuSelectionList.ActionID += 1
|
|
71
|
-
super.init(type: .SelectionList)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
@objc
|
|
75
|
-
public override func serialize() -> [String: Any] {
|
|
76
|
-
var dict = super.serialize()
|
|
77
|
-
dict["items"] = items.map { $0.serialize() }
|
|
78
|
-
dict["dataSourceId"] = dataSourceId ?? NSNull()
|
|
79
|
-
dict["actionId"] = self.callable.id
|
|
80
|
-
return dict
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
@objc
|
|
84
|
-
public func addOnClick(hander: @escaping ([String: Any]?) -> Void) {
|
|
85
|
-
self.callable.function = hander
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public func registerCallable() -> DevMenuExportedCallable? {
|
|
89
|
-
return self.callable
|
|
90
|
-
}
|
|
91
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import Quick
|
|
2
|
-
import Nimble
|
|
3
|
-
|
|
4
|
-
@testable import EXDevMenuInterface
|
|
5
|
-
|
|
6
|
-
class DevMenuActionTest: QuickSpec {
|
|
7
|
-
override class func spec() {
|
|
8
|
-
it("Action should be serializable") {
|
|
9
|
-
let action = DevMenuAction(withId: "action-1", {})
|
|
10
|
-
action.isAvailable = { true }
|
|
11
|
-
action.isEnabled = { true }
|
|
12
|
-
action.label = { "action-1-label" }
|
|
13
|
-
action.detail = { "action-1-details" }
|
|
14
|
-
action.glyphName = { "action-1-glyphname" }
|
|
15
|
-
action.registerKeyCommand(input: "r", modifiers: .command)
|
|
16
|
-
|
|
17
|
-
let serilizedData = action.serialize()
|
|
18
|
-
|
|
19
|
-
expect(serilizedData["type"] as? Int).to(equal(ItemType.action.rawValue))
|
|
20
|
-
expect(serilizedData["actionId"] as? String).to(equal("action-1"))
|
|
21
|
-
expect(serilizedData["isAvailable"] as? Bool).to(beTrue())
|
|
22
|
-
expect(serilizedData["isEnabled"] as? Bool).to(beTrue())
|
|
23
|
-
expect(serilizedData["label"] as? String).to(equal("action-1-label"))
|
|
24
|
-
expect(serilizedData["detail"] as? String).to(equal("action-1-details"))
|
|
25
|
-
expect(serilizedData["glyphName"] as? String).to(equal("action-1-glyphname"))
|
|
26
|
-
|
|
27
|
-
let keyCommand = serilizedData["keyCommand"] as! [String: Any]
|
|
28
|
-
|
|
29
|
-
expect(keyCommand["input"] as? String).to(equal("r"))
|
|
30
|
-
expect(keyCommand["modifiers"] as? Int).to(equal(1 << 2))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
it("Action callable should be contain passed action") {
|
|
34
|
-
var wasCalled = false
|
|
35
|
-
let action = DevMenuAction(withId: "action-1", { wasCalled = true })
|
|
36
|
-
|
|
37
|
-
action.callable.call()
|
|
38
|
-
|
|
39
|
-
expect(wasCalled).to(beTrue())
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import Quick
|
|
2
|
-
import Nimble
|
|
3
|
-
|
|
4
|
-
@testable import EXDevMenuInterface
|
|
5
|
-
|
|
6
|
-
class DevMenuItemsContainerTest: QuickSpec {
|
|
7
|
-
override class func spec() {
|
|
8
|
-
it("should respect importance") {
|
|
9
|
-
let container = DevMenuItemsContainer()
|
|
10
|
-
|
|
11
|
-
let seeder = [("action-1", ItemImportance.lowest), ("action-2", ItemImportance.medium), ("action-3", ItemImportance.highest)]
|
|
12
|
-
|
|
13
|
-
seeder.forEach { actionDate in
|
|
14
|
-
let action = DevMenuAction(withId: actionDate.0)
|
|
15
|
-
action.label = { actionDate.0 }
|
|
16
|
-
action.importance = actionDate.1.rawValue
|
|
17
|
-
|
|
18
|
-
container.addItem(action)
|
|
19
|
-
}
|
|
20
|
-
let items = container.getRootItems()
|
|
21
|
-
|
|
22
|
-
expect(items.count).to(equal(3))
|
|
23
|
-
expect((items[0] as! DevMenuAction).label()).to(equal("action-3"))
|
|
24
|
-
expect((items[1] as! DevMenuAction).label()).to(equal("action-2"))
|
|
25
|
-
expect((items[2] as! DevMenuAction).label()).to(equal("action-1"))
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
it("should unwrap other containers") {
|
|
29
|
-
let container = DevMenuItemsContainer()
|
|
30
|
-
container.addItem(DevMenuAction(withId: "action-1"))
|
|
31
|
-
let innerContainer = DevMenuGroup()
|
|
32
|
-
innerContainer.addItem(DevMenuAction(withId: "action-2"))
|
|
33
|
-
container.addItem(innerContainer)
|
|
34
|
-
|
|
35
|
-
let items = container.getAllItems()
|
|
36
|
-
|
|
37
|
-
expect(items.count).to(equal(3))
|
|
38
|
-
expect(items[0] as? DevMenuAction).toNot(beNil())
|
|
39
|
-
expect(items[1] as? DevMenuGroup).toNot(beNil())
|
|
40
|
-
expect(items[2] as? DevMenuAction).toNot(beNil())
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
it("should serilize items") {
|
|
44
|
-
let container = DevMenuItemsContainer()
|
|
45
|
-
container.addItem(DevMenuAction(withId: "action-1"))
|
|
46
|
-
let innerContainer = DevMenuGroup()
|
|
47
|
-
innerContainer.addItem(DevMenuAction(withId: "action-2"))
|
|
48
|
-
container.addItem(innerContainer)
|
|
49
|
-
|
|
50
|
-
let items = container.serializeItems()
|
|
51
|
-
|
|
52
|
-
expect(items.count).to(equal(2))
|
|
53
|
-
expect(items[0]["type"] as? Int).to(equal(ItemType.action.rawValue))
|
|
54
|
-
expect(items[0]["actionId"] as? String).to(equal("action-1"))
|
|
55
|
-
|
|
56
|
-
expect(items[1]["type"] as? Int).to(equal(ItemType.group.rawValue))
|
|
57
|
-
|
|
58
|
-
let innerItem = (items[1]["items"] as! [[String: Any]])[0]
|
|
59
|
-
expect(innerItem["type"] as? Int).to(equal(ItemType.action.rawValue))
|
|
60
|
-
expect(innerItem["actionId"] as? String).to(equal("action-2"))
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import Quick
|
|
2
|
-
import Nimble
|
|
3
|
-
|
|
4
|
-
@testable import EXDevMenuInterface
|
|
5
|
-
|
|
6
|
-
class DevMenuLinkTest: QuickSpec {
|
|
7
|
-
override class func spec() {
|
|
8
|
-
it("Link should be serializable") {
|
|
9
|
-
let link = DevMenuLink(withTarget: "target-1")
|
|
10
|
-
link.glyphName = { "link-1-glyph" }
|
|
11
|
-
link.label = { "link-1-label" }
|
|
12
|
-
|
|
13
|
-
let serilizedData = link.serialize()
|
|
14
|
-
|
|
15
|
-
expect(serilizedData["type"] as? Int).to(equal(ItemType.link.rawValue))
|
|
16
|
-
expect(serilizedData["label"] as? String).to(equal("link-1-label"))
|
|
17
|
-
expect(serilizedData["glyphName"] as? String).to(equal("link-1-glyph"))
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import Quick
|
|
2
|
-
import Nimble
|
|
3
|
-
|
|
4
|
-
@testable import EXDevMenuInterface
|
|
5
|
-
|
|
6
|
-
class DevMenuScreenTest: QuickSpec {
|
|
7
|
-
override class func spec() {
|
|
8
|
-
it("Screen should be serializable") {
|
|
9
|
-
let screen = DevMenuScreen("screen-1")
|
|
10
|
-
|
|
11
|
-
let serilizedData = screen.serialize()
|
|
12
|
-
|
|
13
|
-
expect(serilizedData["type"] as? Int).to(equal(ItemType.screen.rawValue))
|
|
14
|
-
expect(serilizedData["screenName"] as? String).to(equal("screen-1"))
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import Quick
|
|
2
|
-
import Nimble
|
|
3
|
-
|
|
4
|
-
@testable import EXDevMenuInterface
|
|
5
|
-
|
|
6
|
-
class DevMenuSelectionListTest: QuickSpec {
|
|
7
|
-
override class func spec() {
|
|
8
|
-
it("List should be serializable") {
|
|
9
|
-
let list = DevMenuSelectionList()
|
|
10
|
-
|
|
11
|
-
let serilizedData = list.serialize()
|
|
12
|
-
|
|
13
|
-
expect(serilizedData["type"] as? Int).to(equal(ItemType.selectionList.rawValue))
|
|
14
|
-
expect(serilizedData["actionId"] as? String).toNot(beNil())
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|