diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index ce2a3ac666e..4f61b16479b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -151,6 +151,16 @@ AndroidTextInputProps::AndroidTextInputProps( {false})), fontWeight(convertRawProp(context, rawProps, "fontWeight", sourceProps.fontWeight, {})), fontFamily(convertRawProp(context, rawProps, "fontFamily", sourceProps.fontFamily, {})), + onKeyPress(convertRawProp(context, rawProps, "onKeyPress", sourceProps.onKeyPress, {false})), + onSelectionChange(convertRawProp(context, rawProps, + "onSelectionChange", + sourceProps.onSelectionChange, + {false})), + onContentSizeChange(convertRawProp(context, rawProps, + "onContentSizeChange", + sourceProps.onContentSizeChange, + {false})), + onScroll(convertRawProp(context, rawProps, "onScroll", sourceProps.onScroll, {false})), // See AndroidTextInputComponentDescriptor for usage // TODO T63008435: can these, and this feature, be removed entirely? hasPadding(hasValue(rawProps, sourceProps.hasPadding, "padding")), @@ -227,6 +237,10 @@ void AndroidTextInputProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(includeFontPadding); RAW_SET_PROP_SWITCH_CASE_BASIC(fontWeight); RAW_SET_PROP_SWITCH_CASE_BASIC(fontFamily); + RAW_SET_PROP_SWITCH_CASE_BASIC(onKeyPress); + RAW_SET_PROP_SWITCH_CASE_BASIC(onSelectionChange); + RAW_SET_PROP_SWITCH_CASE_BASIC(onContentSizeChange); + RAW_SET_PROP_SWITCH_CASE_BASIC(onScroll); case CONSTEXPR_RAW_PROPS_KEY_HASH("value"): { fromRawValue(context, value, this->value, {}); @@ -628,6 +642,22 @@ folly::dynamic AndroidTextInputProps::getDiffProps( : folly::dynamic(nullptr); } + if (onKeyPress != oldProps->onKeyPress) { + result["onKeyPress"] = onKeyPress; + } + + if (onSelectionChange != oldProps->onSelectionChange) { + result["onSelectionChange"] = onSelectionChange; + } + + if (onContentSizeChange != oldProps->onContentSizeChange) { + result["onContentSizeChange"] = onContentSizeChange; + } + + if (onScroll != oldProps->onScroll) { + result["onScroll"] = onScroll; + } + return result; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h index 8bfc984e252..32b3070d33e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h @@ -109,6 +109,15 @@ class AndroidTextInputProps final : public BaseTextInputProps { std::string fontWeight{}; std::string fontFamily{}; + /* + * Whether JS listens to these events. ReactTextInputManager only sets up the + * native watchers for them when these props are sent. + */ + bool onKeyPress{false}; + bool onSelectionChange{false}; + bool onContentSizeChange{false}; + bool onScroll{false}; + /** * Auxiliary information to detect if these props are set or not. * See AndroidTextInputComponentDescriptor for usage. diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/tests/AndroidTextInputPropsDiffTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/tests/AndroidTextInputPropsDiffTest.cpp new file mode 100644 index 00000000000..dcd7ba82b16 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/tests/AndroidTextInputPropsDiffTest.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#if defined(ANDROID) && defined(RN_SERIALIZABLE_STATE) + +#include +#include + +namespace facebook::react { + +// ReactTextInputManager only sets up the event watchers when these props are +// sent. JS sends a handler as `true`, and false resets it like null does. +TEST(AndroidTextInputPropsDiffTest, eventHandlerPropsAreSent) { + using folly::dynamic; + expectPayloadsMatchRawProps({ + {dynamic::object("onKeyPress", true)("onSelectionChange", true)( + "onContentSizeChange", true)("onScroll", true)}, + {dynamic::object("onKeyPress", nullptr)("onSelectionChange", nullptr)( + "onContentSizeChange", nullptr)("onScroll", nullptr), + dynamic::object("onKeyPress", false)("onSelectionChange", false)( + "onContentSizeChange", false)("onScroll", false)}, + }); +} + +} // namespace facebook::react + +#endif diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api index b9463dbd17f..4efffc1f8cd 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api @@ -1184,6 +1184,10 @@ class facebook::react::AndroidTextInputProps : public facebook::react::BaseTextI public bool hasPaddingTop; public bool hasPaddingVertical; public bool includeFontPadding; + public bool onContentSizeChange; + public bool onKeyPress; + public bool onScroll; + public bool onSelectionChange; public bool secureTextEntry; public bool selectTextOnFocus; public bool showSoftInputOnFocus;