expo-dev-menu-interface 0.3.3 → 0.4.2
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/Info-generated.plist +22 -0
- package/README.md +1 -1
- package/android/build.gradle +3 -2
- package/android/src/main/java/expo/interfaces/devmenu/DevMenuManagerInterface.kt +8 -0
- package/expo-dev-menu-interface.podspec +8 -1
- package/ios/DevMenuBridgeProtocol.swift +2 -0
- package/ios/DevMenuDelegateProtocol.swift +3 -0
- package/ios/DevMenuExtensionProtocol.swift +2 -0
- package/ios/DevMenuManagerProtocol.swift +2 -0
- package/ios/DevMenuManagerProviderProtocol.swift +2 -0
- package/ios/DevMenuUIResponderExtensionProtocol.swift +3 -0
- package/ios/ExpoApiClient/DevMenuEASUpdates.swift +2 -0
- package/ios/ExpoApiClient/DevMenuExpoApiClientProtocol.swift +2 -0
- package/ios/MenuItems/DevMenuAction.swift +8 -0
- package/ios/MenuItems/DevMenuDataSource.swift +2 -0
- package/ios/MenuItems/DevMenuExportedCallable.swift +3 -0
- package/ios/MenuItems/DevMenuGroup.swift +2 -0
- package/ios/MenuItems/DevMenuItem.swift +2 -0
- package/ios/MenuItems/DevMenuItemsContainer.swift +2 -0
- package/ios/MenuItems/DevMenuItemsContainerProtocol.swift +2 -0
- package/ios/MenuItems/DevMenuLink.swift +2 -0
- package/ios/MenuItems/DevMenuScreen.swift +2 -0
- package/ios/MenuItems/DevMenuScreenItem.swift +2 -0
- package/ios/MenuItems/DevMenuSelectionList.swift +2 -0
- package/ios/Tests/DevMenuActionTest.swift +42 -0
- package/ios/Tests/DevMenuEASUpdatesTest.swift +86 -0
- package/ios/Tests/DevMenuItemsContainerTest.swift +63 -0
- package/ios/Tests/DevMenuLinkTest.swift +20 -0
- package/ios/Tests/DevMenuScreenTest.swift +17 -0
- package/ios/Tests/DevMenuSelectionListTest.swift +17 -0
- package/package.json +2 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>expo.dev.menu.interface</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>EXDevMenuInterface</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>FMWK</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>0.3.2</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>0</string>
|
|
21
|
+
</dict>
|
|
22
|
+
</plist>
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ For managed [managed](https://docs.expo.io/versions/latest/introduction/managed-
|
|
|
8
8
|
|
|
9
9
|
# Installation in bare React Native projects
|
|
10
10
|
|
|
11
|
-
For bare React Native projects, you must ensure that you have [installed and configured the `
|
|
11
|
+
For bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing.
|
|
12
12
|
|
|
13
13
|
### Add the package to your npm dependencies
|
|
14
14
|
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '0.
|
|
6
|
+
version = '0.4.2'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
// Simple helper that allows the root project to override versions declared by this library.
|
|
@@ -57,7 +57,7 @@ android {
|
|
|
57
57
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
58
58
|
targetSdkVersion safeExtGet("targetSdkVersion", 30)
|
|
59
59
|
versionCode 6
|
|
60
|
-
versionName '0.
|
|
60
|
+
versionName '0.4.2'
|
|
61
61
|
}
|
|
62
62
|
lintOptions {
|
|
63
63
|
abortOnError false
|
|
@@ -71,4 +71,5 @@ dependencies {
|
|
|
71
71
|
implementation 'com.squareup.okhttp3:okhttp:3.14.9'
|
|
72
72
|
|
|
73
73
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '1.4.21')}"
|
|
74
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
|
|
74
75
|
}
|
|
@@ -8,6 +8,7 @@ import com.facebook.react.ReactNativeHost
|
|
|
8
8
|
import com.facebook.react.bridge.ReadableMap
|
|
9
9
|
import expo.interfaces.devmenu.expoapi.DevMenuExpoApiClientInterface
|
|
10
10
|
import expo.interfaces.devmenu.items.DevMenuDataSourceItem
|
|
11
|
+
import kotlinx.coroutines.CoroutineScope
|
|
11
12
|
|
|
12
13
|
interface DevMenuManagerInterface {
|
|
13
14
|
/**
|
|
@@ -110,5 +111,12 @@ interface DevMenuManagerInterface {
|
|
|
110
111
|
*/
|
|
111
112
|
fun isInitialized(): Boolean
|
|
112
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Whether to automatically show the dev menu on app load. Defaults to true if not set.
|
|
116
|
+
*/
|
|
117
|
+
fun setCanLaunchDevMenuOnStart(shouldAutoLaunch: Boolean)
|
|
118
|
+
|
|
113
119
|
suspend fun fetchDataSource(id: String): List<DevMenuDataSourceItem>
|
|
120
|
+
|
|
121
|
+
val coroutineScope: CoroutineScope
|
|
114
122
|
}
|
|
@@ -13,13 +13,20 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.platform = :ios, '11.0'
|
|
14
14
|
s.swift_version = '5.2'
|
|
15
15
|
s.source = { git: 'https://github.com/expo/expo.git' }
|
|
16
|
+
s.static_framework = true
|
|
16
17
|
s.source_files = 'ios/**/*.{h,m,swift}'
|
|
17
18
|
s.preserve_paths = 'ios/**/*.{h,m,swift}'
|
|
19
|
+
s.exclude_files = ['ios/Tests/**/*.{h,m,swift}']
|
|
18
20
|
s.requires_arc = true
|
|
19
21
|
s.header_dir = 'EXDevMenuInterface'
|
|
20
22
|
|
|
21
23
|
# Swift/Objective-C compatibility
|
|
22
24
|
s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" }
|
|
23
25
|
|
|
24
|
-
s.
|
|
26
|
+
s.test_spec 'Tests' do |test_spec|
|
|
27
|
+
test_spec.platform = :ios, '12.0'
|
|
28
|
+
test_spec.source_files = 'ios/Tests/**/*.{h,m,swift}'
|
|
29
|
+
test_spec.dependency 'Quick'
|
|
30
|
+
test_spec.dependency 'Nimble'
|
|
31
|
+
end
|
|
25
32
|
end
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
+
import Foundation
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
3
6
|
@objc
|
|
4
7
|
open class DevMenuAction: DevMenuScreenItem, DevMenuCallableProvider {
|
|
5
8
|
@objc
|
|
@@ -45,6 +48,11 @@ open class DevMenuAction: DevMenuScreenItem, DevMenuCallableProvider {
|
|
|
45
48
|
self.callable.action = action
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
@objc
|
|
52
|
+
public convenience init(withId id: String, _ action: @escaping () -> ()) {
|
|
53
|
+
self.init(withId: id, action: action)
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
public func registerCallable() -> DevMenuExportedCallable? {
|
|
49
57
|
return self.callable
|
|
50
58
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Quick
|
|
2
|
+
import Nimble
|
|
3
|
+
|
|
4
|
+
@testable import EXDevMenuInterface
|
|
5
|
+
|
|
6
|
+
class DevMenuActionTest: QuickSpec {
|
|
7
|
+
override 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
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import Quick
|
|
2
|
+
import Nimble
|
|
3
|
+
|
|
4
|
+
@testable import EXDevMenuInterface
|
|
5
|
+
|
|
6
|
+
class DevMenuEASUpdatesTest: QuickSpec {
|
|
7
|
+
override func spec() {
|
|
8
|
+
it("Channel constructor should populate all fields") {
|
|
9
|
+
let seeder = [
|
|
10
|
+
"id": "1234",
|
|
11
|
+
"name": "channel-1",
|
|
12
|
+
"createdAt": "1635508863",
|
|
13
|
+
"updatedAt": "1635508873"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
let channel = DevMenuEASUpdates.Channel(dictionary: seeder)
|
|
17
|
+
|
|
18
|
+
expect(channel.id).to(equal("1234"))
|
|
19
|
+
expect(channel.name).to(equal("channel-1"))
|
|
20
|
+
expect(channel.createdAt).to(equal("1635508863"))
|
|
21
|
+
expect(channel.updatedAt).to(equal("1635508873"))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
it("Update constructor should populate all fields") {
|
|
25
|
+
let seeder = [
|
|
26
|
+
"id": "1234",
|
|
27
|
+
"message": "update-1",
|
|
28
|
+
"platform": "ios",
|
|
29
|
+
"runtimeVersion": "1",
|
|
30
|
+
"createdAt": "1635508863",
|
|
31
|
+
"updatedAt": "1635508873"
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
let update = DevMenuEASUpdates.Update(dictionary: seeder)
|
|
35
|
+
|
|
36
|
+
expect(update.id).to(equal("1234"))
|
|
37
|
+
expect(update.message).to(equal("update-1"))
|
|
38
|
+
expect(update.platform).to(equal("ios"))
|
|
39
|
+
expect(update.runtimeVersion).to(equal("1"))
|
|
40
|
+
expect(update.createdAt).to(equal("1635508863"))
|
|
41
|
+
expect(update.updatedAt).to(equal("1635508873"))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
it("Branch constructor should populate all fields") {
|
|
45
|
+
let seeder = [
|
|
46
|
+
"id": "1",
|
|
47
|
+
"updates": [
|
|
48
|
+
[
|
|
49
|
+
"id": "1234",
|
|
50
|
+
"message": "update-1",
|
|
51
|
+
"platform": "ios",
|
|
52
|
+
"runtimeVersion": "1",
|
|
53
|
+
"createdAt": "1635508863",
|
|
54
|
+
"updatedAt": "1635508873"
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
"id": "9876",
|
|
58
|
+
"message": "update-2",
|
|
59
|
+
"platform": "ios",
|
|
60
|
+
"runtimeVersion": "2",
|
|
61
|
+
"createdAt": "1635508863",
|
|
62
|
+
"updatedAt": "1635508873"
|
|
63
|
+
]
|
|
64
|
+
]
|
|
65
|
+
] as [String : Any]
|
|
66
|
+
|
|
67
|
+
let branch = DevMenuEASUpdates.Branch(dictionary: seeder)
|
|
68
|
+
let update1 = branch.updates[0]
|
|
69
|
+
let update2 = branch.updates[1]
|
|
70
|
+
|
|
71
|
+
expect(branch.id).to(equal("1"))
|
|
72
|
+
expect(update1.id).to(equal("1234"))
|
|
73
|
+
expect(update1.message).to(equal("update-1"))
|
|
74
|
+
expect(update1.platform).to(equal("ios"))
|
|
75
|
+
expect(update1.runtimeVersion).to(equal("1"))
|
|
76
|
+
expect(update1.createdAt).to(equal("1635508863"))
|
|
77
|
+
expect(update1.updatedAt).to(equal("1635508873"))
|
|
78
|
+
expect(update2.id).to(equal("9876"))
|
|
79
|
+
expect(update2.message).to(equal("update-2"))
|
|
80
|
+
expect(update2.platform).to(equal("ios"))
|
|
81
|
+
expect(update2.runtimeVersion).to(equal("2"))
|
|
82
|
+
expect(update2.createdAt).to(equal("1635508863"))
|
|
83
|
+
expect(update2.updatedAt).to(equal("1635508873"))
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Quick
|
|
2
|
+
import Nimble
|
|
3
|
+
|
|
4
|
+
@testable import EXDevMenuInterface
|
|
5
|
+
|
|
6
|
+
class DevMenuItemsContainerTest: QuickSpec {
|
|
7
|
+
override 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
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Quick
|
|
2
|
+
import Nimble
|
|
3
|
+
|
|
4
|
+
@testable import EXDevMenuInterface
|
|
5
|
+
|
|
6
|
+
class DevMenuLinkTest: QuickSpec {
|
|
7
|
+
override 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
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Quick
|
|
2
|
+
import Nimble
|
|
3
|
+
|
|
4
|
+
@testable import EXDevMenuInterface
|
|
5
|
+
|
|
6
|
+
class DevMenuScreenTest: QuickSpec {
|
|
7
|
+
override 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
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Quick
|
|
2
|
+
import Nimble
|
|
3
|
+
|
|
4
|
+
@testable import EXDevMenuInterface
|
|
5
|
+
|
|
6
|
+
class DevMenuSelectionListTest: QuickSpec {
|
|
7
|
+
override 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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-dev-menu-interface",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Interface for expo-dev-menu",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"author": "650 Industries, Inc.",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"homepage": "https://docs.expo.io",
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "7bb3c874946fd9b20e25601b155309080b08b5cb"
|
|
26
26
|
}
|