expo 53.0.17 → 53.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/ReactActivityDelegateWrapper.kt +139 -74
- package/android/src/test/java/expo/modules/ReactActivityDelegateWrapperDelayLoadTest.kt +1 -55
- package/android/src/test/java/expo/modules/ReactActivityDelegateWrapperTest.kt +7 -3
- package/bundledNativeModules.json +3 -3
- package/package.json +6 -6
package/android/build.gradle
CHANGED
|
@@ -32,7 +32,7 @@ buildscript {
|
|
|
32
32
|
def reactNativeVersion = project.extensions.getByType(ExpoModuleExtension).reactNativeVersion
|
|
33
33
|
|
|
34
34
|
group = 'host.exp.exponent'
|
|
35
|
-
version = '53.0.
|
|
35
|
+
version = '53.0.19'
|
|
36
36
|
|
|
37
37
|
expoModule {
|
|
38
38
|
// We can't prebuild the module because it depends on the generated files.
|
|
@@ -43,7 +43,7 @@ android {
|
|
|
43
43
|
namespace "expo.core"
|
|
44
44
|
defaultConfig {
|
|
45
45
|
versionCode 1
|
|
46
|
-
versionName "53.0.
|
|
46
|
+
versionName "53.0.19"
|
|
47
47
|
consumerProguardFiles("proguard-rules.pro")
|
|
48
48
|
}
|
|
49
49
|
testOptions {
|
|
@@ -29,8 +29,13 @@ import expo.modules.core.interfaces.ReactActivityHandler.DelayLoadAppHandler
|
|
|
29
29
|
import expo.modules.core.interfaces.ReactActivityLifecycleListener
|
|
30
30
|
import expo.modules.kotlin.Utils
|
|
31
31
|
import expo.modules.rncompatibility.ReactNativeFeatureFlags
|
|
32
|
+
import kotlinx.coroutines.CompletableDeferred
|
|
33
|
+
import kotlinx.coroutines.CoroutineScope
|
|
32
34
|
import kotlinx.coroutines.CoroutineStart
|
|
35
|
+
import kotlinx.coroutines.Dispatchers
|
|
33
36
|
import kotlinx.coroutines.launch
|
|
37
|
+
import kotlinx.coroutines.sync.Mutex
|
|
38
|
+
import kotlinx.coroutines.sync.withLock
|
|
34
39
|
import java.lang.reflect.Field
|
|
35
40
|
import java.lang.reflect.Method
|
|
36
41
|
import java.lang.reflect.Modifier
|
|
@@ -63,10 +68,25 @@ class ReactActivityDelegateWrapper(
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
/**
|
|
66
|
-
*
|
|
67
|
-
* This flag indicates we should emit `onResume` after `loadApp`.
|
|
71
|
+
* A deferred that indicates when the app loading is ready
|
|
68
72
|
*/
|
|
69
|
-
private
|
|
73
|
+
private val loadAppReady = CompletableDeferred<Unit>()
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A mutex to ensure all coroutines in a scope are running in atomic way.
|
|
77
|
+
*
|
|
78
|
+
* This is to act like [Activity] lifecycle,
|
|
79
|
+
* e.g. all work in [onResume] should be executed after all work in [onCreate] finished.
|
|
80
|
+
*/
|
|
81
|
+
private val mutex = Mutex()
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* A [CoroutineScope] that binds its lifecycle as [ReactActivityDelegateWrapper].
|
|
85
|
+
* This is used for [onDestroy] because we need a longer lifecycle scope to call [onDestroy]
|
|
86
|
+
*/
|
|
87
|
+
private val applicationCoroutineScope: CoroutineScope by lazy {
|
|
88
|
+
CoroutineScope(Dispatchers.Main)
|
|
89
|
+
}
|
|
70
90
|
|
|
71
91
|
//region ReactActivityDelegate
|
|
72
92
|
|
|
@@ -99,7 +119,7 @@ class ReactActivityDelegateWrapper(
|
|
|
99
119
|
}
|
|
100
120
|
|
|
101
121
|
override fun loadApp(appKey: String?) {
|
|
102
|
-
|
|
122
|
+
launchLifecycleScopeWithLock(start = CoroutineStart.UNDISPATCHED) {
|
|
103
123
|
loadAppImpl(appKey, supportsDelayLoad = true)
|
|
104
124
|
}
|
|
105
125
|
}
|
|
@@ -127,8 +147,9 @@ class ReactActivityDelegateWrapper(
|
|
|
127
147
|
// Instead we intercept `ReactActivityDelegate.onCreate` and replace the `mReactDelegate` with our version.
|
|
128
148
|
// That's not ideal but works.
|
|
129
149
|
|
|
130
|
-
|
|
150
|
+
launchLifecycleScopeWithLock(start = CoroutineStart.UNDISPATCHED) {
|
|
131
151
|
awaitDelayLoadAppWhenReady(delayLoadAppHandler)
|
|
152
|
+
loadAppReady.complete(Unit)
|
|
132
153
|
|
|
133
154
|
if (VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled) {
|
|
134
155
|
activity.window.colorMode = ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT
|
|
@@ -172,69 +193,70 @@ class ReactActivityDelegateWrapper(
|
|
|
172
193
|
}
|
|
173
194
|
|
|
174
195
|
override fun onResume() {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
196
|
+
launchLifecycleScopeWithLock {
|
|
197
|
+
loadAppReady.await()
|
|
198
|
+
delegate.onResume()
|
|
199
|
+
reactActivityLifecycleListeners.forEach { listener ->
|
|
200
|
+
listener.onResume(activity)
|
|
201
|
+
}
|
|
181
202
|
}
|
|
182
203
|
}
|
|
183
204
|
|
|
184
205
|
override fun onPause() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
launchLifecycleScopeWithLock {
|
|
207
|
+
loadAppReady.await()
|
|
208
|
+
reactActivityLifecycleListeners.forEach { listener ->
|
|
209
|
+
listener.onPause(activity)
|
|
210
|
+
}
|
|
211
|
+
if (delayLoadAppHandler != null) {
|
|
212
|
+
try {
|
|
213
|
+
// For the delay load case, we may enter a different call flow than react-native.
|
|
214
|
+
// For example, Activity stopped before delay load finished.
|
|
215
|
+
// We stop before the ReactActivityDelegate gets a chance to set up.
|
|
216
|
+
// In this case, we should catch the exceptions.
|
|
217
|
+
delegate.onPause()
|
|
218
|
+
} catch (e: Exception) {
|
|
219
|
+
Log.e(TAG, "Exception occurred during onPause with delayed app loading", e)
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
200
222
|
delegate.onPause()
|
|
201
|
-
} catch (e: Exception) {
|
|
202
|
-
Log.e(TAG, "Exception occurred during onPause with delayed app loading", e)
|
|
203
223
|
}
|
|
204
|
-
} else {
|
|
205
|
-
delegate.onPause()
|
|
206
224
|
}
|
|
207
225
|
}
|
|
208
226
|
|
|
209
227
|
override fun onUserLeaveHint() {
|
|
210
|
-
|
|
211
|
-
|
|
228
|
+
launchLifecycleScopeWithLock {
|
|
229
|
+
loadAppReady.await()
|
|
230
|
+
reactActivityLifecycleListeners.forEach { listener ->
|
|
231
|
+
listener.onUserLeaveHint(activity)
|
|
232
|
+
}
|
|
233
|
+
delegate.onUserLeaveHint()
|
|
212
234
|
}
|
|
213
|
-
delegate.onUserLeaveHint()
|
|
214
235
|
}
|
|
215
236
|
|
|
216
237
|
override fun onDestroy() {
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
238
|
+
// Note: use our `coroutineScope` for onDestroy here
|
|
239
|
+
// because the lifecycleScope destroyed before the executions.
|
|
240
|
+
applicationCoroutineScope.launch {
|
|
241
|
+
mutex.withLock {
|
|
242
|
+
loadAppReady.await()
|
|
243
|
+
reactActivityLifecycleListeners.forEach { listener ->
|
|
244
|
+
listener.onDestroy(activity)
|
|
245
|
+
}
|
|
246
|
+
if (delayLoadAppHandler != null) {
|
|
247
|
+
try {
|
|
248
|
+
// For the delay load case, we may enter a different call flow than react-native.
|
|
249
|
+
// For example, Activity stopped before delay load finished.
|
|
250
|
+
// We stop before the ReactActivityDelegate gets a chance to set up.
|
|
251
|
+
// In this case, we should catch the exceptions.
|
|
252
|
+
delegate.onDestroy()
|
|
253
|
+
} catch (e: Exception) {
|
|
254
|
+
Log.e(TAG, "Exception occurred during onDestroy with delayed app loading", e)
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
delegate.onDestroy()
|
|
258
|
+
}
|
|
235
259
|
}
|
|
236
|
-
} else {
|
|
237
|
-
delegate.onDestroy()
|
|
238
260
|
}
|
|
239
261
|
}
|
|
240
262
|
|
|
@@ -252,20 +274,28 @@ class ReactActivityDelegateWrapper(
|
|
|
252
274
|
*
|
|
253
275
|
* TODO (@bbarthec): fix it upstream?
|
|
254
276
|
*/
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
277
|
+
launchLifecycleScopeWithLock {
|
|
278
|
+
loadAppReady.await()
|
|
279
|
+
if (!ReactNativeFeatureFlags.enableBridgelessArchitecture && delegate.reactInstanceManager.currentReactContext == null) {
|
|
280
|
+
val reactContextListener = object : ReactInstanceEventListener {
|
|
281
|
+
override fun onReactContextInitialized(context: ReactContext) {
|
|
282
|
+
delegate.reactInstanceManager.removeReactInstanceEventListener(this)
|
|
283
|
+
delegate.onActivityResult(requestCode, resultCode, data)
|
|
284
|
+
}
|
|
260
285
|
}
|
|
286
|
+
return@launchLifecycleScopeWithLock delegate.reactInstanceManager.addReactInstanceEventListener(
|
|
287
|
+
reactContextListener
|
|
288
|
+
)
|
|
261
289
|
}
|
|
262
|
-
return delegate.reactInstanceManager.addReactInstanceEventListener(reactContextListener)
|
|
263
|
-
}
|
|
264
290
|
|
|
265
|
-
|
|
291
|
+
delegate.onActivityResult(requestCode, resultCode, data)
|
|
292
|
+
}
|
|
266
293
|
}
|
|
267
294
|
|
|
268
295
|
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
|
296
|
+
if (!loadAppReady.isCompleted) {
|
|
297
|
+
return false
|
|
298
|
+
}
|
|
269
299
|
// if any of the handlers return true, intentionally consume the event instead of passing it
|
|
270
300
|
// through to the delegate
|
|
271
301
|
return reactActivityHandlers
|
|
@@ -274,6 +304,9 @@ class ReactActivityDelegateWrapper(
|
|
|
274
304
|
}
|
|
275
305
|
|
|
276
306
|
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
|
307
|
+
if (!loadAppReady.isCompleted) {
|
|
308
|
+
return false
|
|
309
|
+
}
|
|
277
310
|
// if any of the handlers return true, intentionally consume the event instead of passing it
|
|
278
311
|
// through to the delegate
|
|
279
312
|
return reactActivityHandlers
|
|
@@ -282,6 +315,9 @@ class ReactActivityDelegateWrapper(
|
|
|
282
315
|
}
|
|
283
316
|
|
|
284
317
|
override fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean {
|
|
318
|
+
if (!loadAppReady.isCompleted) {
|
|
319
|
+
return false
|
|
320
|
+
}
|
|
285
321
|
// if any of the handlers return true, intentionally consume the event instead of passing it
|
|
286
322
|
// through to the delegate
|
|
287
323
|
return reactActivityHandlers
|
|
@@ -290,6 +326,9 @@ class ReactActivityDelegateWrapper(
|
|
|
290
326
|
}
|
|
291
327
|
|
|
292
328
|
override fun onBackPressed(): Boolean {
|
|
329
|
+
if (!loadAppReady.isCompleted) {
|
|
330
|
+
return false
|
|
331
|
+
}
|
|
293
332
|
val listenerResult = reactActivityLifecycleListeners
|
|
294
333
|
.map(ReactActivityLifecycleListener::onBackPressed)
|
|
295
334
|
.fold(false) { accu, current -> accu || current }
|
|
@@ -298,6 +337,9 @@ class ReactActivityDelegateWrapper(
|
|
|
298
337
|
}
|
|
299
338
|
|
|
300
339
|
override fun onNewIntent(intent: Intent?): Boolean {
|
|
340
|
+
if (!loadAppReady.isCompleted) {
|
|
341
|
+
return false
|
|
342
|
+
}
|
|
301
343
|
val listenerResult = reactActivityLifecycleListeners
|
|
302
344
|
.map { it.onNewIntent(intent) }
|
|
303
345
|
.fold(false) { accu, current -> accu || current }
|
|
@@ -306,15 +348,24 @@ class ReactActivityDelegateWrapper(
|
|
|
306
348
|
}
|
|
307
349
|
|
|
308
350
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
|
309
|
-
|
|
351
|
+
launchLifecycleScopeWithLock {
|
|
352
|
+
loadAppReady.await()
|
|
353
|
+
delegate.onWindowFocusChanged(hasFocus)
|
|
354
|
+
}
|
|
310
355
|
}
|
|
311
356
|
|
|
312
357
|
override fun requestPermissions(permissions: Array<out String>?, requestCode: Int, listener: PermissionListener?) {
|
|
313
|
-
|
|
358
|
+
launchLifecycleScopeWithLock {
|
|
359
|
+
loadAppReady.await()
|
|
360
|
+
delegate.requestPermissions(permissions, requestCode, listener)
|
|
361
|
+
}
|
|
314
362
|
}
|
|
315
363
|
|
|
316
364
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>?, grantResults: IntArray?) {
|
|
317
|
-
|
|
365
|
+
launchLifecycleScopeWithLock {
|
|
366
|
+
loadAppReady.await()
|
|
367
|
+
delegate.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
|
368
|
+
}
|
|
318
369
|
}
|
|
319
370
|
|
|
320
371
|
override fun getContext(): Context {
|
|
@@ -338,7 +389,10 @@ class ReactActivityDelegateWrapper(
|
|
|
338
389
|
}
|
|
339
390
|
|
|
340
391
|
override fun onConfigurationChanged(newConfig: Configuration?) {
|
|
341
|
-
|
|
392
|
+
launchLifecycleScopeWithLock {
|
|
393
|
+
loadAppReady.await()
|
|
394
|
+
delegate.onConfigurationChanged(newConfig)
|
|
395
|
+
}
|
|
342
396
|
}
|
|
343
397
|
|
|
344
398
|
//endregion
|
|
@@ -401,10 +455,6 @@ class ReactActivityDelegateWrapper(
|
|
|
401
455
|
reactActivityLifecycleListeners.forEach { listener ->
|
|
402
456
|
listener.onContentChanged(activity)
|
|
403
457
|
}
|
|
404
|
-
if (shouldEmitPendingResume) {
|
|
405
|
-
shouldEmitPendingResume = false
|
|
406
|
-
onResume()
|
|
407
|
-
}
|
|
408
458
|
return
|
|
409
459
|
}
|
|
410
460
|
|
|
@@ -412,17 +462,12 @@ class ReactActivityDelegateWrapper(
|
|
|
412
462
|
reactActivityLifecycleListeners.forEach { listener ->
|
|
413
463
|
listener.onContentChanged(activity)
|
|
414
464
|
}
|
|
415
|
-
if (shouldEmitPendingResume) {
|
|
416
|
-
shouldEmitPendingResume = false
|
|
417
|
-
onResume()
|
|
418
|
-
}
|
|
419
465
|
}
|
|
420
466
|
|
|
421
467
|
private suspend fun awaitDelayLoadAppWhenReady(delayLoadAppHandler: DelayLoadAppHandler?) {
|
|
422
468
|
if (delayLoadAppHandler == null) {
|
|
423
469
|
return
|
|
424
470
|
}
|
|
425
|
-
shouldEmitPendingResume = true
|
|
426
471
|
suspendCoroutine { continuation ->
|
|
427
472
|
delayLoadAppHandler.whenReady {
|
|
428
473
|
Utils.assertMainThread()
|
|
@@ -431,6 +476,26 @@ class ReactActivityDelegateWrapper(
|
|
|
431
476
|
}
|
|
432
477
|
}
|
|
433
478
|
|
|
479
|
+
private fun launchLifecycleScopeWithLock(
|
|
480
|
+
start: CoroutineStart = CoroutineStart.DEFAULT,
|
|
481
|
+
block: suspend CoroutineScope.() -> Unit
|
|
482
|
+
) {
|
|
483
|
+
activity.lifecycleScope.launch(start = start) {
|
|
484
|
+
mutex.withLock {
|
|
485
|
+
block()
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Set the [loadAppReady] to completed state.
|
|
492
|
+
* This is only for unit tests when a test setups mocks and skips the [Activity] lifecycle.
|
|
493
|
+
*/
|
|
494
|
+
@VisibleForTesting
|
|
495
|
+
internal fun setLoadAppReadyForTesting() {
|
|
496
|
+
loadAppReady.complete(Unit)
|
|
497
|
+
}
|
|
498
|
+
|
|
434
499
|
//endregion
|
|
435
500
|
|
|
436
501
|
companion object {
|
|
@@ -135,7 +135,7 @@ internal class ReactActivityDelegateWrapperDelayLoadTest {
|
|
|
135
135
|
verify(exactly = 0) { spyDelegate.onResume() }
|
|
136
136
|
|
|
137
137
|
callbackSlot.captured.run()
|
|
138
|
-
verify(exactly =
|
|
138
|
+
verify(exactly = 1) { spyDelegateWrapper.onResume() }
|
|
139
139
|
verify(exactly = 1) { spyDelegate.onResume() }
|
|
140
140
|
verify(exactly = 0) { spyDelegateWrapper.onPause() }
|
|
141
141
|
verify(exactly = 0) { spyDelegateWrapper.onDestroy() }
|
|
@@ -173,60 +173,6 @@ internal class ReactActivityDelegateWrapperDelayLoadTest {
|
|
|
173
173
|
verify(exactly = 1) { spyDelegate.onDestroy() }
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
@Test
|
|
177
|
-
fun `should cancel pending resume if activity pause before delay load finished`() = runTest {
|
|
178
|
-
every { ExpoModulesPackage.Companion.packageList } returns listOf(mockPackageWithDelay)
|
|
179
|
-
|
|
180
|
-
val callbackSlot = slot<Runnable>()
|
|
181
|
-
every { delayLoadAppHandler.whenReady(capture(callbackSlot)) } answers {
|
|
182
|
-
// Don't call the callback immediately to simulate delay
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
activityController = Robolectric.buildActivity(MockActivity::class.java)
|
|
186
|
-
.also {
|
|
187
|
-
val activity = it.get()
|
|
188
|
-
(activity.application as MockApplication).bindCurrentActivity(activity)
|
|
189
|
-
}
|
|
190
|
-
.setup()
|
|
191
|
-
val spyDelegateWrapper = activity.reactActivityDelegate as ReactActivityDelegateWrapper
|
|
192
|
-
val spyDelegate = spyDelegateWrapper.delegate
|
|
193
|
-
|
|
194
|
-
verify(exactly = 1) { spyDelegateWrapper.onCreate(any()) }
|
|
195
|
-
verify(exactly = 1) { spyDelegateWrapper.onResume() }
|
|
196
|
-
verify(exactly = 0) { spyDelegate.onResume() }
|
|
197
|
-
|
|
198
|
-
activityController.pause()
|
|
199
|
-
callbackSlot.captured.run()
|
|
200
|
-
verify(exactly = 0) { spyDelegate.onResume() }
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
@Test
|
|
204
|
-
fun `should cancel pending resume if activity stop before delay load finished`() = runTest {
|
|
205
|
-
every { ExpoModulesPackage.Companion.packageList } returns listOf(mockPackageWithDelay)
|
|
206
|
-
|
|
207
|
-
val callbackSlot = slot<Runnable>()
|
|
208
|
-
every { delayLoadAppHandler.whenReady(capture(callbackSlot)) } answers {
|
|
209
|
-
// Don't call the callback immediately to simulate delay
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
activityController = Robolectric.buildActivity(MockActivity::class.java)
|
|
213
|
-
.also {
|
|
214
|
-
val activity = it.get()
|
|
215
|
-
(activity.application as MockApplication).bindCurrentActivity(activity)
|
|
216
|
-
}
|
|
217
|
-
.setup()
|
|
218
|
-
val spyDelegateWrapper = activity.reactActivityDelegate as ReactActivityDelegateWrapper
|
|
219
|
-
val spyDelegate = spyDelegateWrapper.delegate
|
|
220
|
-
|
|
221
|
-
verify(exactly = 1) { spyDelegateWrapper.onCreate(any()) }
|
|
222
|
-
verify(exactly = 1) { spyDelegateWrapper.onResume() }
|
|
223
|
-
verify(exactly = 0) { spyDelegate.onResume() }
|
|
224
|
-
|
|
225
|
-
activityController.pause().stop()
|
|
226
|
-
callbackSlot.captured.run()
|
|
227
|
-
verify(exactly = 0) { spyDelegate.onResume() }
|
|
228
|
-
}
|
|
229
|
-
|
|
230
176
|
@Test
|
|
231
177
|
fun `should cancel pending resume if activity destroy before delay load finished`() = runTest {
|
|
232
178
|
every { ExpoModulesPackage.Companion.packageList } returns listOf(mockPackageWithDelay)
|
|
@@ -20,9 +20,9 @@ import org.junit.Before
|
|
|
20
20
|
import org.junit.Test
|
|
21
21
|
|
|
22
22
|
internal class ReactActivityDelegateWrapperTest {
|
|
23
|
-
lateinit var mockPackage0: MockPackage
|
|
23
|
+
private lateinit var mockPackage0: MockPackage
|
|
24
24
|
|
|
25
|
-
lateinit var mockPackage1: MockPackage
|
|
25
|
+
private lateinit var mockPackage1: MockPackage
|
|
26
26
|
|
|
27
27
|
@RelaxedMockK
|
|
28
28
|
lateinit var activity: ReactActivity
|
|
@@ -47,6 +47,7 @@ internal class ReactActivityDelegateWrapperTest {
|
|
|
47
47
|
@Test
|
|
48
48
|
fun `onBackPressed should call each handler's callback just once`() {
|
|
49
49
|
val delegateWrapper = ReactActivityDelegateWrapper(activity, delegate)
|
|
50
|
+
delegateWrapper.setLoadAppReadyForTesting()
|
|
50
51
|
every { mockPackage0.reactActivityLifecycleListener.onBackPressed() } returns true
|
|
51
52
|
|
|
52
53
|
delegateWrapper.onBackPressed()
|
|
@@ -59,6 +60,7 @@ internal class ReactActivityDelegateWrapperTest {
|
|
|
59
60
|
@Test
|
|
60
61
|
fun `onBackPressed should return true if someone returns true`() {
|
|
61
62
|
val delegateWrapper = ReactActivityDelegateWrapper(activity, delegate)
|
|
63
|
+
delegateWrapper.setLoadAppReadyForTesting()
|
|
62
64
|
every { mockPackage0.reactActivityLifecycleListener.onBackPressed() } returns false
|
|
63
65
|
every { mockPackage1.reactActivityLifecycleListener.onBackPressed() } returns true
|
|
64
66
|
every { delegate.onBackPressed() } returns false
|
|
@@ -71,6 +73,7 @@ internal class ReactActivityDelegateWrapperTest {
|
|
|
71
73
|
fun `onNewIntent should call each handler's callback just once`() {
|
|
72
74
|
val intent = mockk<Intent>()
|
|
73
75
|
val delegateWrapper = ReactActivityDelegateWrapper(activity, delegate)
|
|
76
|
+
delegateWrapper.setLoadAppReadyForTesting()
|
|
74
77
|
every { mockPackage0.reactActivityLifecycleListener.onNewIntent(intent) } returns false
|
|
75
78
|
every { mockPackage1.reactActivityLifecycleListener.onNewIntent(intent) } returns true
|
|
76
79
|
every { delegate.onNewIntent(intent) } returns false
|
|
@@ -86,6 +89,7 @@ internal class ReactActivityDelegateWrapperTest {
|
|
|
86
89
|
fun `onNewIntent should return true if someone returns true`() {
|
|
87
90
|
val intent = mockk<Intent>()
|
|
88
91
|
val delegateWrapper = ReactActivityDelegateWrapper(activity, delegate)
|
|
92
|
+
delegateWrapper.setLoadAppReadyForTesting()
|
|
89
93
|
every { mockPackage0.reactActivityLifecycleListener.onNewIntent(intent) } returns false
|
|
90
94
|
every { mockPackage1.reactActivityLifecycleListener.onNewIntent(intent) } returns true
|
|
91
95
|
every { delegate.onNewIntent(intent) } returns false
|
|
@@ -97,7 +101,7 @@ internal class ReactActivityDelegateWrapperTest {
|
|
|
97
101
|
|
|
98
102
|
internal class MockPackage : Package {
|
|
99
103
|
val reactActivityLifecycleListener = mockk<ReactActivityLifecycleListener>(relaxed = true)
|
|
100
|
-
val reactActivityHandler = mockk<ReactActivityHandler>(relaxed = true)
|
|
104
|
+
private val reactActivityHandler = mockk<ReactActivityHandler>(relaxed = true)
|
|
101
105
|
|
|
102
106
|
override fun createReactActivityLifecycleListeners(activityContext: Context?): List<ReactActivityLifecycleListener> {
|
|
103
107
|
return listOf(reactActivityLifecycleListener)
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"expo-apple-authentication": "~7.2.4",
|
|
20
20
|
"expo-application": "~6.1.5",
|
|
21
21
|
"expo-asset": "~11.1.7",
|
|
22
|
-
"expo-audio": "~0.4.
|
|
22
|
+
"expo-audio": "~0.4.8",
|
|
23
23
|
"expo-auth-session": "~6.2.1",
|
|
24
24
|
"expo-av": "~15.1.7",
|
|
25
25
|
"expo-background-fetch": "~13.1.6",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"expo-modules-core": "~2.4.2",
|
|
66
66
|
"expo-navigation-bar": "~4.2.7",
|
|
67
67
|
"expo-network": "~7.1.5",
|
|
68
|
-
"expo-notifications": "~0.31.
|
|
68
|
+
"expo-notifications": "~0.31.4",
|
|
69
69
|
"expo-print": "~14.1.4",
|
|
70
70
|
"expo-live-photo": "~0.1.4",
|
|
71
71
|
"expo-router": "~5.1.3",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"expo-sms": "~13.1.4",
|
|
78
78
|
"expo-speech": "~13.1.7",
|
|
79
79
|
"expo-splash-screen": "~0.30.10",
|
|
80
|
-
"expo-sqlite": "~15.2.
|
|
80
|
+
"expo-sqlite": "~15.2.14",
|
|
81
81
|
"expo-status-bar": "~2.2.3",
|
|
82
82
|
"expo-store-review": "~8.1.5",
|
|
83
83
|
"expo-symbols": "~0.4.5",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo",
|
|
3
|
-
"version": "53.0.
|
|
3
|
+
"version": "53.0.19",
|
|
4
4
|
"description": "The Expo SDK",
|
|
5
5
|
"main": "src/Expo.ts",
|
|
6
6
|
"module": "src/Expo.ts",
|
|
@@ -73,9 +73,9 @@
|
|
|
73
73
|
"homepage": "https://github.com/expo/expo/tree/main/packages/expo",
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@babel/runtime": "^7.20.0",
|
|
76
|
-
"@expo/cli": "0.24.
|
|
77
|
-
"@expo/config": "~11.0.
|
|
78
|
-
"@expo/config-plugins": "~10.1.
|
|
76
|
+
"@expo/cli": "0.24.20",
|
|
77
|
+
"@expo/config": "~11.0.13",
|
|
78
|
+
"@expo/config-plugins": "~10.1.2",
|
|
79
79
|
"@expo/fingerprint": "0.13.4",
|
|
80
80
|
"@expo/metro-config": "0.20.17",
|
|
81
81
|
"@expo/vector-icons": "^14.0.0",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"expo-file-system": "~18.1.11",
|
|
86
86
|
"expo-font": "~13.3.2",
|
|
87
87
|
"expo-keep-awake": "~14.1.4",
|
|
88
|
-
"expo-modules-autolinking": "2.1.
|
|
88
|
+
"expo-modules-autolinking": "2.1.14",
|
|
89
89
|
"expo-modules-core": "2.4.2",
|
|
90
90
|
"react-native-edge-to-edge": "1.6.0",
|
|
91
91
|
"whatwg-url-without-unicode": "8.0.0-3"
|
|
@@ -119,5 +119,5 @@
|
|
|
119
119
|
"optional": true
|
|
120
120
|
}
|
|
121
121
|
},
|
|
122
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "134c147ee4274f9688929ac66cfef950947659d0"
|
|
123
123
|
}
|