mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-10 18:35:17 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb93fda060 |
@@ -40,7 +40,7 @@
|
|||||||
"dev:ios": "npm --prefix ../.. run build:client && cross-env APP_VARIANT=development expo run:ios",
|
"dev:ios": "npm --prefix ../.. run build:client && cross-env APP_VARIANT=development expo run:ios",
|
||||||
"build:apk": "npm --prefix ../.. run build:apk",
|
"build:apk": "npm --prefix ../.. run build:apk",
|
||||||
"build:apk:arm64": "npm --prefix ../.. run build:apk:arm64",
|
"build:apk:arm64": "npm --prefix ../.. run build:apk:arm64",
|
||||||
"test:android": "expo prebuild --platform android --no-install && cd android && ./gradlew :paseo-native-trace:testReleaseUnitTest --no-daemon --max-workers=2 -Dorg.gradle.parallel=false"
|
"test:android": "expo prebuild --platform android --no-install && cd android && ./gradlew :paseo-native-trace:testReleaseUnitTest :expo-modules-core:testReleaseUnitTest --tests expo.modules.kotlin.activityresult.AppContextActivityResultRegistryRecreationTest --no-daemon --max-workers=2 -Dorg.gradle.parallel=false"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/commands": "6.10.4",
|
"@codemirror/commands": "6.10.4",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt b/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt
|
diff --git a/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt b/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt
|
||||||
index a5b971e..7ef1b59 100644
|
index a5b971e..84ba96f 100644
|
||||||
--- a/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt
|
--- a/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt
|
||||||
+++ b/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt
|
+++ b/node_modules/expo-modules-core/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt
|
||||||
@@ -29,6 +29,7 @@ import expo.modules.kotlin.safeGetParcelable
|
@@ -29,6 +29,7 @@ import expo.modules.kotlin.safeGetParcelable
|
||||||
@@ -10,7 +10,22 @@ index a5b971e..7ef1b59 100644
|
|||||||
|
|
||||||
private const val TAG = "ActivityResultRegistry"
|
private const val TAG = "ActivityResultRegistry"
|
||||||
|
|
||||||
@@ -222,6 +223,7 @@ class AppContextActivityResultRegistry(
|
@@ -208,7 +209,13 @@ class AppContextActivityResultRegistry(
|
||||||
|
}
|
||||||
|
|
||||||
|
Lifecycle.Event.ON_DESTROY -> {
|
||||||
|
- unregister(key)
|
||||||
|
+ if (launchedKeys.contains(key) && keyToCallbacksAndContract[key]?.mainCallback != null) {
|
||||||
|
+ // The AppContext and awaiting caller survive Activity recreation.
|
||||||
|
+ // Detach the old lifecycle, but keep the in-flight result callback.
|
||||||
|
+ keyToLifecycleContainers.remove(key)?.clearObservers()
|
||||||
|
+ } else {
|
||||||
|
+ unregister(key)
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
@@ -222,6 +229,7 @@ class AppContextActivityResultRegistry(
|
||||||
return object : AppContextActivityResultLauncher<I, O>() {
|
return object : AppContextActivityResultLauncher<I, O>() {
|
||||||
override fun launch(input: I, callback: ActivityResultCallback<O>) {
|
override fun launch(input: I, callback: ActivityResultCallback<O>) {
|
||||||
val requestCode = keyToRequestCode[key]
|
val requestCode = keyToRequestCode[key]
|
||||||
@@ -18,7 +33,7 @@ index a5b971e..7ef1b59 100644
|
|||||||
?: throw IllegalStateException("Attempting to launch an unregistered ActivityResultLauncher with contract $contract and input $input. You must ensure the ActivityResultLauncher is registered before calling launch()")
|
?: throw IllegalStateException("Attempting to launch an unregistered ActivityResultLauncher with contract $contract and input $input. You must ensure the ActivityResultLauncher is registered before calling launch()")
|
||||||
|
|
||||||
keyToCallbacksAndContract[key] = CallbacksAndContract(fallbackCallback, callback, contract)
|
keyToCallbacksAndContract[key] = CallbacksAndContract(fallbackCallback, callback, contract)
|
||||||
@@ -240,6 +242,39 @@ class AppContextActivityResultRegistry(
|
@@ -240,6 +248,39 @@ class AppContextActivityResultRegistry(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,12 +73,24 @@ index a5b971e..7ef1b59 100644
|
|||||||
/**
|
/**
|
||||||
* Persist the state of the registry.
|
* Persist the state of the registry.
|
||||||
*/
|
*/
|
||||||
|
@@ -324,6 +365,11 @@ class AppContextActivityResultRegistry(
|
||||||
|
val input = keyToInputParam[key] as I
|
||||||
|
callbacksAndContract.mainCallback.onActivityResult(callbacksAndContract.contract.parseResult(input, resultCode, data))
|
||||||
|
launchedKeys.remove(key)
|
||||||
|
+ // Release a completed registration whose Activity was destroyed. The
|
||||||
|
+ // retained launcher will register against the live Activity on its next use.
|
||||||
|
+ if (!keyToLifecycleContainers.containsKey(key)) {
|
||||||
|
+ unregister(key)
|
||||||
|
+ }
|
||||||
|
} else if (currentLifecycleState != null && currentLifecycleState.isAtLeast(Lifecycle.State.STARTED) && callbacksAndContract != null && launchedKeys.contains(key)) {
|
||||||
|
// 2. Activity has already started, so let's proceed with fallback callback scenario
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
diff --git a/node_modules/expo-modules-core/android/src/test/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistryRecreationTest.kt b/node_modules/expo-modules-core/android/src/test/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistryRecreationTest.kt
|
diff --git a/node_modules/expo-modules-core/android/src/test/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistryRecreationTest.kt b/node_modules/expo-modules-core/android/src/test/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistryRecreationTest.kt
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..89a8eb1
|
index 0000000..71d740c
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/node_modules/expo-modules-core/android/src/test/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistryRecreationTest.kt
|
+++ b/node_modules/expo-modules-core/android/src/test/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistryRecreationTest.kt
|
||||||
@@ -0,0 +1,78 @@
|
@@ -0,0 +1,140 @@
|
||||||
+package expo.modules.kotlin.activityresult
|
+package expo.modules.kotlin.activityresult
|
||||||
+
|
+
|
||||||
+import android.app.Activity
|
+import android.app.Activity
|
||||||
@@ -71,6 +98,7 @@ index 0000000..89a8eb1
|
|||||||
+import android.content.Intent
|
+import android.content.Intent
|
||||||
+import androidx.appcompat.app.AppCompatActivity
|
+import androidx.appcompat.app.AppCompatActivity
|
||||||
+import expo.modules.kotlin.providers.CurrentActivityProvider
|
+import expo.modules.kotlin.providers.CurrentActivityProvider
|
||||||
|
+import org.junit.Assert.assertFalse
|
||||||
+import org.junit.Assert.assertEquals
|
+import org.junit.Assert.assertEquals
|
||||||
+import org.junit.Assert.assertTrue
|
+import org.junit.Assert.assertTrue
|
||||||
+import org.junit.Test
|
+import org.junit.Test
|
||||||
@@ -95,6 +123,67 @@ index 0000000..89a8eb1
|
|||||||
+ }.setup()
|
+ }.setup()
|
||||||
+
|
+
|
||||||
+ @Test
|
+ @Test
|
||||||
|
+ fun inFlightResultReachesOriginalCallerAfterRepeatedActivityRecreation() {
|
||||||
|
+ var controller = createActivity()
|
||||||
|
+ val provider = ActivityProvider(controller.get())
|
||||||
|
+ val registry = AppContextActivityResultRegistry(provider)
|
||||||
|
+ val results = mutableListOf<String>()
|
||||||
|
+ val fallbackResults = mutableListOf<String>()
|
||||||
|
+ val launcher = registry.register("image", controller.get(), contract) { _, result ->
|
||||||
|
+ fallbackResults.add(result)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Both selection and cancellation must settle the awaiting picker call.
|
||||||
|
+ listOf(Activity.RESULT_OK, Activity.RESULT_CANCELED, Activity.RESULT_OK).forEachIndexed { index, code ->
|
||||||
|
+ launcher.launch("image-$index") { results.add(it) }
|
||||||
|
+ val started = shadowOf(controller.get()).nextStartedActivityForResult
|
||||||
|
+ controller.pause().stop().destroy()
|
||||||
|
+ controller = createActivity()
|
||||||
|
+ provider.currentActivity = controller.get()
|
||||||
|
+
|
||||||
|
+ assertTrue(registry.dispatchResult(started.requestCode, code, null))
|
||||||
|
+ assertEquals(index + 1, results.size)
|
||||||
|
+ assertEquals("image-$index:$code", results.last())
|
||||||
|
+ // A completed request from the destroyed Activity is no longer registered.
|
||||||
|
+ assertFalse(registry.dispatchResult(started.requestCode, code, null))
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ launcher.launch("next-pick") { results.add(it) }
|
||||||
|
+ val next = shadowOf(controller.get()).nextStartedActivityForResult
|
||||||
|
+ assertTrue(registry.dispatchResult(next.requestCode, Activity.RESULT_OK, null))
|
||||||
|
+ assertEquals(listOf("image-0:-1", "image-1:0", "image-2:-1", "next-pick:-1"), results)
|
||||||
|
+ assertEquals(emptyList<String>(), fallbackResults)
|
||||||
|
+ controller.pause().stop().destroy()
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ fun restoredRegistryStillUsesFallbackWithoutTheOriginalAppContext() {
|
||||||
|
+ val previous = createActivity()
|
||||||
|
+ val provider = ActivityProvider(previous.get())
|
||||||
|
+ val original = AppContextActivityResultRegistry(provider)
|
||||||
|
+ val results = mutableListOf<String>()
|
||||||
|
+ val launcher = original.register("image", previous.get(), contract) { _, result ->
|
||||||
|
+ results.add("old-fallback:$result")
|
||||||
|
+ }
|
||||||
|
+ launcher.launch("restored-image") { results.add("old-caller:$it") }
|
||||||
|
+ val started = shadowOf(previous.get()).nextStartedActivityForResult
|
||||||
|
+ original.persistInstanceState(previous.get())
|
||||||
|
+ previous.pause().stop().destroy()
|
||||||
|
+
|
||||||
|
+ val replacement = createActivity()
|
||||||
|
+ provider.currentActivity = replacement.get()
|
||||||
|
+ val restored = AppContextActivityResultRegistry(provider)
|
||||||
|
+ restored.restoreInstanceState(replacement.get())
|
||||||
|
+ restored.register("image", replacement.get(), contract) { _, result ->
|
||||||
|
+ results.add("fallback:$result")
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ assertTrue(restored.dispatchResult(started.requestCode, Activity.RESULT_OK, null))
|
||||||
|
+ assertEquals(listOf("fallback:restored-image:-1"), results)
|
||||||
|
+ replacement.pause().stop().destroy()
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
+ fun retainedLauncherDeliversResultsAfterRepeatedActivityRecreation() {
|
+ fun retainedLauncherDeliversResultsAfterRepeatedActivityRecreation() {
|
||||||
+ var controller = createActivity()
|
+ var controller = createActivity()
|
||||||
+ val provider = ActivityProvider(controller.get())
|
+ val provider = ActivityProvider(controller.get())
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import { join, relative } from "node:path";
|
|||||||
// the patch's node_modules/... paths relative to its working directory.
|
// the patch's node_modules/... paths relative to its working directory.
|
||||||
const patchedPackages = [
|
const patchedPackages = [
|
||||||
// Backport for expo-modules-core 57.0.23: https://github.com/expo/expo/pull/49634.
|
// Backport for expo-modules-core 57.0.23: https://github.com/expo/expo/pull/49634.
|
||||||
// Remove when the installed Expo SDK includes the Activity recreation fix.
|
// Also retain in-flight picker callbacks across same-process Activity recreation (#7557).
|
||||||
|
// Remove when the installed Expo SDK includes both Activity recreation fixes.
|
||||||
{
|
{
|
||||||
nodeModulesPath: "node_modules/expo-modules-core",
|
nodeModulesPath: "node_modules/expo-modules-core",
|
||||||
patchPrefix: "expo-modules-core+",
|
patchPrefix: "expo-modules-core+",
|
||||||
|
|||||||
Reference in New Issue
Block a user