Skip to content
Open
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
15 changes: 15 additions & 0 deletions packages/react-native-reanimated/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ if (project == rootProject) {
apply plugin: "com.android.library"
apply plugin: "maven-publish"
apply plugin: "de.undercouch.download"
apply plugin: 'org.jetbrains.kotlin.android'

if (project != rootProject) {
apply plugin: "org.jetbrains.kotlin.android"
}
Comment on lines 150 to +157
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

org.jetbrains.kotlin.android is applied unconditionally and then applied again for non-root projects. This differs from the pattern used in react-native-worklets (only applied when project != rootProject) and can cause redundant plugin application / configuration warnings. Consider applying the Kotlin Android plugin only once (likely inside the project != rootProject branch).

Copilot uses AI. Check for mistakes.

android {
compileSdkVersion safeExtGet("compileSdkVersion", 36)
Expand Down Expand Up @@ -242,6 +247,14 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
if (project != rootProject) {
kotlinOptions {
jvmTarget = '17'
}
}
Comment on lines +250 to +257
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kotlinOptions { jvmTarget = '17' } is configured twice (once unconditionally and once under if (project != rootProject)). This duplication is easy to drift and makes it unclear which block is authoritative. Prefer a single kotlinOptions configuration (or keep it only in the conditional block, matching the worklets module).

Copilot uses AI. Check for mistakes.
tasks.withType(ExternalNativeBuildJsonTask).tap {
configureEach { compileTask ->
compileTask.doLast {
Expand Down Expand Up @@ -334,6 +347,8 @@ dependencies {
implementation "androidx.core:core:1.15.0"

implementation "com.facebook.react:react-android" // version substituted by RNGP
implementation "androidx.core:core-ktx:1.17.0"
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two androidx.core:core-ktx dependencies declared with different versions. This can lead to unpredictable dependency resolution and larger/duplicated classes on the classpath. Keep a single core-ktx dependency and align its version with the rest of the repo (e.g., the worklets Android module).

Suggested change
implementation "androidx.core:core-ktx:1.17.0"

Copilot uses AI. Check for mistakes.
implementation 'androidx.core:core-ktx:1.18.0'

if (project == rootProject) {
// This is needed for linting in Reanimated's repo.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.swmansion.common

interface GestureHandlerStateManager {
fun setGestureHandlerState(handlerTag: Int, newState: Int)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.swmansion.reanimated

import com.facebook.react.bridge.WritableArray
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter

class CopiedEvent(event: Event<*>) {
var targetTag: Int = 0
private set

var eventName: String = ""
private set

var payload: WritableMap? = null
private set

init {
event.dispatch(
object : RCTEventEmitter {
override fun receiveEvent(targetTag: Int, eventName: String, event: WritableMap?) {
this@CopiedEvent.targetTag = targetTag
this@CopiedEvent.eventName = eventName
this@CopiedEvent.payload = event?.copy()
}

override fun receiveTouches(
eventName: String,
touches: WritableArray,
changedIndices: WritableArray
) {
// noop
}
})
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.swmansion.reanimated

import com.facebook.react.ReactApplication
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.devsupport.interfaces.DevOptionHandler

object DevMenuUtils {
@JvmStatic
fun addDevMenuOption(context: ReactApplicationContext, handler: DevOptionHandler) {
// In Expo, `ApplicationContext` is not an instance of `ReactApplication`
if (context.applicationContext is ReactApplication) {
val devSupportManager =
(context.applicationContext as ReactApplication).reactHost!!.devSupportManager

if (devSupportManager != null) {
devSupportManager.addCustomDevOption("Toggle slow animations (Reanimated)", handler)
} else {
throw RuntimeException("[Reanimated] DevSupportManager is not available")
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.swmansion.reanimated

import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.ViewTreeObserver
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.UiThreadUtil

/** Tracks whether the current UI thread turn is inside a draw pass. */
internal class DrawPassDetector(private val mContext: ReactApplicationContext) {
private val mHandler = Handler(Looper.getMainLooper())
private val mClearRunnable = Runnable { mIsInDrawPass = false }
private var mIsInDrawPass = false
private var mDecorView: View? = null

private val mOnDrawListener = ViewTreeObserver.OnDrawListener {
mIsInDrawPass = true
mHandler.postAtFrontOfQueue(mClearRunnable)
}

fun initialize() {
val activity = mContext.currentActivity ?: return

val decorView = activity.window.decorView
if (decorView === mDecorView) {
return
}

// Decor view has changed (e.g. Activity recreated) — detach from the old one first.
mDecorView?.let { oldView ->
val oldObserver = oldView.viewTreeObserver
if (oldObserver.isAlive) {
oldObserver.removeOnDrawListener(mOnDrawListener)
}
mDecorView = null
}

val observer = decorView.viewTreeObserver
if (!observer.isAlive) {
return
}

mDecorView = decorView
observer.addOnDrawListener(mOnDrawListener)
}

fun isInDrawPass(): Boolean = mIsInDrawPass

fun invalidate() {
if (UiThreadUtil.isOnUiThread()) {
invalidateOnUiThread()
} else {
mHandler.post { invalidateOnUiThread() }
}
}

private fun invalidateOnUiThread() {
mDecorView?.let { view ->
val observer = view.viewTreeObserver
if (observer.isAlive) {
observer.removeOnDrawListener(mOnDrawListener)
}
mDecorView = null
}
mHandler.removeCallbacks(mClearRunnable)
mIsInDrawPass = false
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.swmansion.reanimated

import com.facebook.react.bridge.JSApplicationCausedNativeException
import com.facebook.react.bridge.NoSuchKeyException
import com.facebook.react.bridge.ReadableMap

object MapUtils {
@JvmStatic
fun getInt(map: ReadableMap, name: String, errorMsg: String): Int {
try {
return map.getInt(name)
} catch (e: NoSuchKeyException) {
throw JSApplicationCausedNativeException(errorMsg)
}
}

@JvmStatic
fun getString(map: ReadableMap, name: String, errorMsg: String): String? {
try {
return map.getString(name)
} catch (e: NoSuchKeyException) {
throw JSApplicationCausedNativeException(errorMsg)
}
}
}
Loading
Loading