From a1b49ec3164887cd9012c360f423397a55e28385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= Date: Tue, 14 Jul 2026 14:10:02 +0200 Subject: [PATCH 1/2] fix: prevent programmatic scrolls from cancelling active touches on iOS --- .../ComponentViews/ScrollView/RCTScrollViewComponentView.mm | 1 + .../react/renderer/components/scrollview/ScrollEvent.cpp | 4 +++- .../react/renderer/components/scrollview/ScrollEvent.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) 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 548987ff291d..cd96841fa611 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -599,6 +599,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/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. From 8723cea7857ffe54117143bc8ae221a84cc8a1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= Date: Wed, 15 Jul 2026 09:42:43 +0200 Subject: [PATCH 2/2] chore: cxx api snapshots --- scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api | 1 + scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api | 1 + 9 files changed, 9 insertions(+) diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index 0aaf2efc5caa..9ea34a485d14 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -7858,6 +7858,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 be2958293dad..922137b650b5 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -7619,6 +7619,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 faf7b0b6db37..3528eea0b92b 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -7849,6 +7849,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 2ec052291919..051f7374c5a4 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -9891,6 +9891,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 319fba1e0d52..743b41ed91a8 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -9704,6 +9704,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 3ec823148f22..8f16c9a2fd76 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -9882,6 +9882,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 64301436eeda..bf1b6a6a4874 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api @@ -6004,6 +6004,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 eda51abd3696..d80736b3aa89 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -5829,6 +5829,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 3c9c5e8ab249..2e011217998d 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api @@ -5995,6 +5995,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;