Summary:
This PR refactors the entire ReactAndroid package to replace manual `Arguments.createMap()…` and `Arguments.createArray()…` calls with the new Kotlin DSL helpers `buildReadableMap { … }` and `buildReadableArray { … }`. All eligible call sites have been migrated to the DSL, except in functions whose signatures explicitly declare or return WritableMap or WritableArray.
No runtime behavior changes are introduced; existing functionality and tests continue to pass unchanged.
## Changelog:
<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:
[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message
For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[ANDROID] [CHANGED] Apply Collections DSL on ReactAndroid package
Pull Request resolved: https://github.com/facebook/react-native/pull/51145
Test Plan:
```
yarn android
yarn test-android
```
Reviewed By: rshest
Differential Revision: D74401357
Pulled By: cortinico
fbshipit-source-id: 0f7b7dfbb7b495675bc4730bdf018666e9041884
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51183
D58818560 tried to deduplicate some code, but introduced an error, where we no longer correctly incorporate the width MeasureMode into the text layout that we create, instead, passing `YogaMeasureMode.EXACTLY`.
In effect, this means the Android layout created always takes up the maximum allowable space, even if content is smaller. This is later masked, because our returned measure when `AT_MOST` is based on maximum line length, and the layout is then recreated when drawing a TextView, but means:
1. Attachments may not be positioned correctly, when using a non-left-aligned paragraph alignment
2. Directly drawing the layout shows the wrong thing
Changelog:
[Android][Fixed] - Fix TextLayoutManager MeasureMode Regression
Reviewed By: rshest
Differential Revision: D74366936
fbshipit-source-id: 3eda8c716ba9790a61c2da19023e140afbb6971d
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51174
Allows the start and end of the scrollview to be faded to different values independently by passing an object containing a "start" and "end" value to the fadingEdgeLength prop.
To support non-uniform edge lengths we use the [FadingEdgeStrength](https://developer.android.com/reference/android/view/View#getTopFadingEdgeStrength()) api to set different values for the start/end of the scrollview. The FadingEdgeStrength value is multiplied by the FadingEdgeLength value [internally by Android when drawing the view.](https://cs.android.com/android/platform/superproject/+/android15-qpr1-release:frameworks/base/core/java/android/view/View.java;l=25007)
Because the value of FadingEdgeStrength is required to be between 0 and 1, we set setFadingEdgeLength to the max value and set the smaller side as a percentage of that value.
Changelog: [Android][Added] Allow fadingEdgeLength to be set independently on the start and end of the scrollview
Reviewed By: martinbooth
Differential Revision: D74222606
fbshipit-source-id: 7010ca803cc48450ab98c2a457fdc72ff47c29d7
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51141
This diff introduces ReactSoftExceptionLogger.CategoryMode to limit categories used on soft errors, the limiation will only create a lint warning but won't create a compilation error.
changelog: [internal] internal
Reviewed By: javache
Differential Revision: D74263367
fbshipit-source-id: 56fb2ef0ad3d24810172af300e43ecc1f479464f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51065
This adds infrastructure to let us start storing cached Android text layouts as part of a `ParagraphShadowNode`. After this, we will clear them out, and propagate them to state. Right now, the flag doesn't do much, apart from extra work.
This is done by adding `TextLayoutManagerExtended::supportsPreparedLayout()`, and `TextLayoutManager::PreparedLayout` types, to shim between platforms, then on Android, we add a `PreparedLayout`, which is for now just an Android layout, with extra field (`maxNumberOfLines`, for some reason not exposed on recent versions).
Android `TextLayoutManager` java side is split a little bit, so that we reuse all the existing logic for prepared layouts. I tried to set up the boundary, so that we don't reserialize a MapBuffer after preparation, and for simplicity, this means source of truth for attachment count, and attachment sizes, now lives on the layout. This means we need to change boundary a bit, where we are no longer able to pass in a buffer to fill from C++ side of attachment positions.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D73970149
fbshipit-source-id: ff71c227e062c16fe52a4eb3ba2acbebf3d96e56
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51039
We added a feature flag in case this broke things. Its been about 4 months now with now issues, I think we can clean this up.
Changelog: [Android][Fixed] - Can now focus TextInput with keyboard
Reviewed By: NickGerleman
Differential Revision: D73954790
fbshipit-source-id: 4682cf709aa2f34ba69e76a35d07a908edb28f23
Summary:
This PR introduces a concise Kotlin DSL for constructing `ReadableMap` and `ReadableArray` in Android native modules:
- Adds `buildReadableMap { … }` and `buildReadableArray { … }` functions, modeled after Kotlin’s `buildMap`/`buildList` APIs.
- Wraps `Arguments.createMap()` / `Arguments.createArray()` in a type-safe, nested DSL to reduce boilerplate and prevent errors.
- Improves readability and maintainability when assembling nested map/array structures for React Native bridges.
Current code like:
```kotlin
val map = Arguments.createMap().apply {
putString("name", user.name)
putInt("age", user.age)
// …
}
```
can now be written as:
```kotlin
val userMap = buildReadableMap {
put("name", user.name)
put("age", user.age)
put("scores") {
user.scores.forEach { add(it) }
}
}
```
This feature proposal also written in [[Android] Support Collection DSL](https://github.com/react-native-community/discussions-and-proposals/issues/899)
## Changelog:
[Android] [Added] - Collections DSL functions for Kotlin(`buildReadableMap`, `buildReadableArray`)
Pull Request resolved: https://github.com/facebook/react-native/pull/51042
Test Plan:
### Run Unit Test
```shell
cd packages/react-native/ReactAndroid
./gradlew :ReactAndroid:unitTest
```
Ensure all tests in `src/test/java/.../ReadableMapBuilderTest.kt` and `ReadableArrayBuilderTest.kt` pass.
Reviewed By: javache
Differential Revision: D73986390
Pulled By: cortinico
fbshipit-source-id: b9f94327646bcb6e0190cdd06dfb9bb5eaa6375c
Summary:
Static code analysis detected several redundant constructs across the codebase. Most of the ones fixed here are marked as warnings/weak warnings, likely code smells post-migration from Java.
Doing a small round to clean up some of them.
## Changelog:
[INTERNAL] - Kotlin: Clean up redundant constructs
Pull Request resolved: https://github.com/facebook/react-native/pull/51061
Test Plan:
```sh
yarn android
yarn test-android
```
Reviewed By: rshest
Differential Revision: D74056259
Pulled By: javache
fbshipit-source-id: 04f7ce7ce7b4f6063c8e1712840a44fd91d3b9e1
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51040
## Resubmit
We were previously only checking for `maxNumberOfLines` of `ReactConstants.UNSET` (-1), but it may also be `0` to signify unset from other checks (wut), and different versions of Android would handle this case of `maxLines={0}` differently.
The resubmission adds an explicit check for zero here as well.
```
if (ReactNativeFeatureFlags.incorporateMaxLinesDuringAndroidLayout()) {
if (maxNumberOfLines != ReactConstants.UNSET && maxNumberOfLines != 0) {
builder.setEllipsize(ellipsizeMode).setMaxLines(maxNumberOfLines);
}
}
```
## Previous
Right now, we fully layout text, then use max lines to determine a metric to use when calculating size.
Android API 23+ which we fully target allows incorporating ellipsization and maxlines directly into the layout. This will let us directly draw the layout when using maxLines later. This may also let Android optimize line-breaking a bit, when we hit truncation.
Special care is taken not to set this when we are in `adjustsFontSizeToFit` path, so that line count will flow over, signifing overflow.
I think the main user-facing change is that `onTextLayout` events will have measures post-ellipsization.
Changelog:
[Android][Changed] - Incorporate maxLines and ellipsization into text layout
Reviewed By: lenaic, joevilches
Differential Revision: D73953691
fbshipit-source-id: 2e08faab5bb9eda90a126545571bb441ea1ece39
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51037
## Changelog:
[Android] [Changed] - Make mHybridData in CxxReactPackage protected
In some cases subclass needs to override it in constructor
Reviewed By: javache
Differential Revision: D73894471
fbshipit-source-id: 7958f9b88841a0201d39e49fba09af76927e5737
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51035
This is causing some problems with older versions of Android. Let's back out for now.
Changelog: [Internal]
Reviewed By: joevilches
Differential Revision: D73950625
fbshipit-source-id: 424dfc1216ae811e1e287774c6ac5d0c9ba5aa17
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51013
There's no need to use a singleton pattern here, we can just use a Kotlin object.
Changelog: [Android][Removed] Deprecated `ResourceDrawableIdHelper.instance`
Reviewed By: Abbondanzo
Differential Revision: D73923281
fbshipit-source-id: f46e125ce595fe4506b9fb5aa471109f5ba150f0
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51007
Right now, we fully layout text, then use max lines to determine a metric to use when calculating size.
Android API 23+ which we fully target allows incorporating ellipsization and maxlines directly into the layout. This will let us directly draw the layout when using maxLines later. This may also let Android optimize line-breaking a bit, when we hit truncation.
Special care is taken not to set this when we are in `adjustsFontSizeToFit` path, so that line count will flow over, signifing overflow.
I think the main user-facing change is that `onTextLayout` events will have measures post-ellipsization.
Changelog:
[Android][Changed] - Incorporate maxLines and ellipsization into text layout
Reviewed By: joevilches
Differential Revision: D73811573
fbshipit-source-id: df83295d0902ae8b043ce57b06cbb9c8f0c194fc
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50970
__onAnimatedValueUpdateReceived is called from 2 places.
It is called from the onAnimatedValueUpdate subscription where the source of the values comes from here: https://fburl.com/8v2cwd2x with getValue() returning the offset + value components combined.
It's also called from in the animation end callback here: https://fburl.com/h36xy2nw where the source of this value comes from https://fburl.com/sud7m7st. In this case it's accessing `nodeValue` directly rather than calling getValue() and so it only includes the value component.
In this diff we pass both the value and offset in both onAnimatedValueUpdate callbacks as well as endCallback.
This allows us to separate the value from the offset on the JS side and ensures we have the latest offset value from native
Changelog: [Android][Fixed] - Sync offset and value from native -> js in separate fields
Reviewed By: zeyap
Differential Revision: D73795619
fbshipit-source-id: e8ed234497e3fcaf9d2a137aa1e17ca8d0f76d97
Summary:
This PR aims to migrate ViewGroupManager to kotlin as part of https://github.com/facebook/react-native/issues/50513
## Changelog:
[ANDROID][CHANGED]Migrate ViewGroupManager to kotlin
Pull Request resolved: https://github.com/facebook/react-native/pull/50895
Test Plan: Tested with RN tester with old and new arch
Reviewed By: javache
Differential Revision: D73770843
Pulled By: cortinico
fbshipit-source-id: 45959a8bf512b3590ca8bc64dac281e13fa41ca3
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50850
This prop will be used to enable screen reader focusability without allowing keyboard focus. Mostly a quality of life prop for product engineers and maps 1:1 to Android
Changelog: [Android][Added] - Expose Android's screenReaderFocusable prop
Reviewed By: javache
Differential Revision: D73382051
fbshipit-source-id: 8171b9d24a735dd42d54abe4537fb487bdd011b7
Summary:
Rewrite of the Inspector class from Java to Kotlin in scope of https://github.com/facebook/react-native/issues/50513
## Changelog:
[ANDROID] [CHANGED] - Migrated Inspector to Kotlin
Pull Request resolved: https://github.com/facebook/react-native/pull/50947
Test Plan: Tested using RNTester app, on both old and new arch, and tested by navigating to multiple pages
Reviewed By: cortinico
Differential Revision: D73767386
Pulled By: javache
fbshipit-source-id: e0098568aa0ed9863503e206a88d3b171c8f9966
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50855
This diff addresses a crash caused by view duplication in React Native Android. The issue occurred when a view was not already clipped and was laid out again, resulting in duplicated views.
This problem was particularly noticeable when using nested FlatLists, which triggered a custom focus search with an incomplete and buggy duplicated FlatList container view.
The fix involves preventing the duplication of views by checking if a view is clipped already before laying it out again. Additionally, this diff includes two other improvements:
- Preventing clipping issues: When a view is nested within a non-ReactClippingViewGroup ancestor, focus searching would fail due to the needUpdateClippingRecursive logic only running on instances of ReactClippingViewGroup. By excluding these ancestors, we ensure that the next focusable view can be properly excluded from being clipped.
- Minor fix: A minor fix was made to prevent potential issues in deeply nested cases.
- Add a Kill switch with a feature flag and mobile config combo.
Reviewed By: joevilches
Differential Revision: D73471780
fbshipit-source-id: efbb968600f21b24ab1fa32222d555f346fb336e
Summary:
Rewrite of JSBundleLoader from Java to Kotlin in scope of https://github.com/facebook/react-native/issues/50513
## Changelog:
[ANDROID] [CHANGED] - Migrated JSBundleLoader to Kotlin
<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:
[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message
For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
Pull Request resolved: https://github.com/facebook/react-native/pull/50911
Test Plan: Tested using RNTester app, on both old and new arch, and tested by navigating to multiple pages
Reviewed By: cortinico
Differential Revision: D73649145
Pulled By: javache
fbshipit-source-id: 7ef1fc1ea1c53a8b914ae1aada1966e64b4c3d80
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50920
We construct this from JNI, which doesn't care about visibility, and then only want to expose `StateWrapper` as the public interface.
Changelog:
[Android][Removed] - Make StateWrapperImpl Internal
Reviewed By: Abbondanzo
Differential Revision: D73161592
fbshipit-source-id: b787e31e190dc52a02d73cadfa77b1c1defb9703
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50870
As explained in the doc block, now that ReactInstance is in Kotlin we can move this logic to StackTraceHelper and migrate it to Kotlin
Changelog: [Internal]
Reviewed By: alanleedev
Differential Revision: D73503879
fbshipit-source-id: 38a9ff346e00d68bbc3c383834e2a1763dbba9b8
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50879
The view for a view manager should not be nullable. Let's fix that.
These are also all bound specifically to `ReactTextView` instead of the generic constraint, so I just changed the constraint. Really this should just be totally merged with `ReactTextViewManager`.
Changelog: [Internal]
Reviewed By: cortinico, rshest
Differential Revision: D73453631
fbshipit-source-id: 74bcadeef0e83a719dfe2b989784501575b58168
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/49446
On Android, by default, every EditText accepts `DragEvent` and will automatically focus themselves to accept these data. In some rare cases, it might not be desirable to allow data from arbitrary drag and drop events to be pasted into a text input.
This change adds a new prop `acceptDragAndDropTypes` to do exactly that: reject drag and drop events by telling the system to ignore certain types of drag data and, by proxy, disabling behavior that automatically focuses the text input.
The prop accepts a subset of MIME types supported by Android as documented [here](https://developer.android.com/reference/android/content/ClipDescription#MIMETYPE_TEXT_HTML).
It's important to note that this is an experimental prop, as is evident by the `experimental_` prefix on the JS side. Its signature could change before the prop has fully matured, use at your own risk
Changelog: [Android][Added] - Add new prop for filtering drag and drop targeting to text inputs
Reviewed By: javache
Differential Revision: D69674225
fbshipit-source-id: 4dbbdd81bb0f394b6206da5a377c75ea71671626
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50827
This diff addresses a crash caused by view duplication in React Native Android. The issue occurred when a view was not already clipped and was laid out again, resulting in duplicated views.
This problem was particularly noticeable when using nested FlatLists, which triggered a custom focus search with an incomplete and buggy duplicated FlatList container view.
The fix involves preventing the duplication of views by checking if a view is clipped already before laying it out again. Additionally, this diff includes two other improvements:
- Preventing clipping issues: When a view is nested within a non-ReactClippingViewGroup ancestor, focus searching would fail due to the needUpdateClippingRecursive logic only running on instances of ReactClippingViewGroup. By excluding these ancestors, we ensure that the next focusable view can be properly excluded from being clipped.
- Minor fix: A minor fix was made to prevent potential issues in deeply nested cases.
- Add a Kill switch with a feature flag and mobile config combo. For Facebook we can kill through MC and for all other apps we can kill with the feature flag default value
Changelog: [Internal]
Reviewed By: joevilches
Differential Revision: D73213775
fbshipit-source-id: 51a667a0c22eb35f0ec46ac4cbe430e2e62b407b