diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 54a14a0b864a..14a08b49cb7c 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -597,6 +597,7 @@ - (BOOL)_shouldDisableScrollInteraction metrics.containerSize = RCTSizeFromCGSize(_scrollView.bounds.size); metrics.zoomScale = _scrollView.zoomScale; metrics.timestamp = CACurrentMediaTime(); + metrics.responderIgnoreScroll = !_isUserTriggeredScrolling; if (_layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) { metrics.contentOffset.x = metrics.contentSize.width - metrics.containerSize.width - metrics.contentOffset.x; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index bcda83e61ba7..8f55121cd23d 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -539,7 +539,9 @@ - (void)textInputDidChangeSelection - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (_eventEmitter) { - static_cast(*_eventEmitter).onScroll([self _textInputMetrics]); + auto metrics = [self _textInputMetrics]; + metrics.responderIgnoreScroll = !(scrollView.isDragging || scrollView.isDecelerating); + static_cast(*_eventEmitter).onScroll(metrics); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp index 7adacc575272..5307df67ff62 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp @@ -44,6 +44,7 @@ jsi::Value ScrollEvent::asJSIValue(jsi::Runtime& runtime) const { payload.setProperty(runtime, "zoomScale", zoomScale); payload.setProperty(runtime, "timestamp", timestamp * 1000); + payload.setProperty(runtime, "responderIgnoreScroll", responderIgnoreScroll); return payload; } @@ -67,7 +68,8 @@ folly::dynamic ScrollEvent::asDynamic() const { "contentInset", std::move(contentInsetObj))( "contentSize", std::move(contentSizeObj))( "layoutMeasurement", std::move(containerSizeObj))( - "zoomScale", zoomScale)("timestamp", timestamp * 1000); + "zoomScale", zoomScale)("timestamp", timestamp * 1000)( + "responderIgnoreScroll", responderIgnoreScroll); return metrics; }; diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h index fb2cd8b44fd5..c3fd9583828e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h @@ -21,6 +21,7 @@ struct ScrollEvent : public EventPayload { EdgeInsets contentInset; Size containerSize; Float zoomScale{}; + bool responderIgnoreScroll{false}; /* * The time in seconds when the touch occurred or when it was last mutated. diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.cpp index 2982b12fe014..7da2622926dc 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.cpp @@ -86,6 +86,9 @@ static jsi::Value textInputMetricsScrollPayload( "zoomScale", textInputMetrics.zoomScale != 0.0f ? textInputMetrics.zoomScale : 1); + payload.setProperty( + runtime, "responderIgnoreScroll", textInputMetrics.responderIgnoreScroll); + return payload; }; diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.h index d85b76e806b3..8c1a443f9e5f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/TextInputEventEmitter.h @@ -29,6 +29,7 @@ class TextInputEventEmitter : public ViewEventEmitter { int eventCount; Size layoutMeasurement; Float zoomScale; + bool responderIgnoreScroll{false}; Tag target; }; diff --git a/packages/react-native/types_DEPRECATED/Libraries/Components/TextInput/TextInput.d.ts b/packages/react-native/types_DEPRECATED/Libraries/Components/TextInput/TextInput.d.ts index cc5dc34dd6bb..21bb5c60658a 100644 --- a/packages/react-native/types_DEPRECATED/Libraries/Components/TextInput/TextInput.d.ts +++ b/packages/react-native/types_DEPRECATED/Libraries/Components/TextInput/TextInput.d.ts @@ -440,6 +440,7 @@ export type TextInputFocusEvent = NativeSyntheticEvent; */ export interface TextInputScrollEventData { contentOffset: {x: number; y: number}; + responderIgnoreScroll?: boolean | undefined; } /** diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index 828513e24e82..6a60de295d36 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -5070,6 +5070,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { } struct facebook::react::TextInputEventEmitter::Metrics { + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Float zoomScale; @@ -7901,6 +7902,7 @@ struct facebook::react::ScrollEndDragEvent : public facebook::react::ScrollEvent struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Float timestamp; public facebook::react::Float zoomScale; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api index 39e6d87b0d02..995cc7e919f5 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -4881,6 +4881,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { } struct facebook::react::TextInputEventEmitter::Metrics { + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Float zoomScale; @@ -7662,6 +7663,7 @@ struct facebook::react::ScrollEndDragEvent : public facebook::react::ScrollEvent struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Float timestamp; public facebook::react::Float zoomScale; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api index f5dcbb21b548..bbdb412e7569 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -5061,6 +5061,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { } struct facebook::react::TextInputEventEmitter::Metrics { + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Float zoomScale; @@ -7892,6 +7893,7 @@ struct facebook::react::ScrollEndDragEvent : public facebook::react::ScrollEvent struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Float timestamp; public facebook::react::Float zoomScale; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api index bfbe9280ffce..6c5df63baefb 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -7244,6 +7244,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { } struct facebook::react::TextInputEventEmitter::Metrics { + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Float zoomScale; @@ -9920,6 +9921,7 @@ struct facebook::react::ScrollEndDragEvent : public facebook::react::ScrollEvent struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Float timestamp; public facebook::react::Float zoomScale; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api index 5a097a3af563..d901ec4b5d0d 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -7087,6 +7087,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { } struct facebook::react::TextInputEventEmitter::Metrics { + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Float zoomScale; @@ -9737,6 +9738,7 @@ struct facebook::react::ScrollEndDragEvent : public facebook::react::ScrollEvent struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Float timestamp; public facebook::react::Float zoomScale; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api index 8a50f499d137..88eb5df49a78 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -7235,6 +7235,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { } struct facebook::react::TextInputEventEmitter::Metrics { + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Float zoomScale; @@ -9911,6 +9912,7 @@ struct facebook::react::ScrollEndDragEvent : public facebook::react::ScrollEvent struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Float timestamp; public facebook::react::Float zoomScale; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api index e28f3bd70288..7b9ddfbf88a9 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api @@ -3561,6 +3561,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { struct facebook::react::TextInputEventEmitter::Metrics { public Float zoomScale; + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Point contentOffset; @@ -6022,6 +6023,7 @@ struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public Float timestamp; public Float zoomScale; public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Point contentOffset; public facebook::react::Size containerSize; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api index 1c421afcdf7a..48bca87783b6 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -3412,6 +3412,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { struct facebook::react::TextInputEventEmitter::Metrics { public Float zoomScale; + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Point contentOffset; @@ -5847,6 +5848,7 @@ struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public Float timestamp; public Float zoomScale; public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Point contentOffset; public facebook::react::Size containerSize; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api index 2b46b26d7b0b..50e26d03c561 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api @@ -3552,6 +3552,7 @@ struct facebook::react::TextInputEventEmitter::KeyPressMetrics { struct facebook::react::TextInputEventEmitter::Metrics { public Float zoomScale; + public bool responderIgnoreScroll; public facebook::react::AttributedString::Range selectionRange; public facebook::react::EdgeInsets contentInset; public facebook::react::Point contentOffset; @@ -6013,6 +6014,7 @@ struct facebook::react::ScrollEvent : public facebook::react::EventPayload { public Float timestamp; public Float zoomScale; public ScrollEvent() = default; + public bool responderIgnoreScroll; public facebook::react::EdgeInsets contentInset; public facebook::react::Point contentOffset; public facebook::react::Size containerSize;