expo-dev-menu-interface 0.3.4 → 0.5.0

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.
@@ -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
@@ -4,11 +4,11 @@ Interface for `expo-dev-menu`.
4
4
 
5
5
  # Installation in managed Expo projects
6
6
 
7
- For managed [managed](https://docs.expo.io/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects &mdash; it is likely to be included in an upcoming Expo SDK release.
7
+ For [managed](https://docs.expo.io/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects &mdash; it is likely to be included in an upcoming Expo SDK release.
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 `react-native-unimodules` package](https://github.com/expo/expo/tree/master/packages/react-native-unimodules) before continuing.
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
 
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.3.4'
6
+ version = '0.5.0'
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.3.4'
60
+ versionName '0.5.0'
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
  }
@@ -14,7 +14,7 @@ interface DevMenuExpoApiClientInterface {
14
14
  fun isLoggedIn(): Boolean
15
15
  fun setSessionSecret(newSessionSecret: String?)
16
16
  suspend fun queryMyProjects(options: DevMenuGraphQLOptions = DevMenuGraphQLOptions()): okhttp3.Response
17
- suspend fun queryDevSessions(): okhttp3.Response
17
+ suspend fun queryDevSessions(deviceID: String?): okhttp3.Response
18
18
  suspend fun queryUpdateChannels(
19
19
  appId: String,
20
20
  options: DevMenuGraphQLOptions = DevMenuGraphQLOptions()
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "expo-dev-menu-interface",
3
+ "platforms": ["ios", "android"]
4
+ }
@@ -32,7 +32,7 @@ public protocol DevMenuExpoApiClientProtocol {
32
32
  func setSessionSecret(_ sessionSecret: String?)
33
33
 
34
34
  @objc
35
- func queryDevSessionsAsync(_ completionHandler: @escaping HTTPCompletionHandler)
35
+ func queryDevSessionsAsync(_ installationID: String?, completionHandler: @escaping HTTPCompletionHandler)
36
36
 
37
37
  @objc
38
38
  func queryUpdateChannels(
@@ -48,6 +48,11 @@ open class DevMenuAction: DevMenuScreenItem, DevMenuCallableProvider {
48
48
  self.callable.action = action
49
49
  }
50
50
 
51
+ @objc
52
+ public convenience init(withId id: String, _ action: @escaping () -> ()) {
53
+ self.init(withId: id, action: action)
54
+ }
55
+
51
56
  public func registerCallable() -> DevMenuExportedCallable? {
52
57
  return self.callable
53
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
+ }
@@ -1,6 +1,6 @@
1
1
  require 'json'
2
2
 
3
- package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
3
+ package = JSON.parse(File.read(File.join(__dir__, '../package.json')))
4
4
 
5
5
  Pod::Spec.new do |s|
6
6
  s.name = 'expo-dev-menu-interface'
@@ -13,11 +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.source_files = 'ios/**/*.{h,m,swift}'
17
- s.preserve_paths = 'ios/**/*.{h,m,swift}'
16
+ s.static_framework = true
17
+ s.source_files = '**/*.{h,m,swift}'
18
+ s.preserve_paths = '**/*.{h,m,swift}'
19
+ s.exclude_files = '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" }
25
+
26
+ s.test_spec 'Tests' do |test_spec|
27
+ test_spec.platform = :ios, '12.0'
28
+ test_spec.source_files = 'Tests/**/*.{h,m,swift}'
29
+ test_spec.dependency 'Quick'
30
+ test_spec.dependency 'Nimble'
31
+ end
23
32
  end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-dev-menu-interface",
3
- "version": "0.3.4",
3
+ "version": "0.5.0",
4
4
  "description": "Interface for expo-dev-menu",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -21,6 +21,9 @@
21
21
  },
22
22
  "author": "650 Industries, Inc.",
23
23
  "license": "MIT",
24
- "homepage": "https://docs.expo.io",
25
- "gitHead": "b588610e02acf18f338a3187882e139fd031a9b6"
24
+ "homepage": "https://docs.expo.dev",
25
+ "peerDependencies": {
26
+ "expo": "*"
27
+ },
28
+ "gitHead": "db3c974468338f22450238dc273b343a76e2c347"
26
29
  }
@@ -1,13 +0,0 @@
1
- module.exports = {
2
- dependency: {
3
- platforms: {
4
- ios: {
5
- /**
6
- * We need this property to trick `react-native-cli`. Normally, this tool looks for the XCode project.
7
- * We can generate it using `XcodeGen` but we don't want to add the project file to this library.
8
- */
9
- project: 'ios/EXDevMenuInterface.xcodeproj/project.pbxproj',
10
- },
11
- },
12
- },
13
- };