expo-dev-launcher 6.1.0-canary-20251127-587bc53 → 6.1.0-canary-20251205-756eb7a

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/android/build.gradle +67 -30
  3. package/android/src/debug/AndroidManifest.xml +4 -0
  4. package/android/src/main/AndroidManifest.xml +0 -5
  5. package/app.plugin.js +1 -0
  6. package/expo-dev-launcher.podspec +2 -1
  7. package/ios/EXDevLauncherController.h +1 -1
  8. package/ios/EXDevLauncherController.m +29 -30
  9. package/ios/Errors/EXDevLauncherErrorManager.swift +23 -2
  10. package/ios/Headers/EXDevLauncherRedBoxProtocol.h +0 -2
  11. package/ios/Manifest/EXDevLauncherManifestHelper.swift +5 -2
  12. package/ios/ReactDelegateHandler/ExpoDevLauncherAppDelegateSubscriber.swift +6 -0
  13. package/ios/ReactDelegateHandler/ExpoDevLauncherReactDelegateHandler.swift +21 -1
  14. package/ios/SwiftUI/AccountSheet.swift +3 -3
  15. package/ios/SwiftUI/CrashReportView.swift +6 -4
  16. package/ios/SwiftUI/DevLauncherTabBarManager.swift +11 -2
  17. package/ios/SwiftUI/DevLauncherViewController.swift +18 -2
  18. package/ios/SwiftUI/DevLauncherViews.swift +53 -29
  19. package/ios/SwiftUI/DevServersView.swift +2 -0
  20. package/ios/SwiftUI/ErrorView.swift +2 -0
  21. package/ios/SwiftUI/SettingsTabView.swift +3 -1
  22. package/package.json +5 -4
  23. package/plugin/build/pluginConfig.d.ts +43 -0
  24. package/plugin/build/pluginConfig.js +76 -0
  25. package/plugin/build/withDevLauncher.d.ts +3 -0
  26. package/plugin/build/withDevLauncher.js +30 -0
  27. package/plugin/jest.config.js +1 -0
  28. package/plugin/src/pluginConfig.ts +121 -0
  29. package/plugin/src/withDevLauncher.ts +50 -0
  30. package/plugin/tsconfig.json +9 -0
  31. package/android/src/release/java/expo/modules/devlauncher/DevLauncherController.kt +0 -134
  32. package/android/src/release/java/expo/modules/devlauncher/launcher/DevLauncherReactHost.kt +0 -11
  33. package/android/src/release/java/expo/modules/devlauncher/launcher/DevLauncherReactNativeHost.kt +0 -16
  34. package/android/src/release/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactory.kt +0 -5
  35. /package/android/src/{main → debug}/graphql/GetBranches.graphql +0 -0
  36. /package/android/src/{main → debug}/graphql/GetUpdates.graphql +0 -0
  37. /package/android/src/{main → debug}/graphql/Me.graphql +0 -0
  38. /package/android/src/{main → debug}/graphql/schema.graphqls +0 -0
  39. /package/android/src/{main → debug}/java/com/facebook/react/devsupport/DevLauncherDevServerHelper.kt +0 -0
  40. /package/android/src/{main → debug}/java/com/facebook/react/devsupport/DevLauncherSettings.kt +0 -0
  41. /package/android/src/{main → debug}/java/com/facebook/react/devsupport/NonFinalBridgeDevSupportManager.kt +0 -0
  42. /package/android/src/{main → debug}/java/com/facebook/react/devsupport/NonFinalBridgelessDevSupportManager.kt +0 -0
  43. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherColorsHelper.kt +0 -0
  44. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherCoroutinesExtensions.kt +0 -0
  45. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherInstallationIDHelper.kt +0 -0
  46. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherMetadataHelper.kt +0 -0
  47. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherOkHttpExtensions.kt +0 -0
  48. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherReflectionExtensions.kt +0 -0
  49. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherURLHelper.kt +0 -0
  50. /package/android/src/{main → debug}/java/expo/modules/devlauncher/helpers/DevLauncherUpdatesHelper.kt +0 -0
  51. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/DevLauncherControllerInterface.kt +0 -0
  52. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/DevLauncherIntentRegistry.kt +0 -0
  53. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/DevLauncherLifecycle.kt +0 -0
  54. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/DevLauncherReactActivityDelegateSupplier.kt +0 -0
  55. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/DevLauncherRecentlyOpenedAppsRegistry.kt +0 -0
  56. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/configurators/DevLauncherExpoActivityConfigurator.kt +0 -0
  57. /package/android/src/{main/java/expo/modules/devlauncher/launcher/errors → debug/java/expo/modules/devlauncher/launcher/errors copy}/DevLauncherErrorRegistry.kt +0 -0
  58. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifestParser.kt +0 -0
  59. /package/android/src/{main → debug}/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifestTypes.kt +0 -0
  60. /package/android/src/{main → debug}/java/expo/modules/devlauncher/logs/DevLauncherRemoteLog.kt +0 -0
  61. /package/android/src/{main → debug}/java/expo/modules/devlauncher/logs/DevLauncherRemoteLogManager.kt +0 -0
  62. /package/android/src/{main → debug}/java/expo/modules/devlauncher/react/DevLauncherPackagerConnectionSettings.kt +0 -0
  63. /package/android/src/{main → debug}/java/expo/modules/devlauncher/react/activitydelegates/DevLauncherReactActivityNOPDelegate.kt +0 -0
  64. /package/android/src/{main → debug}/java/expo/modules/devlauncher/react/activitydelegates/DevLauncherReactActivityRedirectDelegate.kt +0 -0
  65. /package/android/src/{main → debug}/java/expo/modules/devlauncher/splashscreen/DevLauncherSplashScreen.kt +0 -0
  66. /package/android/src/{main → debug}/java/expo/modules/devlauncher/splashscreen/DevLauncherSplashScreenProvider.kt +0 -0
  67. /package/android/src/{main → debug}/res/drawable/check_circle.xml +0 -0
  68. /package/android/src/{main → debug}/res/drawable/chevron_right.xml +0 -0
  69. /package/android/src/{main → debug}/res/drawable/download.xml +0 -0
  70. /package/android/src/{main → debug}/res/drawable/expo_logo.xml +0 -0
  71. /package/android/src/{main → debug}/res/drawable/home.xml +0 -0
  72. /package/android/src/{main → debug}/res/drawable/log_in.xml +0 -0
  73. /package/android/src/{main → debug}/res/drawable/plus.xml +0 -0
  74. /package/android/src/{main → debug}/res/drawable/scan.xml +0 -0
  75. /package/android/src/{main → debug}/res/drawable/settings.xml +0 -0
  76. /package/android/src/{main → debug}/res/drawable/show_at_launch.xml +0 -0
  77. /package/android/src/{main → debug}/res/drawable/updates_nav.xml +0 -0
  78. /package/android/src/{main → debug}/res/drawable/user.xml +0 -0
  79. /package/android/src/{main → debug}/res/values/colors.xml +0 -0
  80. /package/android/src/{main → debug}/res/values/styles.xml +0 -0
  81. /package/android/src/{release → disableInRelease}/java/expo/modules/devlauncher/DevLauncherPackageDelegate.kt +0 -0
package/CHANGELOG.md CHANGED
@@ -10,14 +10,17 @@
10
10
  - [iOS] Add brownfield support ([#40463](https://github.com/expo/expo/pull/40463) by [@gabrieldonadel](https://github.com/gabrieldonadel))
11
11
  - [iOS] Decouple menu from dev-launcher ([#40669](https://github.com/expo/expo/pull/40669) by [@alanjhughes](https://github.com/alanjhughes))
12
12
  - [iOS] Add activity indicator when loading dev server URL. ([#40825](https://github.com/expo/expo/pull/40825) by [@alanjhughes](https://github.com/alanjhughes))
13
+ - Add initial macOS support ([#41330](https://github.com/expo/expo/pull/41330) by [@gabrieldonadel](https://github.com/gabrieldonadel))
13
14
 
14
15
  ### 🐛 Bug fixes
15
16
 
16
17
  - [Android] Fix launching apps in brownfield ([#40711](https://github.com/expo/expo/pull/40711) by [@gabrieldonadel](https://github.com/gabrieldonadel))
17
18
  - [iOS] Fix React Native dev menu not showing up in 0.83.x ([#40819](https://github.com/expo/expo/pull/40819) by [@gabrieldonadel](https://github.com/gabrieldonadel))
18
- - [iOS] Fix port scanning on pysical devices. ([#40824](https://github.com/expo/expo/pull/40824) by [@alanjhughes](https://github.com/alanjhughes))
19
19
  - [iOS] Fix RCTDevMenuConfiguration in release builds ([#40870](https://github.com/expo/expo/pull/40870) by [@gabrieldonadel](https://github.com/gabrieldonadel))
20
20
  - [iOS] Fix Safe Area being ignored on physical devices ([#41119](https://github.com/expo/expo/pull/41119) by [@betomoedano](https://github.com/betomoedano))
21
+ - Restore config plugin `launchMode` support ([#41363](https://github.com/expo/expo/pull/41363) by [@gabrieldonadel](https://github.com/gabrieldonadel))
22
+ - [Android] Prevent some debug only artifacts from being included in release builds. ([#41378](https://github.com/expo/expo/pull/41378) by [@lukmccall](https://github.com/lukmccall))
23
+ - [iOS] Fix `DevLauncherWrapperView` in SwiftUI brownfield apps ([#41431](https://github.com/expo/expo/pull/41431) by [@gabrieldonadel](https://github.com/gabrieldonadel))
21
24
 
22
25
  ### 💡 Others
23
26
 
@@ -25,6 +28,27 @@
25
28
  - [android] Make reactNativeHost optional in ReactHostWrapper ([#40085](https://github.com/expo/expo/pull/40085) by [@gabrieldonadel](https://github.com/gabrieldonadel))
26
29
  - [Android] Remove `ReactHostWrapper` ([#40295](https://github.com/expo/expo/pull/40295) by [@gabrieldonadel](https://github.com/gabrieldonadel))
27
30
  - [iOS] Remove custom `ReactNativeFactory`. ([#41084](https://github.com/expo/expo/pull/41084) by [@alanjhughes](https://github.com/alanjhughes))
31
+ - [iOS] Remove unused reactNativeFactory. ([#41286](https://github.com/expo/expo/pull/41286) by [@gabrieldonadel](https://github.com/gabrieldonadel))
32
+
33
+ ## 6.0.20 - 2025-12-05
34
+
35
+ ### 🐛 Bug fixes
36
+
37
+ - [iOS] Fix port scanning on pysical devices. ([#40824](https://github.com/expo/expo/pull/40824) by [@alanjhughes](https://github.com/alanjhughes))
38
+
39
+ ## 6.0.19 - 2025-12-04
40
+
41
+ ### 🐛 Bug fixes
42
+
43
+ - Restore config plugin `launchMode` support ([#41363](https://github.com/expo/expo/pull/41363) by [@gabrieldonadel](https://github.com/gabrieldonadel))
44
+
45
+ ## 6.0.18 - 2025-11-17
46
+
47
+ _This version does not introduce any user-facing changes._
48
+
49
+ ## 6.0.17 - 2025-11-05
50
+
51
+ _This version does not introduce any user-facing changes._
28
52
 
29
53
  ## 6.0.16 - 2025-10-21
30
54
 
@@ -15,18 +15,24 @@ apply plugin: 'org.jetbrains.kotlin.plugin.compose'
15
15
  apply plugin: 'org.jetbrains.kotlin.plugin.serialization'
16
16
  apply plugin: 'com.apollographql.apollo'
17
17
 
18
+ def configureInRelease = findProperty("expo.devlauncher.configureInRelease") == "true"
19
+ if (configureInRelease) {
20
+ println("expo-dev-launcher will be enabled in release")
21
+ }
22
+
23
+
18
24
  expoModule {
19
25
  canBePublished false
20
26
  }
21
27
 
22
28
  group = "host.exp.exponent"
23
- version = "6.1.0-canary-20251127-587bc53"
29
+ version = "6.1.0-canary-20251205-756eb7a"
24
30
 
25
31
  android {
26
32
  namespace "expo.modules.devlauncher"
27
33
  defaultConfig {
28
34
  versionCode 9
29
- versionName "6.1.0-canary-20251127-587bc53"
35
+ versionName "6.1.0-canary-20251205-756eb7a"
30
36
  }
31
37
 
32
38
  buildTypes {
@@ -44,6 +50,17 @@ android {
44
50
  debugOptimized {
45
51
  setRoot 'src/debug'
46
52
  }
53
+
54
+
55
+ release {
56
+ if (configureInRelease) {
57
+ java.srcDir 'src/debug/java'
58
+ res.srcDir 'src/debug/res'
59
+ } else {
60
+ java.srcDir 'src/disableInRelease/java'
61
+ res.srcDir 'src/disableInRelease/res'
62
+ }
63
+ }
47
64
  }
48
65
 
49
66
  buildFeatures {
@@ -55,12 +72,25 @@ android {
55
72
  apollo {
56
73
  service("service") {
57
74
  packageName.set("expo.modules.devlauncher")
75
+ srcDir("src/debug/graphql")
76
+
58
77
  introspection {
59
78
  endpointUrl.set("https://api.expo.dev/graphql")
60
- schemaFile.set(file("src/main/graphql/schema.graphqls"))
79
+ schemaFile.set(file("src/debug/graphql/schema.graphqls"))
80
+ }
81
+
82
+ outputDir.set(project.layout.buildDirectory.dir("generated/apollo"))
83
+ outputDirConnection {
84
+ connectToKotlinSourceSet("debug")
85
+ connectToKotlinSourceSet("debugOptimized")
86
+
87
+ if (configureInRelease) {
88
+ connectToKotlinSourceSet("release")
89
+ }
61
90
  }
62
91
  }
63
92
  }
93
+
64
94
  repositories {
65
95
  // ref: https://www.baeldung.com/maven-local-repository
66
96
  mavenLocal()
@@ -76,50 +106,57 @@ repositories {
76
106
  }
77
107
 
78
108
  dependencies {
79
- implementation project(":expo-dev-menu-interface")
80
- implementation project(":expo-manifests")
81
- implementation project(":expo-updates-interface")
82
- implementation project(":expo-dev-menu")
109
+ def debugOnly = { notation ->
110
+ //noinspection DependencyNotationArgument
111
+ debugImplementation notation
112
+ //noinspection DependencyNotationArgument
113
+ debugOptimizedImplementation notation
114
+ //noinspection DependencyNotationArgument
115
+ testImplementation notation
116
+
117
+ if (configureInRelease) {
118
+ //noinspection DependencyNotationArgument
119
+ releaseImplementation notation
120
+ }
121
+ }
83
122
 
84
123
  implementation 'com.facebook.react:react-android'
85
- implementation 'com.facebook.soloader:soloader:0.11.0'
86
124
 
87
- implementation 'commons-io:commons-io:2.6'
125
+ debugOnly project(":expo-dev-menu-interface")
126
+ debugOnly project(":expo-manifests")
127
+ debugOnly project(":expo-updates-interface")
128
+ debugOnly project(":expo-dev-menu")
88
129
 
89
- implementation 'com.squareup.okhttp3:okhttp:4.9.2'
90
- implementation 'com.google.code.gson:gson:2.13.2'
130
+ debugOnly 'commons-io:commons-io:2.6'
91
131
 
92
- // Fixes
93
- // Cannot access 'androidx....' which is a supertype of 'expo.modules.devmenu.DevMenuActivity'.
94
- // Check your module classpath for missing or conflicting dependencies
95
- api "androidx.appcompat:appcompat:1.7.1"
96
- api "androidx.lifecycle:lifecycle-extensions:2.2.0"
132
+ debugOnly 'com.squareup.okhttp3:okhttp:4.9.2'
133
+ debugOnly 'com.google.code.gson:gson:2.13.2'
97
134
 
98
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
99
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
100
- implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
135
+ debugOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
136
+ debugOnly("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
137
+ debugOnly "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
101
138
 
102
139
  def composeVersion = "1.9.0"
103
140
 
104
- implementation "androidx.compose.foundation:foundation-android:$composeVersion"
105
- implementation "androidx.compose.ui:ui:$composeVersion"
106
- implementation "androidx.compose.ui:ui-tooling:$composeVersion"
107
- implementation "androidx.navigation:navigation-compose:2.9.4"
108
- implementation "com.google.android.gms:play-services-code-scanner:16.1.0"
109
- implementation "com.google.mlkit:barcode-scanning:17.3.0"
141
+ // it's needed by the compose compiler plugin, but it won't leak to the app module
142
+ releaseCompileOnly "androidx.compose.foundation:foundation-android:$composeVersion"
143
+ debugOnly "androidx.compose.foundation:foundation-android:$composeVersion"
144
+ debugOnly "androidx.compose.ui:ui:$composeVersion"
145
+ debugOnly "androidx.compose.ui:ui-tooling:$composeVersion"
146
+ debugOnly "androidx.navigation:navigation-compose:2.9.4"
147
+ debugOnly "com.google.android.gms:play-services-code-scanner:16.1.0"
148
+ debugOnly "com.google.mlkit:barcode-scanning:17.3.0"
110
149
 
111
- implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
150
+ debugOnly("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
112
151
 
113
- implementation("com.apollographql.apollo:apollo-runtime:4.3.1")
152
+ debugOnly("com.apollographql.apollo:apollo-runtime:4.3.1")
114
153
 
115
- implementation("com.composables:core:1.43.1")
154
+ debugOnly("com.composables:core:1.43.1")
116
155
 
117
156
  testImplementation 'androidx.test:core:1.7.0'
118
157
  testImplementation 'androidx.test:core-ktx:1.7.0'
119
158
  testImplementation "com.google.truth:truth:1.4.5"
120
159
  testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.2'
121
- testImplementation "io.insert-koin:koin-test"
122
- testImplementation "io.insert-koin:koin-test-junit4"
123
160
  testImplementation 'io.mockk:mockk:1.12.3'
124
161
  testImplementation "org.robolectric:robolectric:4.16"
125
162
  }
@@ -1,6 +1,10 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
2
 
3
3
  <application>
4
+ <meta-data
5
+ android:name="com.google.mlkit.vision.DEPENDENCIES"
6
+ android:value="barcode_ui"/>
7
+
4
8
  <activity
5
9
  android:name="expo.modules.devlauncher.launcher.DevLauncherActivity"
6
10
  android:exported="true"
@@ -1,7 +1,2 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
- <application>
3
- <meta-data
4
- android:name="com.google.mlkit.vision.DEPENDENCIES"
5
- android:value="barcode_ui"/>
6
- </application>
7
2
  </manifest>
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./plugin/build/withDevLauncher');
@@ -21,7 +21,8 @@ Pod::Spec.new do |s|
21
21
  s.homepage = package['homepage']
22
22
  s.platforms = {
23
23
  :ios => '15.1',
24
- :tvos => '15.1'
24
+ :tvos => '15.1',
25
+ :osx => '13.0'
25
26
  }
26
27
  s.swift_version = '5.2'
27
28
  s.source = { :git => 'https://github.com/github_account/expo-development-client.git', :tag => "#{s.version}" }
@@ -1,7 +1,7 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
  #import <React/RCTBridgeDelegate.h>
3
3
 
4
- #import <UIKit/UIKit.h>
4
+ #import <ExpoModulesCore/Platform.h>
5
5
 
6
6
  // When `use_frameworks!` is used, the generated Swift header is inside modules.
7
7
  // Otherwise, it's available only locally with double-quoted imports.
@@ -52,7 +52,6 @@
52
52
  @property (nonatomic, strong) EXDevLauncherErrorManager *errorManager;
53
53
  @property (nonatomic, strong) EXDevLauncherInstallationIDHelper *installationIDHelper;
54
54
  @property (nonatomic, strong, nullable) EXDevLauncherNetworkInterceptor *networkInterceptor;
55
- @property (nonatomic, strong) RCTReactNativeFactory *reactNativeFactory;
56
55
  @property (nonatomic, strong) DevLauncherViewController *devLauncherViewController;
57
56
  @property (nonatomic, strong) NSURL *lastOpenedAppUrl;
58
57
  @property (nonatomic, strong) DevLauncherDevMenuDelegate *devMenuDelegate;
@@ -83,7 +82,6 @@
83
82
  self.shouldPreferUpdatesInterfaceSourceUrl = NO;
84
83
 
85
84
  self.dependencyProvider = [RCTAppDependencyProvider new];
86
- self.reactNativeFactory = [[RCTReactNativeFactory alloc] initWithDelegate:self releaseLevel:[self getReactNativeReleaseLevel]];
87
85
  self.devMenuDelegate = [[DevLauncherDevMenuDelegate alloc] initWithController:self];
88
86
  [[DevMenuManager shared] setDelegate:self.devMenuDelegate];
89
87
  }
@@ -102,6 +100,7 @@
102
100
  return [_recentlyOpenedAppsRegistry clearRegistry];
103
101
  }
104
102
 
103
+ #if !TARGET_OS_OSX
105
104
  - (NSDictionary<UIApplicationLaunchOptionsKey, NSObject*> *)getLaunchOptions;
106
105
  {
107
106
  NSMutableDictionary *launchOptions = [self.launchOptions ?: @{} mutableCopy];
@@ -127,6 +126,20 @@
127
126
 
128
127
  return launchOptions;
129
128
  }
129
+ #else
130
+ - (NSDictionary *)getLaunchOptions
131
+ {
132
+ NSMutableDictionary *launchOptions = [self.launchOptions ?: @{} mutableCopy];
133
+ NSURL *deepLink = [self.pendingDeepLinkRegistry consumePendingDeepLink];
134
+
135
+ if (deepLink) {
136
+ // Passes pending deep link to initialURL if any
137
+ launchOptions[NSApplicationLaunchUserNotificationKey] = deepLink;
138
+ }
139
+
140
+ return launchOptions;
141
+ }
142
+ #endif
130
143
 
131
144
  - (EXManifestsManifest *)appManifest
132
145
  {
@@ -202,11 +215,13 @@
202
215
 
203
216
  self.networkInterceptor = nil;
204
217
 
218
+ #if !TARGET_OS_OSX
205
219
  [self _applyUserInterfaceStyle:UIUserInterfaceStyleUnspecified];
206
-
220
+ #endif
221
+
207
222
  // Reset app react host
208
223
  [self.delegate destroyReactInstance];
209
-
224
+
210
225
  if (_devLauncherViewController != nil) {
211
226
  [_devLauncherViewController resetHostingController];
212
227
  }
@@ -251,12 +266,6 @@
251
266
  }
252
267
 
253
268
  self.pendingDeepLinkRegistry.pendingDeepLink = url;
254
-
255
- // cold boot -- need to initialize the dev launcher app RN app to handle the link
256
- if (_reactNativeFactory.rootViewFactory.reactHost == nil) {
257
- [self navigateToLauncher];
258
- }
259
-
260
269
  return true;
261
270
  }
262
271
 
@@ -449,6 +458,7 @@
449
458
  self.networkInterceptor = [[EXDevLauncherNetworkInterceptor alloc] initWithBundleUrl:bundleUrl];
450
459
  #endif
451
460
 
461
+ #if !TARGET_OS_OSX
452
462
  UIUserInterfaceStyle userInterfaceStyle = [EXDevLauncherManifestHelper exportManifestUserInterfaceStyle:manifest.userInterfaceStyle];
453
463
  [self _applyUserInterfaceStyle:userInterfaceStyle];
454
464
 
@@ -459,13 +469,16 @@
459
469
  if (userInterfaceStyle != UIUserInterfaceStyleUnspecified) {
460
470
  UITraitCollection.currentTraitCollection = [self.window.rootViewController.traitCollection copy];
461
471
  }
472
+ #endif
462
473
 
463
474
  [self.delegate devLauncherController:self didStartWithSuccess:YES];
464
475
 
465
476
  [self setDevMenuAppBridge];
466
477
 
467
478
  if (backgroundColor) {
479
+ #if !TARGET_OS_OSX
468
480
  self.window.rootViewController.view.backgroundColor = backgroundColor;
481
+ #endif
469
482
  self.window.backgroundColor = backgroundColor;
470
483
  }
471
484
  });
@@ -480,6 +493,7 @@
480
493
  return [_appBridge isValid];
481
494
  }
482
495
 
496
+ #if !TARGET_OS_OSX
483
497
  /**
484
498
  * Temporary `expo-splash-screen` fix.
485
499
  *
@@ -510,6 +524,7 @@
510
524
  // change RN appearance
511
525
  RCTOverrideAppearancePreference(colorSchema);
512
526
  }
527
+ #endif
513
528
 
514
529
  -(NSDictionary *)getBuildInfo
515
530
  {
@@ -575,27 +590,11 @@
575
590
  return appVersion;
576
591
  }
577
592
 
578
- -(RCTReleaseLevel)getReactNativeReleaseLevel
579
- {
580
- // @TODO: Read this value from the main react-native factory instance on 0.82
581
- NSString *releaseLevelString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"ReactNativeReleaseLevel"];
582
- RCTReleaseLevel releaseLevel = Stable;
583
- if ([releaseLevelString isKindOfClass:[NSString class]]) {
584
- NSString *lower = [releaseLevelString lowercaseString];
585
- if ([lower isEqualToString:@"canary"]) {
586
- releaseLevel = Canary;
587
- } else if ([lower isEqualToString:@"experimental"]) {
588
- releaseLevel = Experimental;
589
- } else if ([lower isEqualToString:@"stable"]) {
590
- releaseLevel = Stable;
591
- }
592
- }
593
-
594
- return releaseLevel;
595
- }
596
-
597
593
  -(void)copyToClipboard:(NSString *)content {
598
- #if !TARGET_OS_TV
594
+ #if TARGET_OS_OSX
595
+ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
596
+ [pasteboard setString:(content ?: @"") forType:NSPasteboardTypeString];
597
+ #elif !TARGET_OS_TV
599
598
  UIPasteboard *clipboard = [UIPasteboard generalPasteboard];
600
599
  clipboard.string = (content ?: @"");
601
600
  #endif
@@ -2,7 +2,8 @@
2
2
 
3
3
  import Foundation
4
4
  import SwiftUI
5
- import UIKit
5
+ import ExpoModulesCore
6
+
6
7
 
7
8
  @objc
8
9
  public class EXDevLauncherErrorManager: NSObject {
@@ -17,7 +18,12 @@ public class EXDevLauncherErrorManager: NSObject {
17
18
 
18
19
  @objc
19
20
  public func showError(_ error: EXDevLauncherAppError) {
20
- if let launcherVC = controller?.currentWindow()?.rootViewController as? DevLauncherViewController {
21
+ #if !os(macOS)
22
+ let launcherVC = controller?.currentWindow()?.rootViewController
23
+ #else
24
+ let launcherVC = controller?.currentWindow()?.contentViewController
25
+ #endif
26
+ if let launcherVC = launcherVC as? DevLauncherViewController {
21
27
  DispatchQueue.main.async {
22
28
  launcherVC.viewModel.showError(error)
23
29
  }
@@ -25,10 +31,17 @@ public class EXDevLauncherErrorManager: NSObject {
25
31
  }
26
32
 
27
33
  DispatchQueue.main.async { [weak self] in
34
+ #if !os(macOS)
28
35
  guard let window = self?.controller?.currentWindow(),
29
36
  let rootVC = window.rootViewController else {
30
37
  return
31
38
  }
39
+ #else
40
+ guard let window = self?.controller?.currentWindow(),
41
+ let rootVC = window.contentViewController else {
42
+ return
43
+ }
44
+ #endif
32
45
 
33
46
  self?.dismissCurrentErrorView()
34
47
 
@@ -52,9 +65,15 @@ public class EXDevLauncherErrorManager: NSObject {
52
65
 
53
66
  rootVC.addChild(hostingController)
54
67
  hostingController.view.frame = rootVC.view.bounds
68
+ #if !os(macOS)
55
69
  hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
70
+ #else
71
+ hostingController.view.autoresizingMask = [.width, .height]
72
+ #endif
56
73
  rootVC.view.addSubview(hostingController.view)
74
+ #if !os(macOS)
57
75
  hostingController.didMove(toParent: rootVC)
76
+ #endif
58
77
  }
59
78
  }
60
79
 
@@ -63,7 +82,9 @@ public class EXDevLauncherErrorManager: NSObject {
63
82
  return
64
83
  }
65
84
 
85
+ #if !os(macOS)
66
86
  vc.willMove(toParent: nil)
87
+ #endif
67
88
  vc.view.removeFromSuperview()
68
89
  vc.removeFromParent()
69
90
  currentErrorViewController = nil
@@ -1,7 +1,5 @@
1
1
  // Copied `React/RCTRedBox.h` and turn into a protocol.
2
2
 
3
- #import <UIKit/UIKit.h>
4
-
5
3
  #import <React/RCTRedBox.h>
6
4
  #import <React/RCTJSStackFrame.h>
7
5
 
@@ -1,10 +1,12 @@
1
1
  // Copyright 2015-present 650 Industries. All rights reserved.
2
2
 
3
+ #if os(iOS) || os(tvOS)
3
4
  import UIKit
5
+ #endif
4
6
 
5
7
  @objc
6
8
  public class EXDevLauncherManifestHelper: NSObject {
7
- #if !os(tvOS)
9
+ #if !os(tvOS) && !os(macOS)
8
10
  private static func defaultOrientationForOrientationMask(_ orientationMask: UIInterfaceOrientationMask) -> UIInterfaceOrientation {
9
11
  if orientationMask.contains(.all) {
10
12
  return UIInterfaceOrientation.unknown
@@ -60,7 +62,7 @@ public class EXDevLauncherManifestHelper: NSObject {
60
62
  alpha: 1.0
61
63
  )
62
64
  }
63
-
65
+ #if !os(macOS)
64
66
  @objc
65
67
  public static func exportManifestUserInterfaceStyle(_ userInterfaceStyle: String?) -> UIUserInterfaceStyle {
66
68
  switch userInterfaceStyle {
@@ -72,4 +74,5 @@ public class EXDevLauncherManifestHelper: NSObject {
72
74
  return .unspecified
73
75
  }
74
76
  }
77
+ #endif
75
78
  }
@@ -3,7 +3,13 @@
3
3
  import ExpoModulesCore
4
4
 
5
5
  public class ExpoDevLauncherAppDelegateSubscriber: ExpoAppDelegateSubscriber {
6
+ #if !os(macOS)
6
7
  public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
7
8
  return EXDevLauncherController.sharedInstance().onDeepLink(url, options: options)
8
9
  }
10
+ #else
11
+ public func application(_ app: NSApplication, open urls: [URL]) {
12
+ EXDevLauncherController.sharedInstance().onDeepLink(urls[0], options: [:])
13
+ }
14
+ #endif
9
15
  }
@@ -7,6 +7,7 @@ import React
7
7
  private class DevLauncherWrapperView: UIView {
8
8
  weak var devLauncherViewController: UIViewController?
9
9
 
10
+ #if !os(macOS)
10
11
  override func didMoveToWindow() {
11
12
  super.didMoveToWindow()
12
13
 
@@ -16,7 +17,8 @@ private class DevLauncherWrapperView: UIView {
16
17
  return
17
18
  }
18
19
 
19
- if devLauncherViewController.parent != rootViewController {
20
+ let isSwiftUIController = NSStringFromClass(type(of: rootViewController)).contains("UIHostingController")
21
+ if !isSwiftUIController && devLauncherViewController.parent != rootViewController {
20
22
  rootViewController.addChild(devLauncherViewController)
21
23
  devLauncherViewController.didMove(toParent: rootViewController)
22
24
  devLauncherViewController.view.setNeedsLayout()
@@ -31,6 +33,7 @@ private class DevLauncherWrapperView: UIView {
31
33
  devLauncherViewController?.removeFromParent()
32
34
  }
33
35
  }
36
+ #endif
34
37
  }
35
38
 
36
39
  @objc
@@ -129,7 +132,24 @@ public class ExpoDevLauncherReactDelegateHandler: ExpoReactDelegateHandler, EXDe
129
132
  guard let rootViewController = rootViewController ?? self.reactDelegate?.createRootViewController() else {
130
133
  fatalError("Invalid rootViewController returned from ExpoReactDelegate")
131
134
  }
135
+ #if os(macOS)
136
+ let newViewController = UIViewController()
137
+ newViewController.view = rootView
138
+
139
+ rootViewController.view.subviews.forEach { $0.removeFromSuperview() }
140
+ rootViewController.addChild(newViewController)
141
+ rootViewController.view.addSubview(newViewController.view)
142
+
143
+ newViewController.view.translatesAutoresizingMaskIntoConstraints = false
144
+ NSLayoutConstraint.activate([
145
+ newViewController.view.topAnchor.constraint(equalTo: rootViewController.view.topAnchor),
146
+ newViewController.view.leadingAnchor.constraint(equalTo: rootViewController.view.leadingAnchor),
147
+ newViewController.view.trailingAnchor.constraint(equalTo: rootViewController.view.trailingAnchor),
148
+ newViewController.view.bottomAnchor.constraint(equalTo: rootViewController.view.bottomAnchor)
149
+ ])
150
+ #else
132
151
  rootViewController.view = rootView
152
+ #endif
133
153
  // it is purposeful that we don't clean up saved properties here, because we may initialize
134
154
  // several React instances over a single app lifetime and we want them all to have the same
135
155
  // initial properties
@@ -29,7 +29,7 @@ struct AccountSheet: View {
29
29
  .padding(.horizontal, 16)
30
30
  }
31
31
  .frame(maxWidth: .infinity, maxHeight: .infinity)
32
- #if !os(tvOS)
32
+ #if !os(tvOS) && !os(macOS)
33
33
  .background(Color(.systemGroupedBackground))
34
34
  #endif
35
35
  }
@@ -179,7 +179,7 @@ struct AccountSheet: View {
179
179
  }
180
180
  .padding(.horizontal, 16)
181
181
  .padding(.vertical, 12)
182
- #if !os(tvOS)
182
+ #if !os(tvOS) && !os(macOS)
183
183
  .background(Color(.systemBackground))
184
184
  #endif
185
185
  }
@@ -211,7 +211,7 @@ struct AccountSheet: View {
211
211
  .scaledToFill()
212
212
  } placeholder: {
213
213
  Circle()
214
- #if !os(tvOS)
214
+ #if !os(tvOS) && !os(macOS)
215
215
  .fill(Color(.systemGray5))
216
216
  #endif
217
217
  .overlay(
@@ -29,22 +29,24 @@ struct CrashReportView: View {
29
29
  .foregroundColor(.black)
30
30
  .frame(maxWidth: .infinity)
31
31
  .padding()
32
- #if !os(tvOS)
32
+ #if !os(tvOS) && !os(macOS)
33
33
  .background(Color(.systemGray5))
34
34
  #endif
35
35
  .cornerRadius(8)
36
36
  }
37
37
  .padding()
38
38
  }
39
- #if !os(tvOS)
39
+ #if !os(tvOS) && !os(macOS)
40
40
  .background(Color(.systemBackground))
41
41
  #endif
42
+ #if !os(macOS)
42
43
  .navigationBarHidden(true)
44
+ #endif
43
45
  }
44
46
 
45
47
  private func copyToClipboard() {
46
48
  let crashReport = generateJSONFromCrash()
47
- #if !os(tvOS)
49
+ #if !os(tvOS) && !os(macOS)
48
50
  UIPasteboard.general.string = crashReport
49
51
 
50
52
  showCopiedMessage = true
@@ -131,7 +133,7 @@ struct CrashReportView: View {
131
133
  .frame(maxWidth: .infinity, alignment: .leading)
132
134
  }
133
135
  .frame(maxHeight: 200)
134
- #if !os(tvOS)
136
+ #if !os(tvOS) && !os(macOS)
135
137
  .background(Color(.secondarySystemGroupedBackground))
136
138
  #endif
137
139
  .cornerRadius(8)
@@ -2,12 +2,12 @@
2
2
 
3
3
  class DevLauncherTabBarManager {
4
4
  static let shared = DevLauncherTabBarManager()
5
+ private init() {}
5
6
 
7
+ #if os(iOS) || os(tvOS)
6
8
  private var originalStandardAppearance: UITabBarAppearance?
7
9
  private var originalScrollEdgeAppearance: UITabBarAppearance?
8
10
 
9
- private init() {}
10
-
11
11
  func setCustomAppearance() {
12
12
  if originalStandardAppearance == nil {
13
13
  originalStandardAppearance = UITabBar.appearance().standardAppearance
@@ -29,4 +29,13 @@ class DevLauncherTabBarManager {
29
29
  UITabBar.appearance().scrollEdgeAppearance = originalScrollEdgeAppearance
30
30
  }
31
31
  }
32
+ #else
33
+ func setCustomAppearance() {
34
+ // No-op on macOS
35
+ }
36
+
37
+ func restoreOriginalAppearance() {
38
+ // No-op on macOS
39
+ }
40
+ #endif
32
41
  }