expo-modules-core 2.0.0-preview.1 → 2.0.0-preview.10

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 (48) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/ExpoModulesCore.podspec +15 -2
  3. package/android/build.gradle +3 -3
  4. package/android/src/main/java/expo/modules/adapters/react/apploader/RNHeadlessAppLoader.kt +68 -21
  5. package/android/src/main/java/expo/modules/adapters/react/permissions/PermissionsService.kt +14 -5
  6. package/android/src/main/java/expo/modules/adapters/react/services/EventEmitterModule.java +2 -0
  7. package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +5 -0
  8. package/android/src/main/java/expo/modules/core/ModulePriorities.kt +1 -1
  9. package/android/src/main/java/expo/modules/core/ModuleRegistry.java +1 -0
  10. package/android/src/main/java/expo/modules/core/arguments/ReadableArguments.java +1 -0
  11. package/android/src/main/java/expo/modules/interfaces/taskManager/TaskServiceProviderHelper.kt +41 -0
  12. package/android/src/main/java/expo/modules/interfaces/taskManager/TaskServiceProviderInterface.java +18 -0
  13. package/android/src/main/java/expo/modules/kotlin/Promise.kt +6 -6
  14. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +2 -2
  15. package/android/src/main/java/expo/modules/kotlin/devtools/ExpoRequestCdpInterceptor.kt +4 -3
  16. package/android/src/main/java/expo/modules/kotlin/exception/CommonExceptions.kt +16 -0
  17. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +0 -22
  18. package/android/src/main/java/expo/modules/kotlin/modules/ModuleUtils.kt +25 -0
  19. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +15 -0
  20. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObject.kt +1 -0
  21. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +1 -0
  22. package/android/src/main/java/expo/modules/kotlin/views/ExpoView.kt +37 -1
  23. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +2 -14
  24. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +2 -14
  25. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +11 -12
  26. package/build/ts-declarations/global.d.ts +17 -16
  27. package/build/ts-declarations/global.d.ts.map +1 -1
  28. package/ios/Core/{Convertibles → Arguments}/Either.swift +29 -12
  29. package/ios/Core/DynamicTypes/DynamicEitherType.swift +47 -0
  30. package/ios/Core/DynamicTypes/DynamicOptionalType.swift +1 -1
  31. package/ios/Core/Modules/CoreModule.swift +2 -2
  32. package/ios/Core/Protocols/AnyExpoView.swift +6 -0
  33. package/ios/Core/SharedObjects/SharedRef.swift +1 -1
  34. package/ios/Core/Views/ComponentData.swift +1 -1
  35. package/ios/Core/Views/ExpoView.swift +9 -0
  36. package/ios/Core/Views/SwiftUI/SwiftUIHostingView.swift +28 -8
  37. package/ios/Core/Views/SwiftUI/SwiftUIViewDefinition.swift +1 -1
  38. package/ios/DevTools/ExpoRequestCdpInterceptor.swift +1 -1
  39. package/ios/DevTools/ExpoRequestInterceptorProtocol.swift +11 -0
  40. package/ios/DevTools/URLAuthenticationChallengeForwardSender.swift +33 -0
  41. package/ios/DevTools/URLSessionSessionDelegateProxy.swift +15 -0
  42. package/ios/Tests/DynamicEitherTypeSpec.swift +93 -0
  43. package/ios/Tests/DynamicTypeSpec.swift +18 -0
  44. package/ios/Tests/EitherSpec.swift +0 -44
  45. package/package.json +2 -2
  46. package/src/ts-declarations/global.ts +22 -20
  47. package/ios/Interfaces/BarcodeScanner/EXBarcodeScannerInterface.h +0 -22
  48. package/ios/Interfaces/BarcodeScanner/EXBarcodeScannerProviderInterface.h +0 -9
package/CHANGELOG.md CHANGED
@@ -10,6 +10,67 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 2.0.0-preview.10 — 2024-11-07
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - [iOS] Fixed broken self-signed connections from network inspector. ([#32670](https://github.com/expo/expo/pull/32670) by [@kudo](https://github.com/kudo))
18
+
19
+ ## 2.0.0-preview.9 — 2024-10-31
20
+
21
+ ### 💡 Others
22
+
23
+ - [Android] Fix `ClassCastException` in headless app loader under the old architecture. ([#32390](https://github.com/expo/expo/pull/32390) by [@robertying](https://github.com/robertying))
24
+
25
+ ## 2.0.0-preview.8 — 2024-10-31
26
+
27
+ ### 🛠 Breaking changes
28
+
29
+ - Remove expo barcode scanner interface. ([#32198](https://github.com/expo/expo/pull/32198) by [@aleqsio](https://github.com/aleqsio))
30
+
31
+ ### 💡 Others
32
+
33
+ - [android] Added helper for looking up TaskService instance used by expo-task-manager ([#32300](https://github.com/expo/expo/pull/32300) by [@chrfalch](https://github.com/chrfalch))
34
+ - Made TypeScript declaration for `process` an interface. ([#32464](https://github.com/expo/expo/pull/32464) by [@tsapeta](https://github.com/tsapeta))
35
+
36
+ ## 2.0.0-preview.7 — 2024-10-29
37
+
38
+ ### 💡 Others
39
+
40
+ - [Android] Added `shouldUseAndroidLayout` flag to `ExpoView`. ([#32446](https://github.com/expo/expo/pull/32446) by [@lukmccall](https://github.com/lukmccall))
41
+
42
+ ## 2.0.0-preview.6 — 2024-10-29
43
+
44
+ _This version does not introduce any user-facing changes._
45
+
46
+ ## 2.0.0-preview.5 — 2024-10-28
47
+
48
+ ### 🐛 Bug fixes
49
+
50
+ - Fixed updating props on SwiftUI views on the New Architecture. ([#32381](https://github.com/expo/expo/pull/32381) by [@tsapeta](https://github.com/tsapeta))
51
+ - Fixed build error when `use_frameworks!`. ([#32358](https://github.com/expo/expo/pull/32358) by [@kudo](https://github.com/kudo))
52
+
53
+ ## 2.0.0-preview.4 — 2024-10-25
54
+
55
+ ### 💡 Others
56
+
57
+ - Added a new dynamic type dedicated for Either types. ([#32328](https://github.com/expo/expo/pull/32328) by [@tsapeta](https://github.com/tsapeta))
58
+
59
+ ## 2.0.0-preview.3 — 2024-10-24
60
+
61
+ _This version does not introduce any user-facing changes._
62
+
63
+ ## 2.0.0-preview.2 — 2024-10-24
64
+
65
+ ### 🐛 Bug fixes
66
+
67
+ - [iOS] Fix optionals conversion. ([#32239](https://github.com/expo/expo/pull/32239) by [@aleqsio](https://github.com/aleqsio))
68
+ - Fixed retain cycle for `ExpoRequestCdpInterceptor`. ([#32289](https://github.com/expo/expo/pull/32289) by [@kudo](https://github.com/kudo))
69
+
70
+ ### 💡 Others
71
+
72
+ - [android] Add enum event support to OnStartObserving and OnStopObserving. ([#32251](https://github.com/expo/expo/pull/32251), [#32287](https://github.com/expo/expo/pull/32287) by [@wschurman](https://github.com/wschurman))
73
+
13
74
  ## 2.0.0-preview.1 — 2024-10-22
14
75
 
15
76
  ### 🐛 Bug fixes
@@ -56,6 +117,7 @@
56
117
 
57
118
  ### 🐛 Bug fixes
58
119
 
120
+ - [Android] Fixed `RNHeadlessAppLoader` class for New Architecture support. ([#32146](https://github.com/expo/expo/pull/32146) by [@chrfalch](https://github.com/chrfalch))
59
121
  - [iOS] Fix using enums as optional arguments. ([#32147](https://github.com/expo/expo/pull/32147) by [@aleqsio](https://github.com/aleqsio))
60
122
  - [Android] Change JS return type for kotlin `null` to be `null` instead of `undefined`. ([#31301](https://github.com/expo/expo/pull/31301) by [@aleqsio](https://github.com/aleqsio))
61
123
  - [iOS] Swift `Enumerable`s did not correctly convert to JS values. ([#30191](https://github.com/expo/expo/pull/30191) by [@vonovak](https://github.com/vonovak))
@@ -47,19 +47,32 @@ Pod::Spec.new do |s|
47
47
  s.static_framework = true
48
48
  s.header_dir = 'ExpoModulesCore'
49
49
 
50
+ header_search_paths = []
51
+ if ENV['USE_FRAMEWORKS']
52
+ header_search_paths.concat([
53
+ # [begin] transitive dependencies of React-RCTAppDelegate that are not defined modules
54
+ '"${PODS_CONFIGURATION_BUILD_DIR}/React-RuntimeApple/React_RuntimeApple.framework/Headers"',
55
+ '"${PODS_CONFIGURATION_BUILD_DIR}/React-RuntimeCore/React_RuntimeCore.framework/Headers"',
56
+ '"${PODS_CONFIGURATION_BUILD_DIR}/React-jserrorhandler/React_jserrorhandler.framework/Headers"',
57
+ '"${PODS_CONFIGURATION_BUILD_DIR}/React-runtimescheduler/React_runtimescheduler.framework/Headers"',
58
+ '"${PODS_CONFIGURATION_BUILD_DIR}/React-performancetimeline/React_performancetimeline.framework/Headers"',
59
+ '"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererconsistency/React_rendererconsistency.framework/Headers"',
60
+ # [end] transitive dependencies of React-RCTAppDelegate that are not defined modules
61
+ ])
62
+ end
50
63
  # Swift/Objective-C compatibility
51
64
  s.pod_target_xcconfig = {
52
65
  'USE_HEADERMAP' => 'YES',
53
66
  'DEFINES_MODULE' => 'YES',
54
67
  'CLANG_CXX_LANGUAGE_STANDARD' => 'c++20',
55
68
  'SWIFT_COMPILATION_MODE' => 'wholemodule',
56
- 'OTHER_SWIFT_FLAGS' => "$(inherited) #{new_arch_enabled ? new_arch_compiler_flags : ''}"
69
+ 'OTHER_SWIFT_FLAGS' => "$(inherited) #{new_arch_enabled ? new_arch_compiler_flags : ''}",
70
+ 'HEADER_SEARCH_PATHS' => header_search_paths.join(' '),
57
71
  }
58
72
  s.user_target_xcconfig = {
59
73
  "HEADER_SEARCH_PATHS" => [
60
74
  '"${PODS_CONFIGURATION_BUILD_DIR}/ExpoModulesCore/Swift Compatibility Header"',
61
75
  '"$(PODS_ROOT)/Headers/Private/Yoga"', # Expo.h -> ExpoModulesCore-umbrella.h -> Fabric ViewProps.h -> Private Yoga headers
62
-
63
76
  ],
64
77
  }
65
78
 
@@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
3
3
  apply plugin: 'com.android.library'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '2.0.0-preview.1'
6
+ version = '2.0.0-preview.10'
7
7
 
8
8
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
9
9
  apply from: expoModulesCorePlugin
@@ -67,7 +67,7 @@ android {
67
67
  defaultConfig {
68
68
  consumerProguardFiles 'proguard-rules.pro'
69
69
  versionCode 1
70
- versionName "2.0.0-preview.1"
70
+ versionName "2.0.0-preview.10"
71
71
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
72
72
 
73
73
  testInstrumentationRunner "expo.modules.TestRunner"
@@ -198,7 +198,7 @@ dependencies {
198
198
 
199
199
  if (shouldTurnWarningsIntoErrors) {
200
200
  tasks.withType(JavaCompile) configureEach {
201
- options.compilerArgs << "-Werror" << "-Xlint:all"
201
+ options.compilerArgs << "-Werror" << "-Xlint:all" << '-Xlint:-serial' << '-Xlint:-rawtypes'
202
202
  }
203
203
  tasks.withType(KotlinCompile) configureEach {
204
204
  compilerOptions.allWarningsAsErrors = true
@@ -1,16 +1,18 @@
1
1
  package expo.modules.adapters.react.apploader
2
2
 
3
+ import android.annotation.SuppressLint
3
4
  import android.content.Context
4
5
  import com.facebook.react.ReactApplication
5
6
  import com.facebook.react.ReactInstanceEventListener
6
7
  import com.facebook.react.ReactInstanceManager
7
8
  import com.facebook.react.bridge.ReactContext
8
9
  import com.facebook.react.common.LifecycleState
10
+ import expo.modules.BuildConfig
9
11
  import expo.modules.apploader.HeadlessAppLoader
10
12
  import expo.modules.core.interfaces.Consumer
11
13
  import expo.modules.core.interfaces.DoNotStrip
12
14
 
13
- private val appRecords: MutableMap<String, ReactInstanceManager> = mutableMapOf()
15
+ private val appRecords: MutableMap<String, ReactContext> = mutableMapOf()
14
16
 
15
17
  class RNHeadlessAppLoader @DoNotStrip constructor(private val context: Context) : HeadlessAppLoader {
16
18
 
@@ -22,16 +24,35 @@ class RNHeadlessAppLoader @DoNotStrip constructor(private val context: Context)
22
24
  }
23
25
 
24
26
  if (context.applicationContext is ReactApplication) {
25
- val reactInstanceManager = (context.applicationContext as ReactApplication).reactNativeHost.reactInstanceManager
26
27
  if (!appRecords.containsKey(params.appScopeKey)) {
27
- reactInstanceManager.addReactInstanceEventListener(object : ReactInstanceEventListener {
28
- override fun onReactContextInitialized(context: ReactContext) {
29
- HeadlessAppLoaderNotifier.notifyAppLoaded(params.appScopeKey)
30
- callback?.apply(true)
31
- }
32
- })
33
- appRecords[params.appScopeKey] = reactInstanceManager
34
- if (!reactInstanceManager.hasStartedCreatingInitialContext()) {
28
+ // In old arch reactHost will be null
29
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
30
+ // New architecture
31
+ val reactHost = (context.applicationContext as ReactApplication).reactHost ?: throw IllegalStateException("Your application does not have a valid reactHost")
32
+ reactHost.addReactInstanceEventListener(
33
+ object : ReactInstanceEventListener {
34
+ override fun onReactContextInitialized(context: ReactContext) {
35
+ reactHost.removeReactInstanceEventListener(this)
36
+ HeadlessAppLoaderNotifier.notifyAppLoaded(params.appScopeKey)
37
+ appRecords[params.appScopeKey] = context
38
+ callback?.apply(true)
39
+ }
40
+ }
41
+ )
42
+ reactHost.start()
43
+ } else {
44
+ // Old architecture
45
+ val reactInstanceManager = (context.applicationContext as ReactApplication).reactNativeHost.reactInstanceManager
46
+ reactInstanceManager.addReactInstanceEventListener(
47
+ object : ReactInstanceEventListener {
48
+ override fun onReactContextInitialized(context: ReactContext) {
49
+ HeadlessAppLoaderNotifier.notifyAppLoaded(params.appScopeKey)
50
+ reactInstanceManager.removeReactInstanceEventListener(this)
51
+ appRecords[params.appScopeKey] = context
52
+ callback?.apply(true)
53
+ }
54
+ }
55
+ )
35
56
  reactInstanceManager.createReactContextInBackground()
36
57
  }
37
58
  } else {
@@ -42,18 +63,34 @@ class RNHeadlessAppLoader @DoNotStrip constructor(private val context: Context)
42
63
  }
43
64
  }
44
65
 
66
+ @SuppressLint("VisibleForTests")
45
67
  override fun invalidateApp(appScopeKey: String?): Boolean {
46
68
  return if (appRecords.containsKey(appScopeKey) && appRecords[appScopeKey] != null) {
47
- val appRecord: ReactInstanceManager = appRecords[appScopeKey]!!
48
- android.os.Handler(context.mainLooper).post {
49
- // Only destroy the `ReactInstanceManager` if it does not bind with an Activity.
50
- // And The Activity would take over the ownership of `ReactInstanceManager`.
51
- // This case happens when a user clicks a background task triggered notification immediately.
52
- if (appRecord.lifecycleState == LifecycleState.BEFORE_CREATE) {
53
- appRecord.destroy()
69
+ val reactContext = appRecords[appScopeKey] ?: return false
70
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
71
+ // New architecture
72
+ val reactHost = (reactContext.applicationContext as ReactApplication).reactHost ?: throw IllegalStateException("Your application does not have a valid reactHost")
73
+ android.os.Handler(reactContext.mainLooper).post {
74
+ reactHost.destroy("Closing headless task app", null)
75
+ HeadlessAppLoaderNotifier.notifyAppDestroyed(appScopeKey)
76
+ appRecords.remove(appScopeKey)
77
+ }
78
+ } else {
79
+ // Old architecture
80
+ val reactNativeHost = (reactContext.applicationContext as ReactApplication).reactNativeHost
81
+ if (reactNativeHost.hasInstance()) {
82
+ val reactInstanceManager: ReactInstanceManager = reactNativeHost.reactInstanceManager
83
+ android.os.Handler(reactContext.mainLooper).post {
84
+ // Only destroy the `ReactInstanceManager` if it does not bind with an Activity.
85
+ // And The Activity would take over the ownership of `ReactInstanceManager`.
86
+ // This case happens when a user clicks a background task triggered notification immediately.
87
+ if (reactInstanceManager.lifecycleState == LifecycleState.BEFORE_CREATE) {
88
+ reactInstanceManager.destroy()
89
+ }
90
+ HeadlessAppLoaderNotifier.notifyAppDestroyed(appScopeKey)
91
+ appRecords.remove(appScopeKey)
92
+ }
54
93
  }
55
- HeadlessAppLoaderNotifier.notifyAppDestroyed(appScopeKey)
56
- appRecords.remove(appScopeKey)
57
94
  }
58
95
  true
59
96
  } else {
@@ -61,8 +98,18 @@ class RNHeadlessAppLoader @DoNotStrip constructor(private val context: Context)
61
98
  }
62
99
  }
63
100
 
64
- override fun isRunning(appScopeKey: String?): Boolean =
65
- appRecords.contains(appScopeKey) && appRecords[appScopeKey]!!.hasStartedCreatingInitialContext()
101
+ override fun isRunning(appScopeKey: String?): Boolean {
102
+ val reactContext = appRecords[appScopeKey] ?: return false
103
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
104
+ // New architecture - We can return true since the fact that we have a reactContext
105
+ // means that we've already called start on the reactHost
106
+ return true
107
+ } else {
108
+ // Old architecture
109
+ val reactNativeHost = (reactContext.applicationContext as ReactApplication).reactNativeHost
110
+ return reactNativeHost.reactInstanceManager.hasStartedCreatingInitialContext()
111
+ }
112
+ }
66
113
 
67
114
  //endregion HeadlessAppLoader
68
115
  }
@@ -13,7 +13,6 @@ import androidx.core.content.ContextCompat
13
13
  import com.facebook.react.modules.core.PermissionAwareActivity
14
14
  import com.facebook.react.modules.core.PermissionListener
15
15
  import expo.modules.core.ModuleRegistry
16
- import expo.modules.core.Promise
17
16
  import expo.modules.core.interfaces.ActivityProvider
18
17
  import expo.modules.core.interfaces.InternalModule
19
18
  import expo.modules.core.interfaces.LifecycleEventListener
@@ -59,7 +58,12 @@ open class PermissionsService(val context: Context) : InternalModule, Permission
59
58
  mAskedPermissionsCache = context.applicationContext.getSharedPreferences(PREFERENCE_FILENAME, Context.MODE_PRIVATE)
60
59
  }
61
60
 
62
- override fun getPermissionsWithPromise(promise: Promise, vararg permissions: String) {
61
+ override fun getPermissionsWithPromise(
62
+ promise:
63
+ @Suppress("DEPRECATION")
64
+ expo.modules.core.Promise,
65
+ vararg permissions: String
66
+ ) {
63
67
  getPermissions(
64
68
  PermissionsResponseListener { permissionsMap: MutableMap<String, PermissionsResponse> ->
65
69
  val areAllGranted = permissionsMap.all { (_, response) -> response.status == PermissionsStatus.GRANTED }
@@ -86,7 +90,12 @@ open class PermissionsService(val context: Context) : InternalModule, Permission
86
90
  )
87
91
  }
88
92
 
89
- override fun askForPermissionsWithPromise(promise: Promise, vararg permissions: String) {
93
+ override fun askForPermissionsWithPromise(
94
+ promise:
95
+ @Suppress("DEPRECATION")
96
+ expo.modules.core.Promise,
97
+ vararg permissions: String
98
+ ) {
90
99
  askForPermissions(
91
100
  PermissionsResponseListener {
92
101
  getPermissionsWithPromise(promise, *permissions)
@@ -165,7 +174,7 @@ open class PermissionsService(val context: Context) : InternalModule, Permission
165
174
  return requestedPermissions!!.contains(permission)
166
175
  }
167
176
  return false
168
- } catch (e: PackageManager.NameNotFoundException) {
177
+ } catch (_: PackageManager.NameNotFoundException) {
169
178
  return false
170
179
  }
171
180
  }
@@ -206,7 +215,7 @@ open class PermissionsService(val context: Context) : InternalModule, Permission
206
215
  private fun canAskAgain(permission: String): Boolean {
207
216
  return mActivityProvider?.currentActivity?.let {
208
217
  ActivityCompat.shouldShowRequestPermissionRationale(it, permission)
209
- } ?: false
218
+ } == true
210
219
  }
211
220
 
212
221
  private fun parseNativeResult(permissionsString: Array<out String>, grantResults: IntArray): Map<String, PermissionsResponse> {
@@ -35,6 +35,7 @@ public class EventEmitterModule implements EventEmitter, InternalModule {
35
35
  }
36
36
 
37
37
  @Override
38
+ @SuppressWarnings("deprecation")
38
39
  public void emit(final int viewId, final String eventName, final Bundle eventBody) {
39
40
  final EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(mReactContext, viewId);
40
41
  dispatcher.dispatchEvent(new com.facebook.react.uimanager.events.Event(viewId) {
@@ -65,6 +66,7 @@ public class EventEmitterModule implements EventEmitter, InternalModule {
65
66
  return Collections.singletonList((Class) EventEmitter.class);
66
67
  }
67
68
 
69
+ @SuppressWarnings("deprecation")
68
70
  private static com.facebook.react.uimanager.events.Event getReactEventFromEvent(final int viewId, final Event event) {
69
71
  return new com.facebook.react.uimanager.events.Event(viewId) {
70
72
  @Override
@@ -70,6 +70,7 @@ public class UIManagerModuleWrapper implements
70
70
  }
71
71
 
72
72
  @Override
73
+ @SuppressWarnings("deprecation")
73
74
  public <T> void addUIBlock(final int tag, final UIBlock<T> block, final Class<T> tClass) {
74
75
  UIBlockInterface uiBlock = new UIBlockInterface() {
75
76
  @Override
@@ -105,6 +106,7 @@ public class UIManagerModuleWrapper implements
105
106
  }
106
107
 
107
108
  @Override
109
+ @SuppressWarnings("deprecation")
108
110
  public void addUIBlock(final GroupUIBlock block) {
109
111
  UIBlockInterface uiBlock = new UIBlockInterface() {
110
112
  @Override
@@ -141,6 +143,7 @@ public class UIManagerModuleWrapper implements
141
143
 
142
144
  @Nullable
143
145
  @Override
146
+ @SuppressWarnings("deprecation")
144
147
  public View resolveView(int viewTag) {
145
148
  final com.facebook.react.bridge.UIManager uiManager = UIManagerHelper.getUIManagerForReactTag(getContext(), viewTag);
146
149
  if (uiManager == null) {
@@ -263,6 +266,7 @@ public class UIManagerModuleWrapper implements
263
266
  }
264
267
 
265
268
  @androidx.annotation.OptIn(markerClass = FrameworkAPI.class)
269
+ @SuppressWarnings("deprecation")
266
270
  public CallInvokerHolderImpl getJSCallInvokerHolder() {
267
271
  return (CallInvokerHolderImpl) mReactContext.getCatalystInstance().getJSCallInvokerHolder();
268
272
  }
@@ -273,5 +277,6 @@ public class UIManagerModuleWrapper implements
273
277
  }
274
278
  }
275
279
 
280
+ @SuppressWarnings("deprecation")
276
281
  interface UIBlockInterface extends com.facebook.react.uimanager.UIBlock, com.facebook.react.fabric.interop.UIBlock {
277
282
  }
@@ -20,7 +20,7 @@ object ModulePriorities {
20
20
  // {key} to {value}
21
21
  // key: full qualified class name
22
22
  // value: priority value, the higher value takes precedence
23
- "expo.modules.splashscreen.SplashScreenPackage" to 11,
23
+ "host.exp.exponent.experience.splashscreen.legacy.SplashScreenPackage" to 11,
24
24
  "expo.modules.updates.UpdatesPackage" to 10
25
25
  )
26
26
  }
@@ -40,6 +40,7 @@ public class ModuleRegistry {
40
40
  return (T) mInternalModulesMap.get(interfaceClass);
41
41
  }
42
42
 
43
+ @SuppressWarnings("unchecked")
43
44
  public <T> T getSingletonModule(String singletonName, Class<T> singletonClass) {
44
45
  return (T) mSingletonModulesMap.get(singletonName);
45
46
  }
@@ -63,6 +63,7 @@ public interface ReadableArguments {
63
63
 
64
64
  int size();
65
65
 
66
+ @SuppressWarnings("unchecked")
66
67
  default Bundle toBundle() {
67
68
  Bundle bundle = new Bundle();
68
69
  for (String key : keys()) {
@@ -0,0 +1,41 @@
1
+ package expo.modules.interfaces.taskManager
2
+
3
+ import android.content.Context
4
+ import expo.modules.core.ModulePriorities
5
+ import expo.modules.core.interfaces.DoNotStrip
6
+ import expo.modules.core.interfaces.Package
7
+
8
+ @DoNotStrip
9
+ object TaskServiceProviderHelper {
10
+ /**
11
+ Uses reflection to look through the current list of packages and attempts to find
12
+ one that provides a TaskServiceInterface implementation.
13
+ @param context Provide the application context (context.getApplicationContext())
14
+ @return A implementation of the TaskServiceInterface it a package offers it
15
+ */
16
+ @DoNotStrip
17
+ fun getTaskServiceImpl(context: Context): TaskServiceInterface? {
18
+ // Use reflection to get the packages list from ExpoModulesPackageList without
19
+ // creating the reactInstanceManager. ExpoModulesPackageList is generated by
20
+ // autolinking and should safely be callable in this way - we already have a
21
+ // few other places in our code where it is called like this.
22
+ val expoModules: Class<*>? = try {
23
+ Class.forName("expo.modules.ExpoModulesPackageList")
24
+ } catch (e: ClassNotFoundException) {
25
+ // Handle the exception, e.g., log it or fallback to a default behavior
26
+ return null
27
+ }
28
+ val getPackageList = expoModules?.getMethod("getPackageList") ?: return null
29
+
30
+ // Invoke and get the list of packages
31
+ val result = getPackageList.invoke(null) as? List<*> ?: return null
32
+ val packages = result.filterIsInstance<Package>()
33
+ .sortedByDescending { ModulePriorities.get(it::class.qualifiedName) }
34
+
35
+ // Check if any of the packages are providing a task manager implementation
36
+ return packages
37
+ .filterIsInstance<TaskServiceProviderInterface>()
38
+ .firstOrNull()
39
+ ?.getTaskServiceImpl(context)
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ package expo.modules.interfaces.taskManager;
2
+
3
+ import android.content.Context;
4
+
5
+ import expo.modules.core.interfaces.Package;
6
+
7
+ /**
8
+ * Interface defining a package that provides a TaskServiceInterface implementation.
9
+ * This is utilized when an app is launched in the background without an activity.
10
+ * It enables running expo-task-manager JavaScript tasks in the background via the HeadlessAppLoader.
11
+ */
12
+ public interface TaskServiceProviderInterface extends Package {
13
+ /**
14
+ * @param context Current application context
15
+ * @return A task service implementation that can be provided without having setup the whole app
16
+ */
17
+ TaskServiceInterface getTaskServiceImpl(Context context);
18
+ }
@@ -46,15 +46,15 @@ fun Promise.toBridgePromise(): com.facebook.react.bridge.Promise {
46
46
  }
47
47
 
48
48
  override fun reject(code: String, message: String?) {
49
- expoPromise.reject(code ?: unknownCode, message, null)
49
+ expoPromise.reject(code, message, null)
50
50
  }
51
51
 
52
52
  override fun reject(code: String, throwable: Throwable?) {
53
- expoPromise.reject(code ?: unknownCode, null, throwable)
53
+ expoPromise.reject(code, null, throwable)
54
54
  }
55
55
 
56
56
  override fun reject(code: String, message: String?, throwable: Throwable?) {
57
- expoPromise.reject(code ?: unknownCode, message, throwable)
57
+ expoPromise.reject(code, message, throwable)
58
58
  }
59
59
 
60
60
  override fun reject(throwable: Throwable) {
@@ -66,15 +66,15 @@ fun Promise.toBridgePromise(): com.facebook.react.bridge.Promise {
66
66
  }
67
67
 
68
68
  override fun reject(code: String, userInfo: WritableMap) {
69
- expoPromise.reject(code ?: unknownCode, null, null)
69
+ expoPromise.reject(code, null, null)
70
70
  }
71
71
 
72
72
  override fun reject(code: String, throwable: Throwable?, userInfo: WritableMap) {
73
- expoPromise.reject(code ?: unknownCode, null, throwable)
73
+ expoPromise.reject(code, null, throwable)
74
74
  }
75
75
 
76
76
  override fun reject(code: String, message: String?, userInfo: WritableMap) {
77
- expoPromise.reject(code ?: unknownCode, message, null)
77
+ expoPromise.reject(code, message, null)
78
78
  }
79
79
 
80
80
  override fun reject(code: String?, message: String?, throwable: Throwable?, userInfo: WritableMap?) {
@@ -32,10 +32,10 @@ class ClassComponentBuilder<SharedObjectType : Any>(
32
32
 
33
33
  if (eventsDefinition != null && isSharedObject) {
34
34
  listOf("__expo_onStartListeningToEvent" to SharedObject::onStartListeningToEvent, "__expo_onStopListeningToEvent" to SharedObject::onStopListeningToEvent)
35
- .forEach { (name, function) ->
35
+ .forEach { (name, listener) ->
36
36
  SyncFunctionComponent(name, arrayOf(ownerType, toAnyType<String>()), toReturnType<Unit>()) { (self, eventName) ->
37
37
  enforceType<SharedObject, String>(self, eventName)
38
- function.invoke(self, eventName)
38
+ listener.invoke(self, eventName)
39
39
  }.also { function ->
40
40
  function.enumerable(false)
41
41
  syncFunctions[name] = function
@@ -14,6 +14,7 @@ import kotlinx.coroutines.launch
14
14
  import okhttp3.Request
15
15
  import okhttp3.Response
16
16
  import okhttp3.ResponseBody
17
+ import java.lang.ref.WeakReference
17
18
  import java.math.BigDecimal
18
19
  import java.math.RoundingMode
19
20
 
@@ -22,18 +23,18 @@ import java.math.RoundingMode
22
23
  * dispatch CDP (Chrome DevTools Protocol: https://chromedevtools.github.io/devtools-protocol/) events.
23
24
  */
24
25
  object ExpoRequestCdpInterceptor : ExpoNetworkInspectOkHttpInterceptorsDelegate {
25
- private var delegate: Delegate? = null
26
+ private var delegate: WeakReference<Delegate?> = WeakReference(null)
26
27
  internal var coroutineScope = CoroutineScope(Dispatchers.Default)
27
28
 
28
29
  fun setDelegate(delegate: Delegate?) {
29
30
  coroutineScope.launch {
30
- this@ExpoRequestCdpInterceptor.delegate = delegate
31
+ this@ExpoRequestCdpInterceptor.delegate = WeakReference(delegate)
31
32
  }
32
33
  }
33
34
 
34
35
  private fun dispatchEvent(event: Event) {
35
36
  coroutineScope.launch {
36
- this@ExpoRequestCdpInterceptor.delegate?.dispatch(event.toJson())
37
+ this@ExpoRequestCdpInterceptor.delegate.get()?.dispatch(event.toJson())
37
38
  }
38
39
  }
39
40
 
@@ -70,4 +70,20 @@ class Exceptions {
70
70
  * An exception to throw when the root view is missing.
71
71
  */
72
72
  class MissingRootView : CodedException(message = "The root view is missing")
73
+
74
+ /**
75
+ * An exception to throw to indicate that a method has been passed an illegal or inappropriate argument.
76
+ */
77
+ class IllegalArgument(
78
+ message: String,
79
+ cause: Throwable? = null
80
+ ) : CodedException(message, cause)
81
+
82
+ /**
83
+ * An exception to signal that a method has been invoked at an illegal or inappropriate time.
84
+ */
85
+ class IllegalStateException(
86
+ message: String,
87
+ cause: Throwable? = null
88
+ ) : CodedException(message, cause)
73
89
  }
@@ -7,9 +7,6 @@ import expo.modules.kotlin.providers.AppContextProvider
7
7
  import expo.modules.kotlin.tracing.trace
8
8
  import expo.modules.kotlin.types.Enumerable
9
9
  import kotlinx.coroutines.CoroutineScope
10
- import kotlin.reflect.KProperty1
11
- import kotlin.reflect.full.declaredMemberProperties
12
- import kotlin.reflect.full.primaryConstructor
13
10
 
14
11
  abstract class Module : AppContextProvider {
15
12
 
@@ -54,25 +51,6 @@ abstract class Module : AppContextProvider {
54
51
  }
55
52
 
56
53
  abstract fun definition(): ModuleDefinitionData
57
-
58
- private fun <T> convertEnumToString(enumValue: T): String where T : Enumerable, T : Enum<T> {
59
- val enumClass = enumValue::class
60
- val primaryConstructor = enumClass.primaryConstructor
61
- if (primaryConstructor?.parameters?.size == 1) {
62
- val parameterName = primaryConstructor.parameters.first().name
63
- val parameterProperty = enumClass
64
- .declaredMemberProperties
65
- .find { it.name == parameterName }
66
-
67
- requireNotNull(parameterProperty) { "Cannot find a property for $parameterName parameter" }
68
- require(parameterProperty.returnType.classifier == String::class) { "The enum parameter has to be a string." }
69
-
70
- @Suppress("UNCHECKED_CAST")
71
- return (parameterProperty as KProperty1<T, String>).get(enumValue)
72
- }
73
-
74
- return enumValue.name
75
- }
76
54
  }
77
55
 
78
56
  @Suppress("FunctionName")
@@ -0,0 +1,25 @@
1
+ package expo.modules.kotlin.modules
2
+
3
+ import expo.modules.kotlin.types.Enumerable
4
+ import kotlin.reflect.KProperty1
5
+ import kotlin.reflect.full.declaredMemberProperties
6
+ import kotlin.reflect.full.primaryConstructor
7
+
8
+ internal fun <T> convertEnumToString(enumValue: T): String where T : Enumerable, T : Enum<T> {
9
+ val enumClass = enumValue::class
10
+ val primaryConstructor = enumClass.primaryConstructor
11
+ if (primaryConstructor?.parameters?.size == 1) {
12
+ val parameterName = primaryConstructor.parameters.first().name
13
+ val parameterProperty = enumClass
14
+ .declaredMemberProperties
15
+ .find { it.name == parameterName }
16
+
17
+ requireNotNull(parameterProperty) { "Cannot find a property for $parameterName parameter" }
18
+ require(parameterProperty.returnType.classifier == String::class) { "The enum parameter has to be a string." }
19
+
20
+ @Suppress("UNCHECKED_CAST")
21
+ return (parameterProperty as KProperty1<T, String>).get(enumValue)
22
+ }
23
+
24
+ return enumValue.name
25
+ }