Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/react-native-reanimated/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ if (project != rootProject) {
val packageDir: File = project.projectDir.parentFile
val reactNativeRootDir: File = resolveReactNativeDirectory()
val REACT_NATIVE_VERSION: String = getReactNativeVersion()
val IS_REACT_NATIVE_86_OR_NEWER: Boolean = run {
val parts = REACT_NATIVE_VERSION.split(".")
val major = parts.getOrNull(0)?.toIntOrNull() ?: 0
val minor = parts.getOrNull(1)?.toIntOrNull() ?: 0
major > 0 || minor >= 86
}
val REANIMATED_VERSION: String = getReanimatedVersion()
val IS_REANIMATED_EXAMPLE_APP: Boolean = safeAppExtGet("isReanimatedExampleApp", false)?.toString()?.toBoolean() ?: false
val REANIMATED_PROFILING: Boolean = safeAppExtGet("enableReanimatedProfiling", false)?.toString()?.toBoolean() ?: false
Expand Down Expand Up @@ -171,6 +177,7 @@ android {
buildConfigField("String", "REANIMATED_VERSION_JAVA", "\"$REANIMATED_VERSION\"")
buildConfigField("boolean", "IS_INTERNAL_BUILD", "false")
buildConfigField("int", "EXOPACKAGE_FLAGS", "0")
buildConfigField("boolean", "IS_REACT_NATIVE_86_OR_NEWER", IS_REACT_NATIVE_86_OR_NEWER.toString())

@Suppress("UnstableApiUsage")
externalNativeBuild {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.swmansion.reanimated
import android.content.ContentResolver
import android.os.SystemClock
import android.provider.Settings
import android.util.Log
import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.bridge.NativeModule
Expand Down Expand Up @@ -222,13 +223,43 @@ open class NativeProxy {
return true
}

// TODO(#9681): Temporary workaround for RN >= 0.86. Since RN 0.86,
// overrideBySynchronousMountPropsAtMountingAndroid defaults on, so RN's only public
// synchronous-update API (synchronouslyUpdateViewOnUIThread) seeds the tagToSynchronousMountProps
// cache that then clamps later commits and freezes animations. On RN >= 0.86 we instead call
// MountingManager.updatePropsSynchronously directly (apply without cache seeding) via reflection, since
// MountingManager is internal. On older RN the flag is off, so we keep the original RN path
// unchanged (gated by BuildConfig.IS_REACT_NATIVE_86_OR_NEWER, derived from the RN version at
// build time). Remove once RN exposes a non-seeding synchronous-update API.
private val mountingManager: Any by lazy {
FabricUIManager::class.java.getDeclaredField("mMountingManager").run {
isAccessible = true
get(mFabricUIManager)
}
}

private val updatePropsSynchronouslyMethod by lazy {
mountingManager.javaClass.methods
.first {
it.name.startsWith("updatePropsSynchronously") && it.parameterTypes.size == 2
}.apply { isAccessible = true }
}

@DoNotStrip
fun synchronouslyUpdateUIProps(
intBuffer: IntArray,
doubleBuffer: DoubleArray,
) {
SynchronousPropsBufferParser.parse(intBuffer, doubleBuffer) { viewTag, props ->
mFabricUIManager.synchronouslyUpdateViewOnUIThread(viewTag, props)
if (BuildConfig.IS_REACT_NATIVE_86_OR_NEWER) {
try {
updatePropsSynchronouslyMethod.invoke(mountingManager, viewTag, props)
} catch (e: Exception) {
Log.w("Reanimated", "synchronouslyUpdateUIProps failed for tag $viewTag", e)
}
} else {
mFabricUIManager.synchronouslyUpdateViewOnUIThread(viewTag, props)
}
}
}

Expand Down
Loading