From 1e0bbb80ce0c0a01ed2713e603bc0b1c9499466a Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 9 Jun 2025 20:40:46 -0400 Subject: [PATCH 01/10] [0.79] Fix broken focus behavior on TextInput in older Android versions --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +-- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +--- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +---- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../react/views/textinput/ReactEditText.java | 55 +++++++------------ .../textinput/ReactTextInputManager.java | 2 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +----- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 +-- .../ReactNativeFeatureFlagsAccessor.cpp | 34 +++--------- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 +--- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +-- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 10 ---- .../featureflags/ReactNativeFeatureFlags.js | 7 +-- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 22 files changed, 47 insertions(+), 180 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 19b3394dbd4..9bb269e321c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -250,12 +250,6 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useAlwaysAvailableJSErrorHandling(): Boolean = accessor.useAlwaysAvailableJSErrorHandling() - /** - * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. - */ - @JvmStatic - public fun useEditTextStockAndroidFocusBehavior(): Boolean = accessor.useEditTextStockAndroidFocusBehavior() - /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 3e2792c8d08..6041c2ad940 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0496ecf3d1e5d8a2e6d4d594aca806d0>> + * @generated SignedSource<<9ecb711480b7d6c22bac380c28d035bc>> */ /** @@ -57,7 +57,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null - private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null private var useFabricInteropCache: Boolean? = null private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null @@ -399,15 +398,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } - override fun useEditTextStockAndroidFocusBehavior(): Boolean { - var cached = useEditTextStockAndroidFocusBehaviorCache - if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.useEditTextStockAndroidFocusBehavior() - useEditTextStockAndroidFocusBehaviorCache = cached - } - return cached - } - override fun useFabricInterop(): Boolean { var cached = useFabricInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index c1a6f42f24f..88c0f481470 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<2151e5ec5d04924e742f37b527dc23b9>> */ /** @@ -102,8 +102,6 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useAlwaysAvailableJSErrorHandling(): Boolean - @DoNotStrip @JvmStatic public external fun useEditTextStockAndroidFocusBehavior(): Boolean - @DoNotStrip @JvmStatic public external fun useFabricInterop(): Boolean @DoNotStrip @JvmStatic public external fun useNativeViewConfigsInBridgelessMode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 8f33f72f796..4b29a9f3cb1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<56f86a3a0c0bbf453cf45a0db541ef54>> */ /** @@ -97,8 +97,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useAlwaysAvailableJSErrorHandling(): Boolean = false - override fun useEditTextStockAndroidFocusBehavior(): Boolean = true - override fun useFabricInterop(): Boolean = false override fun useNativeViewConfigsInBridgelessMode(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 399a1788f74..a3a143303ed 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8f5180a0ef154c083ac38d28e650ee11>> + * @generated SignedSource<<5b016fd6298477856116736e37c37c6f>> */ /** @@ -61,7 +61,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null - private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null private var useFabricInteropCache: Boolean? = null private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null @@ -440,16 +439,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } - override fun useEditTextStockAndroidFocusBehavior(): Boolean { - var cached = useEditTextStockAndroidFocusBehaviorCache - if (cached == null) { - cached = currentProvider.useEditTextStockAndroidFocusBehavior() - accessedFeatureFlags.add("useEditTextStockAndroidFocusBehavior") - useEditTextStockAndroidFocusBehaviorCache = cached - } - return cached - } - override fun useFabricInterop(): Boolean { var cached = useFabricInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 79b76152ea5..a24b14f0079 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<33571f99b1f78fbc62cecfca5f8351fa>> + * @generated SignedSource<> */ /** @@ -97,8 +97,6 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useAlwaysAvailableJSErrorHandling(): Boolean - @DoNotStrip public fun useEditTextStockAndroidFocusBehavior(): Boolean - @DoNotStrip public fun useFabricInterop(): Boolean @DoNotStrip public fun useNativeViewConfigsInBridgelessMode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 42f238363e8..e55a3ab1b17 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -36,6 +36,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -146,9 +147,6 @@ public class ReactEditText extends AppCompatEditText { public ReactEditText(Context context) { super(context); - if (!ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { - setFocusableInTouchMode(false); - } mInputMethodManager = (InputMethodManager) @@ -191,9 +189,7 @@ public class ReactEditText extends AppCompatEditText { // selection on accessibility click to undo that. setSelection(length); } - return ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior() - ? requestFocusProgramatically() - : requestFocusInternal(); + return requestFocusProgramatically(); } return super.performAccessibilityAction(host, action, args); } @@ -341,29 +337,28 @@ public class ReactEditText extends AppCompatEditText { return super.onTextContextMenuItem(id); } - @Override - public void clearFocus() { - boolean useStockFocusBehavior = ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior(); - if (!useStockFocusBehavior) { - setFocusableInTouchMode(false); + public void clearFocusAndMaybeRefocus() { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P || !isInTouchMode()) { + super.clearFocus(); + } else { + // Avoid refocusing to a new view on old versions of Android by default + // by preventing `requestFocus()` on the rootView from moving focus to any child. + // https://cs.android.com/android/_/android/platform/frameworks/base/+/bdc66cb5a0ef513f4306edf9156cc978b08e06e4 + ViewGroup rootViewGroup = (ViewGroup)getRootView(); + int oldDescendantFocusability = rootViewGroup.getDescendantFocusability(); + rootViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + super.clearFocus(); + rootViewGroup.setDescendantFocusability(oldDescendantFocusability); } - super.clearFocus(); + hideSoftKeyboard(); } - @Override - public boolean requestFocus(int direction, Rect previouslyFocusedRect) { - // This is a no-op so that when the OS calls requestFocus(), nothing will happen. ReactEditText - // is a controlled component, which means its focus is controlled by JS, with two exceptions: - // autofocus when it's attached to the window, and responding to accessibility events. In both - // of these cases, we call requestFocusInternal() directly. - return ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior() - ? super.requestFocus(direction, previouslyFocusedRect) - : isFocused(); + /* package */ void clearFocusFromJS() { + clearFocusAndMaybeRefocus(); } private boolean requestFocusInternal() { - setFocusableInTouchMode(true); // We must explicitly call this method on the super class; if we call requestFocus() without // any arguments, it will call into the overridden requestFocus(int, Rect) above, which no-ops. boolean focused = super.requestFocus(View.FOCUS_DOWN, null); @@ -656,15 +651,7 @@ public class ReactEditText extends AppCompatEditText { // VisibleForTesting from {@link TextInputEventsTestCase}. public void requestFocusFromJS() { - if (ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { - requestFocusProgramatically(); - } else { - requestFocusInternal(); - } - } - - /* package */ void clearFocusFromJS() { - clearFocus(); + requestFocusProgramatically(); } // VisibleForTesting from {@link TextInputEventsTestCase}. @@ -1107,11 +1094,7 @@ public class ReactEditText extends AppCompatEditText { } if (mAutoFocus && !mDidAttachToWindow) { - if (ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { - requestFocusProgramatically(); - } else { - requestFocusInternal(); - } + requestFocusProgramatically(); } mDidAttachToWindow = true; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index f18e569c923..c93107684a7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -1164,7 +1164,7 @@ public class ReactTextInputManager extends BaseViewManager> + * @generated SignedSource<> */ /** @@ -261,12 +261,6 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } - bool useEditTextStockAndroidFocusBehavior() override { - static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useEditTextStockAndroidFocusBehavior"); - return method(javaProvider_); - } - bool useFabricInterop() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useFabricInterop"); @@ -498,11 +492,6 @@ bool JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling( return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling(); } -bool JReactNativeFeatureFlagsCxxInterop::useEditTextStockAndroidFocusBehavior( - facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior(); -} - bool JReactNativeFeatureFlagsCxxInterop::useFabricInterop( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useFabricInterop(); @@ -680,9 +669,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useAlwaysAvailableJSErrorHandling", JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling), - makeNativeMethod( - "useEditTextStockAndroidFocusBehavior", - JReactNativeFeatureFlagsCxxInterop::useEditTextStockAndroidFocusBehavior), makeNativeMethod( "useFabricInterop", JReactNativeFeatureFlagsCxxInterop::useFabricInterop), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 925a31a7166..7c104c10737 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -141,9 +141,6 @@ class JReactNativeFeatureFlagsCxxInterop static bool useAlwaysAvailableJSErrorHandling( facebook::jni::alias_ref); - static bool useEditTextStockAndroidFocusBehavior( - facebook::jni::alias_ref); - static bool useFabricInterop( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index f0efac973d0..992998a349d 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<661a4193f9ba7af0c963bc13751deb15>> + * @generated SignedSource<<1c90106ded5dc5f08cdec4dede695341>> */ /** @@ -174,10 +174,6 @@ bool ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling() { return getAccessor().useAlwaysAvailableJSErrorHandling(); } -bool ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior() { - return getAccessor().useEditTextStockAndroidFocusBehavior(); -} - bool ReactNativeFeatureFlags::useFabricInterop() { return getAccessor().useFabricInterop(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 35afb5835d8..ca53dff33e3 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<53e965423f2957b37e0470c607cc45a4>> + * @generated SignedSource<> */ /** @@ -224,11 +224,6 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useAlwaysAvailableJSErrorHandling(); - /** - * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. - */ - RN_EXPORT static bool useEditTextStockAndroidFocusBehavior(); - /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 6c494257b4d..9c075b6f9b2 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5ff3ac57eb17d9b6642d98f2fc35bd9d>> + * @generated SignedSource<> */ /** @@ -695,24 +695,6 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::useEditTextStockAndroidFocusBehavior() { - auto flagValue = useEditTextStockAndroidFocusBehavior_.load(); - - if (!flagValue.has_value()) { - // This block is not exclusive but it is not necessary. - // If multiple threads try to initialize the feature flag, we would only - // be accessing the provider multiple times but the end state of this - // instance and the returned flag value would be the same. - - markFlagAsAccessed(37, "useEditTextStockAndroidFocusBehavior"); - - flagValue = currentProvider_->useEditTextStockAndroidFocusBehavior(); - useEditTextStockAndroidFocusBehavior_ = flagValue; - } - - return flagValue.value(); -} - bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { auto flagValue = useFabricInterop_.load(); @@ -722,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useFabricInterop"); + markFlagAsAccessed(37, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -740,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(38, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -758,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(39, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -776,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "useRawPropsJsiValue"); + markFlagAsAccessed(40, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -794,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useShadowNodeStateOnClone"); + markFlagAsAccessed(41, "useShadowNodeStateOnClone"); flagValue = currentProvider_->useShadowNodeStateOnClone(); useShadowNodeStateOnClone_ = flagValue; @@ -812,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useTurboModuleInterop"); + markFlagAsAccessed(42, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -830,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useTurboModules"); + markFlagAsAccessed(43, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 48e75d266b0..ea0cd805517 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<267385c8df88a5d1eb7f1e2478209d39>> + * @generated SignedSource<<978f828e7368b8802f8eaa5194e86e2f>> */ /** @@ -69,7 +69,6 @@ class ReactNativeFeatureFlagsAccessor { bool traceTurboModulePromiseRejectionsOnAndroid(); bool updateRuntimeShadowNodeReferencesOnCommit(); bool useAlwaysAvailableJSErrorHandling(); - bool useEditTextStockAndroidFocusBehavior(); bool useFabricInterop(); bool useNativeViewConfigsInBridgelessMode(); bool useOptimizedEventBatchingOnAndroid(); @@ -88,7 +87,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 45> accessedFeatureFlags_; + std::array, 44> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> disableMountItemReorderingAndroid_; @@ -127,7 +126,6 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> traceTurboModulePromiseRejectionsOnAndroid_; std::atomic> updateRuntimeShadowNodeReferencesOnCommit_; std::atomic> useAlwaysAvailableJSErrorHandling_; - std::atomic> useEditTextStockAndroidFocusBehavior_; std::atomic> useFabricInterop_; std::atomic> useNativeViewConfigsInBridgelessMode_; std::atomic> useOptimizedEventBatchingOnAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index e81708e657d..bf4c5451e37 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<48bb4ea50c42676aee161ea1594a6aec>> + * @generated SignedSource<<643c1fd24fbc1a77ef109e712023f9d5>> */ /** @@ -175,10 +175,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } - bool useEditTextStockAndroidFocusBehavior() override { - return true; - } - bool useFabricInterop() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index cfd48f0bf4f..2d71d1dfb5f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -378,15 +378,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::useAlwaysAvailableJSErrorHandling(); } - bool useEditTextStockAndroidFocusBehavior() override { - auto value = values_["useEditTextStockAndroidFocusBehavior"]; - if (!value.isNull()) { - return value.getBool(); - } - - return ReactNativeFeatureFlagsDefaults::useEditTextStockAndroidFocusBehavior(); - } - bool useFabricInterop() override { auto value = values_["useFabricInterop"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 8efd2e70070..ba1782d6a6b 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<4db2ff36701f0dbcd3dd59fa5879a612>> */ /** @@ -62,7 +62,6 @@ class ReactNativeFeatureFlagsProvider { virtual bool traceTurboModulePromiseRejectionsOnAndroid() = 0; virtual bool updateRuntimeShadowNodeReferencesOnCommit() = 0; virtual bool useAlwaysAvailableJSErrorHandling() = 0; - virtual bool useEditTextStockAndroidFocusBehavior() = 0; virtual bool useFabricInterop() = 0; virtual bool useNativeViewConfigsInBridgelessMode() = 0; virtual bool useOptimizedEventBatchingOnAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index cf4b98fd8c0..7afdd1d4758 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<76f1f689940817c1df6ace2f8dd062e7>> + * @generated SignedSource<<4f6ee8b8bae8ea84fab77eb9feb63f9d>> */ /** @@ -229,11 +229,6 @@ bool NativeReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling( return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling(); } -bool NativeReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior( - jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior(); -} - bool NativeReactNativeFeatureFlags::useFabricInterop( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useFabricInterop(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 2c6765db1f1..77c80a0b94b 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<0009cf8a05d254e3695e7ce57fc5f8af>> */ /** @@ -111,8 +111,6 @@ class NativeReactNativeFeatureFlags bool useAlwaysAvailableJSErrorHandling(jsi::Runtime& runtime); - bool useEditTextStockAndroidFocusBehavior(jsi::Runtime& runtime); - bool useFabricInterop(jsi::Runtime& runtime); bool useNativeViewConfigsInBridgelessMode(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 2403266d4a8..671b3536dff 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -440,16 +440,6 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, - useEditTextStockAndroidFocusBehavior: { - defaultValue: true, - metadata: { - description: - 'If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior.', - expectedReleaseValue: true, - purpose: 'release', - }, - ossReleaseStage: 'none', - }, useFabricInterop: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 3b4b290483a..530444b1604 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5b1d3ba6712de7a927eeeb8602ee2a8f>> + * @generated SignedSource<> * @flow strict */ @@ -86,7 +86,6 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ traceTurboModulePromiseRejectionsOnAndroid: Getter, updateRuntimeShadowNodeReferencesOnCommit: Getter, useAlwaysAvailableJSErrorHandling: Getter, - useEditTextStockAndroidFocusBehavior: Getter, useFabricInterop: Getter, useNativeViewConfigsInBridgelessMode: Getter, useOptimizedEventBatchingOnAndroid: Getter, @@ -323,10 +322,6 @@ export const updateRuntimeShadowNodeReferencesOnCommit: Getter = create * In Bridgeless mode, use the always available javascript error reporting pipeline. */ export const useAlwaysAvailableJSErrorHandling: Getter = createNativeFlagGetter('useAlwaysAvailableJSErrorHandling', false); -/** - * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. - */ -export const useEditTextStockAndroidFocusBehavior: Getter = createNativeFlagGetter('useEditTextStockAndroidFocusBehavior', true); /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index f61e2c7d42d..7fb3cc6ee73 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<2499cbe243c048d9e3647342ebec3544>> * @flow strict */ @@ -61,7 +61,6 @@ export interface Spec extends TurboModule { +traceTurboModulePromiseRejectionsOnAndroid?: () => boolean; +updateRuntimeShadowNodeReferencesOnCommit?: () => boolean; +useAlwaysAvailableJSErrorHandling?: () => boolean; - +useEditTextStockAndroidFocusBehavior?: () => boolean; +useFabricInterop?: () => boolean; +useNativeViewConfigsInBridgelessMode?: () => boolean; +useOptimizedEventBatchingOnAndroid?: () => boolean; From da6115c6d72a8a07abf53d88f8f6520b8912284b Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Tue, 10 Jun 2025 10:20:08 -0400 Subject: [PATCH 02/10] remove unused fn --- .../facebook/react/views/textinput/ReactEditText.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index e55a3ab1b17..9226a679ae6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -358,17 +358,6 @@ public class ReactEditText extends AppCompatEditText { clearFocusAndMaybeRefocus(); } - private boolean requestFocusInternal() { - // We must explicitly call this method on the super class; if we call requestFocus() without - // any arguments, it will call into the overridden requestFocus(int, Rect) above, which no-ops. - boolean focused = super.requestFocus(View.FOCUS_DOWN, null); - if (getShowSoftInputOnFocus()) { - showSoftKeyboard(); - } - - return focused; - } - // For cases like autoFocus, or ref.focus() where we request focus programatically and not through // interacting with the EditText directly (like clicking on it). We cannot use stock // requestFocus() because it will not pop up the soft keyboard, only clicking the input will do From 69349ebdd5fa36addc61fd8a8cca89583a1b245a Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 10 Jun 2025 16:09:47 +0100 Subject: [PATCH 03/10] Revert "remove unused fn" This reverts commit da6115c6d72a8a07abf53d88f8f6520b8912284b. --- .../facebook/react/views/textinput/ReactEditText.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 9226a679ae6..e55a3ab1b17 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -358,6 +358,17 @@ public class ReactEditText extends AppCompatEditText { clearFocusAndMaybeRefocus(); } + private boolean requestFocusInternal() { + // We must explicitly call this method on the super class; if we call requestFocus() without + // any arguments, it will call into the overridden requestFocus(int, Rect) above, which no-ops. + boolean focused = super.requestFocus(View.FOCUS_DOWN, null); + if (getShowSoftInputOnFocus()) { + showSoftKeyboard(); + } + + return focused; + } + // For cases like autoFocus, or ref.focus() where we request focus programatically and not through // interacting with the EditText directly (like clicking on it). We cannot use stock // requestFocus() because it will not pop up the soft keyboard, only clicking the input will do From 81ed5e1ef074cd25c0fd1f4f3dd05c28272f6267 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 10 Jun 2025 16:09:58 +0100 Subject: [PATCH 04/10] Revert "[0.79] Fix broken focus behavior on TextInput in older Android versions" This reverts commit 1e0bbb80ce0c0a01ed2713e603bc0b1c9499466a. --- .../featureflags/ReactNativeFeatureFlags.kt | 8 ++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../react/views/textinput/ReactEditText.java | 55 ++++++++++++------- .../textinput/ReactTextInputManager.java | 2 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 ++- .../ReactNativeFeatureFlagsAccessor.cpp | 34 +++++++++--- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 +++- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 ++- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 10 ++++ .../featureflags/ReactNativeFeatureFlags.js | 7 ++- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 22 files changed, 180 insertions(+), 47 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 9bb269e321c..19b3394dbd4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -250,6 +250,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useAlwaysAvailableJSErrorHandling(): Boolean = accessor.useAlwaysAvailableJSErrorHandling() + /** + * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. + */ + @JvmStatic + public fun useEditTextStockAndroidFocusBehavior(): Boolean = accessor.useEditTextStockAndroidFocusBehavior() + /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 6041c2ad940..3e2792c8d08 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<9ecb711480b7d6c22bac380c28d035bc>> + * @generated SignedSource<<0496ecf3d1e5d8a2e6d4d594aca806d0>> */ /** @@ -57,6 +57,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null + private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null private var useFabricInteropCache: Boolean? = null private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null @@ -398,6 +399,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun useEditTextStockAndroidFocusBehavior(): Boolean { + var cached = useEditTextStockAndroidFocusBehaviorCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.useEditTextStockAndroidFocusBehavior() + useEditTextStockAndroidFocusBehaviorCache = cached + } + return cached + } + override fun useFabricInterop(): Boolean { var cached = useFabricInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 88c0f481470..c1a6f42f24f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2151e5ec5d04924e742f37b527dc23b9>> + * @generated SignedSource<> */ /** @@ -102,6 +102,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useAlwaysAvailableJSErrorHandling(): Boolean + @DoNotStrip @JvmStatic public external fun useEditTextStockAndroidFocusBehavior(): Boolean + @DoNotStrip @JvmStatic public external fun useFabricInterop(): Boolean @DoNotStrip @JvmStatic public external fun useNativeViewConfigsInBridgelessMode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 4b29a9f3cb1..8f33f72f796 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<56f86a3a0c0bbf453cf45a0db541ef54>> + * @generated SignedSource<> */ /** @@ -97,6 +97,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useAlwaysAvailableJSErrorHandling(): Boolean = false + override fun useEditTextStockAndroidFocusBehavior(): Boolean = true + override fun useFabricInterop(): Boolean = false override fun useNativeViewConfigsInBridgelessMode(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index a3a143303ed..399a1788f74 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5b016fd6298477856116736e37c37c6f>> + * @generated SignedSource<<8f5180a0ef154c083ac38d28e650ee11>> */ /** @@ -61,6 +61,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null + private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null private var useFabricInteropCache: Boolean? = null private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null @@ -439,6 +440,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun useEditTextStockAndroidFocusBehavior(): Boolean { + var cached = useEditTextStockAndroidFocusBehaviorCache + if (cached == null) { + cached = currentProvider.useEditTextStockAndroidFocusBehavior() + accessedFeatureFlags.add("useEditTextStockAndroidFocusBehavior") + useEditTextStockAndroidFocusBehaviorCache = cached + } + return cached + } + override fun useFabricInterop(): Boolean { var cached = useFabricInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index a24b14f0079..79b76152ea5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<33571f99b1f78fbc62cecfca5f8351fa>> */ /** @@ -97,6 +97,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useAlwaysAvailableJSErrorHandling(): Boolean + @DoNotStrip public fun useEditTextStockAndroidFocusBehavior(): Boolean + @DoNotStrip public fun useFabricInterop(): Boolean @DoNotStrip public fun useNativeViewConfigsInBridgelessMode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index e55a3ab1b17..42f238363e8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -36,7 +36,6 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -147,6 +146,9 @@ public class ReactEditText extends AppCompatEditText { public ReactEditText(Context context) { super(context); + if (!ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { + setFocusableInTouchMode(false); + } mInputMethodManager = (InputMethodManager) @@ -189,7 +191,9 @@ public class ReactEditText extends AppCompatEditText { // selection on accessibility click to undo that. setSelection(length); } - return requestFocusProgramatically(); + return ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior() + ? requestFocusProgramatically() + : requestFocusInternal(); } return super.performAccessibilityAction(host, action, args); } @@ -337,28 +341,29 @@ public class ReactEditText extends AppCompatEditText { return super.onTextContextMenuItem(id); } - public void clearFocusAndMaybeRefocus() { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P || !isInTouchMode()) { - super.clearFocus(); - } else { - // Avoid refocusing to a new view on old versions of Android by default - // by preventing `requestFocus()` on the rootView from moving focus to any child. - // https://cs.android.com/android/_/android/platform/frameworks/base/+/bdc66cb5a0ef513f4306edf9156cc978b08e06e4 - ViewGroup rootViewGroup = (ViewGroup)getRootView(); - int oldDescendantFocusability = rootViewGroup.getDescendantFocusability(); - rootViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - super.clearFocus(); - rootViewGroup.setDescendantFocusability(oldDescendantFocusability); + @Override + public void clearFocus() { + boolean useStockFocusBehavior = ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior(); + if (!useStockFocusBehavior) { + setFocusableInTouchMode(false); } - + super.clearFocus(); hideSoftKeyboard(); } - /* package */ void clearFocusFromJS() { - clearFocusAndMaybeRefocus(); + @Override + public boolean requestFocus(int direction, Rect previouslyFocusedRect) { + // This is a no-op so that when the OS calls requestFocus(), nothing will happen. ReactEditText + // is a controlled component, which means its focus is controlled by JS, with two exceptions: + // autofocus when it's attached to the window, and responding to accessibility events. In both + // of these cases, we call requestFocusInternal() directly. + return ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior() + ? super.requestFocus(direction, previouslyFocusedRect) + : isFocused(); } private boolean requestFocusInternal() { + setFocusableInTouchMode(true); // We must explicitly call this method on the super class; if we call requestFocus() without // any arguments, it will call into the overridden requestFocus(int, Rect) above, which no-ops. boolean focused = super.requestFocus(View.FOCUS_DOWN, null); @@ -651,7 +656,15 @@ public class ReactEditText extends AppCompatEditText { // VisibleForTesting from {@link TextInputEventsTestCase}. public void requestFocusFromJS() { - requestFocusProgramatically(); + if (ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { + requestFocusProgramatically(); + } else { + requestFocusInternal(); + } + } + + /* package */ void clearFocusFromJS() { + clearFocus(); } // VisibleForTesting from {@link TextInputEventsTestCase}. @@ -1094,7 +1107,11 @@ public class ReactEditText extends AppCompatEditText { } if (mAutoFocus && !mDidAttachToWindow) { - requestFocusProgramatically(); + if (ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { + requestFocusProgramatically(); + } else { + requestFocusInternal(); + } } mDidAttachToWindow = true; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index c93107684a7..f18e569c923 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -1164,7 +1164,7 @@ public class ReactTextInputManager extends BaseViewManager> + * @generated SignedSource<<83b23039ed9fff5109ff3b532648baac>> */ /** @@ -261,6 +261,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool useEditTextStockAndroidFocusBehavior() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useEditTextStockAndroidFocusBehavior"); + return method(javaProvider_); + } + bool useFabricInterop() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useFabricInterop"); @@ -492,6 +498,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling( return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling(); } +bool JReactNativeFeatureFlagsCxxInterop::useEditTextStockAndroidFocusBehavior( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior(); +} + bool JReactNativeFeatureFlagsCxxInterop::useFabricInterop( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useFabricInterop(); @@ -669,6 +680,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useAlwaysAvailableJSErrorHandling", JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling), + makeNativeMethod( + "useEditTextStockAndroidFocusBehavior", + JReactNativeFeatureFlagsCxxInterop::useEditTextStockAndroidFocusBehavior), makeNativeMethod( "useFabricInterop", JReactNativeFeatureFlagsCxxInterop::useFabricInterop), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 7c104c10737..925a31a7166 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -141,6 +141,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool useAlwaysAvailableJSErrorHandling( facebook::jni::alias_ref); + static bool useEditTextStockAndroidFocusBehavior( + facebook::jni::alias_ref); + static bool useFabricInterop( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 992998a349d..f0efac973d0 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1c90106ded5dc5f08cdec4dede695341>> + * @generated SignedSource<<661a4193f9ba7af0c963bc13751deb15>> */ /** @@ -174,6 +174,10 @@ bool ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling() { return getAccessor().useAlwaysAvailableJSErrorHandling(); } +bool ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior() { + return getAccessor().useEditTextStockAndroidFocusBehavior(); +} + bool ReactNativeFeatureFlags::useFabricInterop() { return getAccessor().useFabricInterop(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index ca53dff33e3..35afb5835d8 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<53e965423f2957b37e0470c607cc45a4>> */ /** @@ -224,6 +224,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useAlwaysAvailableJSErrorHandling(); + /** + * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. + */ + RN_EXPORT static bool useEditTextStockAndroidFocusBehavior(); + /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 9c075b6f9b2..6c494257b4d 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5ff3ac57eb17d9b6642d98f2fc35bd9d>> */ /** @@ -695,6 +695,24 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::useEditTextStockAndroidFocusBehavior() { + auto flagValue = useEditTextStockAndroidFocusBehavior_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(37, "useEditTextStockAndroidFocusBehavior"); + + flagValue = currentProvider_->useEditTextStockAndroidFocusBehavior(); + useEditTextStockAndroidFocusBehavior_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { auto flagValue = useFabricInterop_.load(); @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "useFabricInterop"); + markFlagAsAccessed(38, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(39, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(40, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "useRawPropsJsiValue"); + markFlagAsAccessed(41, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "useShadowNodeStateOnClone"); + markFlagAsAccessed(42, "useShadowNodeStateOnClone"); flagValue = currentProvider_->useShadowNodeStateOnClone(); useShadowNodeStateOnClone_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useTurboModuleInterop"); + markFlagAsAccessed(43, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useTurboModules"); + markFlagAsAccessed(44, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index ea0cd805517..48e75d266b0 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<978f828e7368b8802f8eaa5194e86e2f>> + * @generated SignedSource<<267385c8df88a5d1eb7f1e2478209d39>> */ /** @@ -69,6 +69,7 @@ class ReactNativeFeatureFlagsAccessor { bool traceTurboModulePromiseRejectionsOnAndroid(); bool updateRuntimeShadowNodeReferencesOnCommit(); bool useAlwaysAvailableJSErrorHandling(); + bool useEditTextStockAndroidFocusBehavior(); bool useFabricInterop(); bool useNativeViewConfigsInBridgelessMode(); bool useOptimizedEventBatchingOnAndroid(); @@ -87,7 +88,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 44> accessedFeatureFlags_; + std::array, 45> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> disableMountItemReorderingAndroid_; @@ -126,6 +127,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> traceTurboModulePromiseRejectionsOnAndroid_; std::atomic> updateRuntimeShadowNodeReferencesOnCommit_; std::atomic> useAlwaysAvailableJSErrorHandling_; + std::atomic> useEditTextStockAndroidFocusBehavior_; std::atomic> useFabricInterop_; std::atomic> useNativeViewConfigsInBridgelessMode_; std::atomic> useOptimizedEventBatchingOnAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index bf4c5451e37..e81708e657d 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<643c1fd24fbc1a77ef109e712023f9d5>> + * @generated SignedSource<<48bb4ea50c42676aee161ea1594a6aec>> */ /** @@ -175,6 +175,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool useEditTextStockAndroidFocusBehavior() override { + return true; + } + bool useFabricInterop() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 2d71d1dfb5f..cfd48f0bf4f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -378,6 +378,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::useAlwaysAvailableJSErrorHandling(); } + bool useEditTextStockAndroidFocusBehavior() override { + auto value = values_["useEditTextStockAndroidFocusBehavior"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::useEditTextStockAndroidFocusBehavior(); + } + bool useFabricInterop() override { auto value = values_["useFabricInterop"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index ba1782d6a6b..8efd2e70070 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4db2ff36701f0dbcd3dd59fa5879a612>> + * @generated SignedSource<> */ /** @@ -62,6 +62,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool traceTurboModulePromiseRejectionsOnAndroid() = 0; virtual bool updateRuntimeShadowNodeReferencesOnCommit() = 0; virtual bool useAlwaysAvailableJSErrorHandling() = 0; + virtual bool useEditTextStockAndroidFocusBehavior() = 0; virtual bool useFabricInterop() = 0; virtual bool useNativeViewConfigsInBridgelessMode() = 0; virtual bool useOptimizedEventBatchingOnAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 7afdd1d4758..cf4b98fd8c0 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4f6ee8b8bae8ea84fab77eb9feb63f9d>> + * @generated SignedSource<<76f1f689940817c1df6ace2f8dd062e7>> */ /** @@ -229,6 +229,11 @@ bool NativeReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling( return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling(); } +bool NativeReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior(); +} + bool NativeReactNativeFeatureFlags::useFabricInterop( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useFabricInterop(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 77c80a0b94b..2c6765db1f1 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0009cf8a05d254e3695e7ce57fc5f8af>> + * @generated SignedSource<> */ /** @@ -111,6 +111,8 @@ class NativeReactNativeFeatureFlags bool useAlwaysAvailableJSErrorHandling(jsi::Runtime& runtime); + bool useEditTextStockAndroidFocusBehavior(jsi::Runtime& runtime); + bool useFabricInterop(jsi::Runtime& runtime); bool useNativeViewConfigsInBridgelessMode(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 671b3536dff..2403266d4a8 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -440,6 +440,16 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + useEditTextStockAndroidFocusBehavior: { + defaultValue: true, + metadata: { + description: + 'If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior.', + expectedReleaseValue: true, + purpose: 'release', + }, + ossReleaseStage: 'none', + }, useFabricInterop: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 530444b1604..3b4b290483a 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5b1d3ba6712de7a927eeeb8602ee2a8f>> * @flow strict */ @@ -86,6 +86,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ traceTurboModulePromiseRejectionsOnAndroid: Getter, updateRuntimeShadowNodeReferencesOnCommit: Getter, useAlwaysAvailableJSErrorHandling: Getter, + useEditTextStockAndroidFocusBehavior: Getter, useFabricInterop: Getter, useNativeViewConfigsInBridgelessMode: Getter, useOptimizedEventBatchingOnAndroid: Getter, @@ -322,6 +323,10 @@ export const updateRuntimeShadowNodeReferencesOnCommit: Getter = create * In Bridgeless mode, use the always available javascript error reporting pipeline. */ export const useAlwaysAvailableJSErrorHandling: Getter = createNativeFlagGetter('useAlwaysAvailableJSErrorHandling', false); +/** + * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. + */ +export const useEditTextStockAndroidFocusBehavior: Getter = createNativeFlagGetter('useEditTextStockAndroidFocusBehavior', true); /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 7fb3cc6ee73..f61e2c7d42d 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2499cbe243c048d9e3647342ebec3544>> + * @generated SignedSource<> * @flow strict */ @@ -61,6 +61,7 @@ export interface Spec extends TurboModule { +traceTurboModulePromiseRejectionsOnAndroid?: () => boolean; +updateRuntimeShadowNodeReferencesOnCommit?: () => boolean; +useAlwaysAvailableJSErrorHandling?: () => boolean; + +useEditTextStockAndroidFocusBehavior?: () => boolean; +useFabricInterop?: () => boolean; +useNativeViewConfigsInBridgelessMode?: () => boolean; +useOptimizedEventBatchingOnAndroid?: () => boolean; From 2cd074d77a706f4fe4396ffdf87408f781e935a4 Mon Sep 17 00:00:00 2001 From: Nick Lefever Date: Mon, 16 Jun 2025 11:18:51 +0200 Subject: [PATCH 05/10] Disabling `updateRuntimeShadowNodeReferencesOnCommit` by default. (#52013) Co-authored-by: Nick --- .../Libraries/AppDelegate/RCTReactNativeFactory.mm | 4 ---- .../ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android.kt | 2 -- 2 files changed, 6 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm index 232a354bbef..b99e2e7488b 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm @@ -314,10 +314,6 @@ class RCTAppDelegateBridgelessFeatureFlags : public ReactNativeFeatureFlagsDefau { return true; } - bool updateRuntimeShadowNodeReferencesOnCommit() override - { - return true; - } bool useShadowNodeStateOnClone() override { return true; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android.kt index 50282190296..f47d8198fbd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android.kt @@ -18,7 +18,5 @@ public class ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android( override fun useTurboModules(): Boolean = bridgelessEnabled || turboModulesEnabled - override fun updateRuntimeShadowNodeReferencesOnCommit(): Boolean = true - override fun useShadowNodeStateOnClone(): Boolean = true } From ea6abb690e40b1595791f5f6f645b8014117bf0c Mon Sep 17 00:00:00 2001 From: Aswin Andro Date: Thu, 12 Jun 2025 14:28:14 -0700 Subject: [PATCH 06/10] Publish top-level Flow types for `react-native` (#51908) Summary: FIXED Add index.js.flow to npm package files for Flow support Currently, the distributed npm package for react-native does not include the index.js.flow file, which causes all exports to be typed as any when using Flow. This commit adds index.js.flow to the "files" array in package.json, ensuring Flow users receive proper type definitions out of the box. This addresses issues where type checking with Flow fails in React Native projects. ## Changelog: [General][Added] Publish top-level Flow types for `react-native` Pull Request resolved: https://github.com/facebook/react-native/pull/51908 Reviewed By: huntie, necolas Differential Revision: D76292301 Pulled By: robhogan fbshipit-source-id: e56360d3f35af30ef160470181349aac1812e7c1 --- packages/react-native/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 35068704f17..57679f3c97a 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -39,6 +39,7 @@ "gradle.properties", "gradle/libs.versions.toml", "index.js", + "index.flow.js", "interface.js", "jest-preset.js", "jest", From 235ac2cca0b173934d329f3a797f136a219d315f Mon Sep 17 00:00:00 2001 From: Ritesh Shukla Date: Mon, 16 Jun 2025 14:58:42 +0530 Subject: [PATCH 07/10] Fix Dimensions not changing when orientation changes (#51978) This fixes the bug where Dimensions (width and height) are not changing when the orientation changes. --- .../React/CoreModules/RCTDeviceInfo.mm | 70 +++++++++++++------ 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index 6b4fcef8522..d04bda2fe29 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -14,9 +14,7 @@ #import #import #import -#import #import -#import #import #import "CoreModulesPlugins.h" @@ -31,8 +29,13 @@ using namespace facebook::react; NSDictionary *_currentInterfaceDimensions; BOOL _isFullscreen; std::atomic _invalidated; + NSDictionary *_constants; + + __weak UIWindow *_applicationWindow; } +static NSString *const kFrameKeyPath = @"frame"; + @synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -40,14 +43,26 @@ RCT_EXPORT_MODULE() - (instancetype)init { if (self = [super init]) { - [[RCTKeyWindowValuesProxy sharedInstance] startObservingWindowSizeIfNecessary]; + _applicationWindow = RCTKeyWindow(); + [_applicationWindow addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:nil]; } return self; } +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + if ([keyPath isEqualToString:kFrameKeyPath]) { + [self interfaceFrameDidChange]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self]; + } +} + + (BOOL)requiresMainQueueSetup { - return NO; + return YES; } - (dispatch_queue_t)methodQueue @@ -81,7 +96,7 @@ RCT_EXPORT_MODULE() #if TARGET_OS_IOS - _currentInterfaceOrientation = [RCTKeyWindowValuesProxy sharedInstance].currentInterfaceOrientation; + _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceFrameDidChange) @@ -98,6 +113,15 @@ RCT_EXPORT_MODULE() selector:@selector(invalidate) name:RCTBridgeWillInvalidateModulesNotification object:nil]; + + _constants = @{ + @"Dimensions" : [self _exportedDimensions], + // Note: + // This prop is deprecated and will be removed in a future release. + // Please use this only for a quick and temporary solution. + // Use instead. + @"isIPhoneX_deprecated" : @(RCTIsIPhoneNotched()), + }; } - (void)invalidate @@ -120,6 +144,8 @@ RCT_EXPORT_MODULE() [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil]; + [_applicationWindow removeObserver:self forKeyPath:kFrameKeyPath]; + #if TARGET_OS_IOS [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; #endif @@ -132,8 +158,13 @@ static BOOL RCTIsIPhoneNotched() #if TARGET_OS_IOS dispatch_once(&onceToken, ^{ + RCTAssertMainQueue(); + // 20pt is the top safeArea value in non-notched devices - isIPhoneNotched = [RCTWindowSafeAreaProxy sharedInstance].currentSafeAreaInsets.top > 20; + UIWindow *keyWindow = RCTKeyWindow(); + if (keyWindow) { + isIPhoneNotched = keyWindow.safeAreaInsets.top > 20; + } }); #endif @@ -142,11 +173,13 @@ static BOOL RCTIsIPhoneNotched() static NSDictionary *RCTExportedDimensions(CGFloat fontScale) { + RCTAssertMainQueue(); UIScreen *mainScreen = UIScreen.mainScreen; CGSize screenSize = mainScreen.bounds.size; + UIView *mainWindow = RCTKeyWindow(); // We fallback to screen size if a key window is not found. - CGSize windowSize = [RCTKeyWindowValuesProxy sharedInstance].windowSize; + CGSize windowSize = mainWindow ? mainWindow.bounds.size : screenSize; NSDictionary *dimsWindow = @{ @"width" : @(windowSize.width), @@ -170,7 +203,10 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale) RCTAssert(_moduleRegistry, @"Failed to get exported dimensions: RCTModuleRegistry is nil"); RCTAccessibilityManager *accessibilityManager = (RCTAccessibilityManager *)[_moduleRegistry moduleForName:"AccessibilityManager"]; - RCTAssert(accessibilityManager, @"Failed to get exported dimensions: AccessibilityManager is nil"); + // TOOD(T225745315): For some reason, accessibilityManager is nil in some cases. + // We default the fontScale to 1.0 in this case. This should be okay: if we assume + // that accessibilityManager will eventually become available, js will eventually + // be updated with the correct fontScale. CGFloat fontScale = accessibilityManager ? accessibilityManager.multiplier : 1.0; return RCTExportedDimensions(fontScale); } @@ -182,14 +218,7 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale) - (NSDictionary *)getConstants { - return @{ - @"Dimensions" : [self _exportedDimensions], - // Note: - // This prop is deprecated and will be removed in a future release. - // Please use this only for a quick and temporary solution. - // Use instead. - @"isIPhoneX_deprecated" : @(RCTIsIPhoneNotched()), - }; + return _constants; } - (void)didReceiveNewContentSizeMultiplier @@ -209,10 +238,11 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale) - (void)interfaceOrientationDidChange { #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST - UIWindow *keyWindow = RCTKeyWindow(); - UIInterfaceOrientation nextOrientation = keyWindow.windowScene.interfaceOrientation; + UIApplication *application = RCTSharedApplication(); + UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation; - BOOL isRunningInFullScreen = CGRectEqualToRect(keyWindow.frame, keyWindow.screen.bounds); + BOOL isRunningInFullScreen = + CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds); // We are catching here two situations for multitasking view: // a) The app is in Split View and the container gets resized -> !isRunningInFullScreen // b) The app changes to/from fullscreen example: App runs in slide over mode and goes into fullscreen-> @@ -275,4 +305,4 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale) Class RCTDeviceInfoCls(void) { return RCTDeviceInfo.class; -} +} \ No newline at end of file From 129622d9b9ae6e2019f7d8e2707d72283f4914b4 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 13 Jun 2025 03:30:14 -0700 Subject: [PATCH 08/10] Move React Native publishing URLs to Central Portal (#51693) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51693 This moves React Native to use the Central Portal URLs rather than the legacy OSSRH ones. See https://github.com/gradle-nexus/publish-plugin for more context. Changelog: [Internal] [Changed] - Reviewed By: cipolleschi Differential Revision: D75673984 fbshipit-source-id: 1de6746809eed72f232eac0c3fb4d809c2046620 --- build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index e7121937353..edfe503db0a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,6 +54,8 @@ nexusPublishing { sonatype { username.set(sonatypeUsername) password.set(sonatypePassword) + nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/")) + snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/")) } } } From e386b01a8f409a95e788406b9b32b72aad0f91c4 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 13 Jun 2025 10:09:47 -0700 Subject: [PATCH 09/10] Update Nightly URL for newly published versions on central.sonatype.com (#52004) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52004 This is necessary because the snapshots are now going to be published on a different repository: central.sonatype.com. Changelog: [Internal] [Changed] - Reviewed By: cipolleschi Differential Revision: D76596802 fbshipit-source-id: 424fb1134e41502d53b76209fba325c895c79ba8 --- .../main/kotlin/com/facebook/react/utils/DependencyUtils.kt | 2 +- .../kotlin/com/facebook/react/utils/DependencyUtilsTest.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index d9cc0f7be27..beee98a2d04 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -37,7 +37,7 @@ internal object DependencyUtils { } } // We add the snapshot for users on nightlies. - mavenRepoFromUrl("https://oss.sonatype.org/content/repositories/snapshots/") { repo -> + mavenRepoFromUrl("https://central.sonatype.com/repository/maven-snapshots/") { repo -> repo.content { it.excludeGroup("org.webkit") } } repositories.mavenCentral { repo -> diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 155f18b44e0..16973ae47a2 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -45,7 +45,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_containsSnapshotRepo() { - val repositoryURI = URI.create("https://oss.sonatype.org/content/repositories/snapshots/") + val repositoryURI = URI.create("https://central.sonatype.com/repository/maven-snapshots/") val project = createProject() configureRepositories(project) @@ -176,7 +176,7 @@ class DependencyUtilsTest { @Test fun configureRepositories_snapshotRepoHasHigherPriorityThanMavenCentral() { - val repositoryURI = URI.create("https://oss.sonatype.org/content/repositories/snapshots/") + val repositoryURI = URI.create("https://central.sonatype.com/repository/maven-snapshots/") val mavenCentralURI = URI.create("https://repo.maven.apache.org/maven2/") val project = createProject() From 0ebaaed281fcfa01b20a17a461c1d0b489a7f0a2 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 16 Jun 2025 06:05:26 -0400 Subject: [PATCH 10/10] Fix broken focus behavior for TextInput in older Android versions (< 9) (#51964) --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +-- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +--- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +---- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../react/views/textinput/ReactEditText.java | 55 +++++++------------ .../textinput/ReactTextInputManager.java | 2 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +----- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 +-- .../ReactNativeFeatureFlagsAccessor.cpp | 34 +++--------- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 +--- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +-- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 10 ---- .../featureflags/ReactNativeFeatureFlags.js | 7 +-- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 22 files changed, 47 insertions(+), 180 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 19b3394dbd4..9bb269e321c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -250,12 +250,6 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useAlwaysAvailableJSErrorHandling(): Boolean = accessor.useAlwaysAvailableJSErrorHandling() - /** - * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. - */ - @JvmStatic - public fun useEditTextStockAndroidFocusBehavior(): Boolean = accessor.useEditTextStockAndroidFocusBehavior() - /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 3e2792c8d08..6041c2ad940 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0496ecf3d1e5d8a2e6d4d594aca806d0>> + * @generated SignedSource<<9ecb711480b7d6c22bac380c28d035bc>> */ /** @@ -57,7 +57,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null - private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null private var useFabricInteropCache: Boolean? = null private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null @@ -399,15 +398,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } - override fun useEditTextStockAndroidFocusBehavior(): Boolean { - var cached = useEditTextStockAndroidFocusBehaviorCache - if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.useEditTextStockAndroidFocusBehavior() - useEditTextStockAndroidFocusBehaviorCache = cached - } - return cached - } - override fun useFabricInterop(): Boolean { var cached = useFabricInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index c1a6f42f24f..88c0f481470 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<2151e5ec5d04924e742f37b527dc23b9>> */ /** @@ -102,8 +102,6 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useAlwaysAvailableJSErrorHandling(): Boolean - @DoNotStrip @JvmStatic public external fun useEditTextStockAndroidFocusBehavior(): Boolean - @DoNotStrip @JvmStatic public external fun useFabricInterop(): Boolean @DoNotStrip @JvmStatic public external fun useNativeViewConfigsInBridgelessMode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 8f33f72f796..4b29a9f3cb1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<56f86a3a0c0bbf453cf45a0db541ef54>> */ /** @@ -97,8 +97,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useAlwaysAvailableJSErrorHandling(): Boolean = false - override fun useEditTextStockAndroidFocusBehavior(): Boolean = true - override fun useFabricInterop(): Boolean = false override fun useNativeViewConfigsInBridgelessMode(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 399a1788f74..a3a143303ed 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8f5180a0ef154c083ac38d28e650ee11>> + * @generated SignedSource<<5b016fd6298477856116736e37c37c6f>> */ /** @@ -61,7 +61,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null - private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null private var useFabricInteropCache: Boolean? = null private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null @@ -440,16 +439,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } - override fun useEditTextStockAndroidFocusBehavior(): Boolean { - var cached = useEditTextStockAndroidFocusBehaviorCache - if (cached == null) { - cached = currentProvider.useEditTextStockAndroidFocusBehavior() - accessedFeatureFlags.add("useEditTextStockAndroidFocusBehavior") - useEditTextStockAndroidFocusBehaviorCache = cached - } - return cached - } - override fun useFabricInterop(): Boolean { var cached = useFabricInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 79b76152ea5..a24b14f0079 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<33571f99b1f78fbc62cecfca5f8351fa>> + * @generated SignedSource<> */ /** @@ -97,8 +97,6 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useAlwaysAvailableJSErrorHandling(): Boolean - @DoNotStrip public fun useEditTextStockAndroidFocusBehavior(): Boolean - @DoNotStrip public fun useFabricInterop(): Boolean @DoNotStrip public fun useNativeViewConfigsInBridgelessMode(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 42f238363e8..e55a3ab1b17 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -36,6 +36,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -146,9 +147,6 @@ public class ReactEditText extends AppCompatEditText { public ReactEditText(Context context) { super(context); - if (!ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { - setFocusableInTouchMode(false); - } mInputMethodManager = (InputMethodManager) @@ -191,9 +189,7 @@ public class ReactEditText extends AppCompatEditText { // selection on accessibility click to undo that. setSelection(length); } - return ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior() - ? requestFocusProgramatically() - : requestFocusInternal(); + return requestFocusProgramatically(); } return super.performAccessibilityAction(host, action, args); } @@ -341,29 +337,28 @@ public class ReactEditText extends AppCompatEditText { return super.onTextContextMenuItem(id); } - @Override - public void clearFocus() { - boolean useStockFocusBehavior = ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior(); - if (!useStockFocusBehavior) { - setFocusableInTouchMode(false); + public void clearFocusAndMaybeRefocus() { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P || !isInTouchMode()) { + super.clearFocus(); + } else { + // Avoid refocusing to a new view on old versions of Android by default + // by preventing `requestFocus()` on the rootView from moving focus to any child. + // https://cs.android.com/android/_/android/platform/frameworks/base/+/bdc66cb5a0ef513f4306edf9156cc978b08e06e4 + ViewGroup rootViewGroup = (ViewGroup)getRootView(); + int oldDescendantFocusability = rootViewGroup.getDescendantFocusability(); + rootViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + super.clearFocus(); + rootViewGroup.setDescendantFocusability(oldDescendantFocusability); } - super.clearFocus(); + hideSoftKeyboard(); } - @Override - public boolean requestFocus(int direction, Rect previouslyFocusedRect) { - // This is a no-op so that when the OS calls requestFocus(), nothing will happen. ReactEditText - // is a controlled component, which means its focus is controlled by JS, with two exceptions: - // autofocus when it's attached to the window, and responding to accessibility events. In both - // of these cases, we call requestFocusInternal() directly. - return ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior() - ? super.requestFocus(direction, previouslyFocusedRect) - : isFocused(); + /* package */ void clearFocusFromJS() { + clearFocusAndMaybeRefocus(); } private boolean requestFocusInternal() { - setFocusableInTouchMode(true); // We must explicitly call this method on the super class; if we call requestFocus() without // any arguments, it will call into the overridden requestFocus(int, Rect) above, which no-ops. boolean focused = super.requestFocus(View.FOCUS_DOWN, null); @@ -656,15 +651,7 @@ public class ReactEditText extends AppCompatEditText { // VisibleForTesting from {@link TextInputEventsTestCase}. public void requestFocusFromJS() { - if (ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { - requestFocusProgramatically(); - } else { - requestFocusInternal(); - } - } - - /* package */ void clearFocusFromJS() { - clearFocus(); + requestFocusProgramatically(); } // VisibleForTesting from {@link TextInputEventsTestCase}. @@ -1107,11 +1094,7 @@ public class ReactEditText extends AppCompatEditText { } if (mAutoFocus && !mDidAttachToWindow) { - if (ReactNativeFeatureFlags.useEditTextStockAndroidFocusBehavior()) { - requestFocusProgramatically(); - } else { - requestFocusInternal(); - } + requestFocusProgramatically(); } mDidAttachToWindow = true; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index f18e569c923..c93107684a7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -1164,7 +1164,7 @@ public class ReactTextInputManager extends BaseViewManager> + * @generated SignedSource<> */ /** @@ -261,12 +261,6 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } - bool useEditTextStockAndroidFocusBehavior() override { - static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useEditTextStockAndroidFocusBehavior"); - return method(javaProvider_); - } - bool useFabricInterop() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useFabricInterop"); @@ -498,11 +492,6 @@ bool JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling( return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling(); } -bool JReactNativeFeatureFlagsCxxInterop::useEditTextStockAndroidFocusBehavior( - facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior(); -} - bool JReactNativeFeatureFlagsCxxInterop::useFabricInterop( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useFabricInterop(); @@ -680,9 +669,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useAlwaysAvailableJSErrorHandling", JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling), - makeNativeMethod( - "useEditTextStockAndroidFocusBehavior", - JReactNativeFeatureFlagsCxxInterop::useEditTextStockAndroidFocusBehavior), makeNativeMethod( "useFabricInterop", JReactNativeFeatureFlagsCxxInterop::useFabricInterop), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 925a31a7166..7c104c10737 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -141,9 +141,6 @@ class JReactNativeFeatureFlagsCxxInterop static bool useAlwaysAvailableJSErrorHandling( facebook::jni::alias_ref); - static bool useEditTextStockAndroidFocusBehavior( - facebook::jni::alias_ref); - static bool useFabricInterop( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index f0efac973d0..992998a349d 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<661a4193f9ba7af0c963bc13751deb15>> + * @generated SignedSource<<1c90106ded5dc5f08cdec4dede695341>> */ /** @@ -174,10 +174,6 @@ bool ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling() { return getAccessor().useAlwaysAvailableJSErrorHandling(); } -bool ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior() { - return getAccessor().useEditTextStockAndroidFocusBehavior(); -} - bool ReactNativeFeatureFlags::useFabricInterop() { return getAccessor().useFabricInterop(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 35afb5835d8..ca53dff33e3 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<53e965423f2957b37e0470c607cc45a4>> + * @generated SignedSource<> */ /** @@ -224,11 +224,6 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useAlwaysAvailableJSErrorHandling(); - /** - * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. - */ - RN_EXPORT static bool useEditTextStockAndroidFocusBehavior(); - /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 6c494257b4d..9c075b6f9b2 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5ff3ac57eb17d9b6642d98f2fc35bd9d>> + * @generated SignedSource<> */ /** @@ -695,24 +695,6 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::useEditTextStockAndroidFocusBehavior() { - auto flagValue = useEditTextStockAndroidFocusBehavior_.load(); - - if (!flagValue.has_value()) { - // This block is not exclusive but it is not necessary. - // If multiple threads try to initialize the feature flag, we would only - // be accessing the provider multiple times but the end state of this - // instance and the returned flag value would be the same. - - markFlagAsAccessed(37, "useEditTextStockAndroidFocusBehavior"); - - flagValue = currentProvider_->useEditTextStockAndroidFocusBehavior(); - useEditTextStockAndroidFocusBehavior_ = flagValue; - } - - return flagValue.value(); -} - bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { auto flagValue = useFabricInterop_.load(); @@ -722,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useFabricInterop"); + markFlagAsAccessed(37, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -740,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(38, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -758,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(39, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -776,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "useRawPropsJsiValue"); + markFlagAsAccessed(40, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -794,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useShadowNodeStateOnClone"); + markFlagAsAccessed(41, "useShadowNodeStateOnClone"); flagValue = currentProvider_->useShadowNodeStateOnClone(); useShadowNodeStateOnClone_ = flagValue; @@ -812,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useTurboModuleInterop"); + markFlagAsAccessed(42, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -830,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useTurboModules"); + markFlagAsAccessed(43, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 48e75d266b0..ea0cd805517 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<267385c8df88a5d1eb7f1e2478209d39>> + * @generated SignedSource<<978f828e7368b8802f8eaa5194e86e2f>> */ /** @@ -69,7 +69,6 @@ class ReactNativeFeatureFlagsAccessor { bool traceTurboModulePromiseRejectionsOnAndroid(); bool updateRuntimeShadowNodeReferencesOnCommit(); bool useAlwaysAvailableJSErrorHandling(); - bool useEditTextStockAndroidFocusBehavior(); bool useFabricInterop(); bool useNativeViewConfigsInBridgelessMode(); bool useOptimizedEventBatchingOnAndroid(); @@ -88,7 +87,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 45> accessedFeatureFlags_; + std::array, 44> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> disableMountItemReorderingAndroid_; @@ -127,7 +126,6 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> traceTurboModulePromiseRejectionsOnAndroid_; std::atomic> updateRuntimeShadowNodeReferencesOnCommit_; std::atomic> useAlwaysAvailableJSErrorHandling_; - std::atomic> useEditTextStockAndroidFocusBehavior_; std::atomic> useFabricInterop_; std::atomic> useNativeViewConfigsInBridgelessMode_; std::atomic> useOptimizedEventBatchingOnAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index e81708e657d..bf4c5451e37 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<48bb4ea50c42676aee161ea1594a6aec>> + * @generated SignedSource<<643c1fd24fbc1a77ef109e712023f9d5>> */ /** @@ -175,10 +175,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } - bool useEditTextStockAndroidFocusBehavior() override { - return true; - } - bool useFabricInterop() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index cfd48f0bf4f..2d71d1dfb5f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -378,15 +378,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::useAlwaysAvailableJSErrorHandling(); } - bool useEditTextStockAndroidFocusBehavior() override { - auto value = values_["useEditTextStockAndroidFocusBehavior"]; - if (!value.isNull()) { - return value.getBool(); - } - - return ReactNativeFeatureFlagsDefaults::useEditTextStockAndroidFocusBehavior(); - } - bool useFabricInterop() override { auto value = values_["useFabricInterop"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 8efd2e70070..ba1782d6a6b 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<4db2ff36701f0dbcd3dd59fa5879a612>> */ /** @@ -62,7 +62,6 @@ class ReactNativeFeatureFlagsProvider { virtual bool traceTurboModulePromiseRejectionsOnAndroid() = 0; virtual bool updateRuntimeShadowNodeReferencesOnCommit() = 0; virtual bool useAlwaysAvailableJSErrorHandling() = 0; - virtual bool useEditTextStockAndroidFocusBehavior() = 0; virtual bool useFabricInterop() = 0; virtual bool useNativeViewConfigsInBridgelessMode() = 0; virtual bool useOptimizedEventBatchingOnAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index cf4b98fd8c0..7afdd1d4758 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<76f1f689940817c1df6ace2f8dd062e7>> + * @generated SignedSource<<4f6ee8b8bae8ea84fab77eb9feb63f9d>> */ /** @@ -229,11 +229,6 @@ bool NativeReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling( return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling(); } -bool NativeReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior( - jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::useEditTextStockAndroidFocusBehavior(); -} - bool NativeReactNativeFeatureFlags::useFabricInterop( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useFabricInterop(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 2c6765db1f1..77c80a0b94b 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<0009cf8a05d254e3695e7ce57fc5f8af>> */ /** @@ -111,8 +111,6 @@ class NativeReactNativeFeatureFlags bool useAlwaysAvailableJSErrorHandling(jsi::Runtime& runtime); - bool useEditTextStockAndroidFocusBehavior(jsi::Runtime& runtime); - bool useFabricInterop(jsi::Runtime& runtime); bool useNativeViewConfigsInBridgelessMode(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 2403266d4a8..671b3536dff 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -440,16 +440,6 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, - useEditTextStockAndroidFocusBehavior: { - defaultValue: true, - metadata: { - description: - 'If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior.', - expectedReleaseValue: true, - purpose: 'release', - }, - ossReleaseStage: 'none', - }, useFabricInterop: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 3b4b290483a..530444b1604 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5b1d3ba6712de7a927eeeb8602ee2a8f>> + * @generated SignedSource<> * @flow strict */ @@ -86,7 +86,6 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ traceTurboModulePromiseRejectionsOnAndroid: Getter, updateRuntimeShadowNodeReferencesOnCommit: Getter, useAlwaysAvailableJSErrorHandling: Getter, - useEditTextStockAndroidFocusBehavior: Getter, useFabricInterop: Getter, useNativeViewConfigsInBridgelessMode: Getter, useOptimizedEventBatchingOnAndroid: Getter, @@ -323,10 +322,6 @@ export const updateRuntimeShadowNodeReferencesOnCommit: Getter = create * In Bridgeless mode, use the always available javascript error reporting pipeline. */ export const useAlwaysAvailableJSErrorHandling: Getter = createNativeFlagGetter('useAlwaysAvailableJSErrorHandling', false); -/** - * If true, focusing in ReactEditText will mainly use stock Android requestFocus() behavior. If false it will use legacy custom focus behavior. - */ -export const useEditTextStockAndroidFocusBehavior: Getter = createNativeFlagGetter('useEditTextStockAndroidFocusBehavior', true); /** * Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index f61e2c7d42d..7fb3cc6ee73 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<2499cbe243c048d9e3647342ebec3544>> * @flow strict */ @@ -61,7 +61,6 @@ export interface Spec extends TurboModule { +traceTurboModulePromiseRejectionsOnAndroid?: () => boolean; +updateRuntimeShadowNodeReferencesOnCommit?: () => boolean; +useAlwaysAvailableJSErrorHandling?: () => boolean; - +useEditTextStockAndroidFocusBehavior?: () => boolean; +useFabricInterop?: () => boolean; +useNativeViewConfigsInBridgelessMode?: () => boolean; +useOptimizedEventBatchingOnAndroid?: () => boolean;