From 0dbfcda6c6aac72bf657b57f1852ed74ce6281f9 Mon Sep 17 00:00:00 2001 From: Nick Lefever Date: Thu, 8 May 2025 09:37:26 -0700 Subject: [PATCH] Add getDiffProps for ScrollView component (#51168) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51168 See title Changelog: [Internal] Reviewed By: rshest Differential Revision: D74327336 fbshipit-source-id: 9e306400578ac6d83c49537ab2c38e86209fbcfd --- .../react/fabric/FabricMountingManager.cpp | 3 +- .../components/scrollview/ScrollViewProps.cpp | 269 ++++++++++++++++++ .../components/scrollview/ScrollViewProps.h | 6 + 3 files changed, 277 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index e80808583e9..92003720059 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -224,7 +224,8 @@ jni::local_ref getProps( auto* newProps = newShadowView.props.get(); if ((ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid()) && (strcmp(newShadowView.componentName, "View") == 0 || - strcmp(newShadowView.componentName, "Image") == 0)) { + strcmp(newShadowView.componentName, "Image") == 0 || + strcmp(newShadowView.componentName, "ScrollView") == 0)) { return ReadableNativeMap::newObjectCxxArgs( newProps->getDiffProps(oldProps)); } diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp index ca8b33fb240..580912cb264 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp @@ -592,4 +592,273 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const { } #endif +#ifdef ANDROID + +static folly::dynamic convertScrollViewMaintainVisibleContentPosition( + const ScrollViewMaintainVisibleContentPosition& value) { + folly::dynamic result = folly::dynamic::object(); + result["minIndexForVisible"] = value.minIndexForVisible; + if (value.autoscrollToTopThreshold.has_value()) { + result["autoscrollToTopThreshold"] = value.autoscrollToTopThreshold.value(); + } + return result; +} + +static folly::dynamic convertEdgeInsets(const EdgeInsets& edgeInsets) { + folly::dynamic edgeInsetsResult = folly::dynamic::object(); + edgeInsetsResult["left"] = edgeInsets.left; + edgeInsetsResult["top"] = edgeInsets.top; + edgeInsetsResult["right"] = edgeInsets.right; + edgeInsetsResult["bottom"] = edgeInsets.bottom; + return edgeInsetsResult; +} + +static folly::dynamic convertPoint(const Point& point) { + folly::dynamic pointResult = folly::dynamic::object(); + pointResult["y"] = point.y; + pointResult["x"] = point.x; + return pointResult; +} + +folly::dynamic ScrollViewProps::getDiffProps(const Props* prevProps) const { + static const auto defaultProps = ScrollViewProps(); + const ScrollViewProps* oldProps = prevProps == nullptr + ? &defaultProps + : static_cast(prevProps); + + folly::dynamic result = ViewProps::getDiffProps(oldProps); + + if (alwaysBounceHorizontal != oldProps->alwaysBounceHorizontal) { + result["alwaysBounceHorizontal"] = alwaysBounceHorizontal; + } + + if (alwaysBounceVertical != oldProps->alwaysBounceVertical) { + result["alwaysBounceVertical"] = alwaysBounceVertical; + } + + if (bounces != oldProps->bounces) { + result["bounces"] = bounces; + } + + if (bouncesZoom != oldProps->bouncesZoom) { + result["bouncesZoom"] = bouncesZoom; + } + + if (canCancelContentTouches != oldProps->canCancelContentTouches) { + result["canCancelContentTouches"] = canCancelContentTouches; + } + + if (centerContent != oldProps->centerContent) { + result["centerContent"] = centerContent; + } + + if (automaticallyAdjustContentInsets != + oldProps->automaticallyAdjustContentInsets) { + result["automaticallyAdjustContentInsets"] = + automaticallyAdjustContentInsets; + } + + if (automaticallyAdjustsScrollIndicatorInsets != + oldProps->automaticallyAdjustsScrollIndicatorInsets) { + result["automaticallyAdjustsScrollIndicatorInsets"] = + automaticallyAdjustsScrollIndicatorInsets; + } + + if (automaticallyAdjustKeyboardInsets != + oldProps->automaticallyAdjustKeyboardInsets) { + result["automaticallyAdjustKeyboardInsets"] = + automaticallyAdjustKeyboardInsets; + } + + if (decelerationRate != oldProps->decelerationRate) { + result["decelerationRate"] = decelerationRate; + } + + if (endDraggingSensitivityMultiplier != + oldProps->endDraggingSensitivityMultiplier) { + result["endDraggingSensitivityMultiplier"] = + endDraggingSensitivityMultiplier; + } + + if (directionalLockEnabled != oldProps->directionalLockEnabled) { + result["directionalLockEnabled"] = directionalLockEnabled; + } + + if (indicatorStyle != oldProps->indicatorStyle) { + switch (indicatorStyle) { + case ScrollViewIndicatorStyle::Default: + result["indicatorStyle"] = "default"; + break; + case ScrollViewIndicatorStyle::Black: + result["indicatorStyle"] = "black"; + break; + case ScrollViewIndicatorStyle::White: + result["indicatorStyle"] = "white"; + break; + } + } + + if (keyboardDismissMode != oldProps->keyboardDismissMode) { + switch (keyboardDismissMode) { + case ScrollViewKeyboardDismissMode::None: + result["keyboardDismissMode"] = "none"; + break; + case ScrollViewKeyboardDismissMode::OnDrag: + result["keyboardDismissMode"] = "on-drag"; + break; + case ScrollViewKeyboardDismissMode::Interactive: + result["keyboardDismissMode"] = "interactive"; + break; + } + } + + if (maintainVisibleContentPosition != + oldProps->maintainVisibleContentPosition) { + if (maintainVisibleContentPosition.has_value()) { + result["maintainVisibleContentPosition"] = + convertScrollViewMaintainVisibleContentPosition( + maintainVisibleContentPosition.value()); + } else { + result["maintainVisibleContentPosition"] = folly::dynamic(nullptr); + } + } + + if (maximumZoomScale != oldProps->maximumZoomScale) { + result["maximumZoomScale"] = maximumZoomScale; + } + + if (minimumZoomScale != oldProps->minimumZoomScale) { + result["minimumZoomScale"] = minimumZoomScale; + } + + if (scrollEnabled != oldProps->scrollEnabled) { + result["scrollEnabled"] = scrollEnabled; + } + + if (pagingEnabled != oldProps->pagingEnabled) { + result["pagingEnabled"] = pagingEnabled; + } + + if (pinchGestureEnabled != oldProps->pinchGestureEnabled) { + result["pinchGestureEnabled"] = pinchGestureEnabled; + } + + if (scrollsToTop != oldProps->scrollsToTop) { + result["scrollsToTop"] = scrollsToTop; + } + + if (showsHorizontalScrollIndicator != + oldProps->showsHorizontalScrollIndicator) { + result["showsHorizontalScrollIndicator"] = showsHorizontalScrollIndicator; + } + + if (showsVerticalScrollIndicator != oldProps->showsVerticalScrollIndicator) { + result["showsVerticalScrollIndicator"] = showsVerticalScrollIndicator; + } + + if (persistentScrollbar != oldProps->persistentScrollbar) { + result["persistentScrollbar"] = persistentScrollbar; + } + + if (horizontal != oldProps->horizontal) { + result["horizontal"] = horizontal; + } + + if (scrollEventThrottle != oldProps->scrollEventThrottle) { + result["scrollEventThrottle"] = scrollEventThrottle; + } + + if (zoomScale != oldProps->zoomScale) { + result["zoomScale"] = zoomScale; + } + + if (contentInset != oldProps->contentInset) { + result["contentInset"] = convertEdgeInsets(contentInset); + } + + if (contentOffset != oldProps->contentOffset) { + result["contentOffset"] = convertPoint(contentOffset); + } + + if (scrollIndicatorInsets != oldProps->scrollIndicatorInsets) { + result["scrollIndicatorInsets"] = convertEdgeInsets(scrollIndicatorInsets); + } + + if (snapToInterval != oldProps->snapToInterval) { + result["snapToInterval"] = snapToInterval; + } + + if (snapToAlignment != oldProps->snapToAlignment) { + switch (snapToAlignment) { + case ScrollViewSnapToAlignment::Start: + result["snapToAlignment"] = "start"; + break; + case ScrollViewSnapToAlignment::Center: + result["snapToAlignment"] = "center"; + break; + case ScrollViewSnapToAlignment::End: + result["snapToAlignment"] = "end"; + break; + } + } + + if (disableIntervalMomentum != oldProps->disableIntervalMomentum) { + result["disableIntervalMomentum"] = disableIntervalMomentum; + } + + if (snapToOffsets != oldProps->snapToOffsets) { + auto snapToOffsetsArray = folly::dynamic::array(); + for (const auto& snapToOffset : snapToOffsets) { + snapToOffsetsArray.push_back(snapToOffset); + } + result["snapToOffsets"] = snapToOffsetsArray; + } + + if (snapToStart != oldProps->snapToStart) { + result["snapToStart"] = snapToStart; + } + + if (snapToEnd != oldProps->snapToEnd) { + result["snapToEnd"] = snapToEnd; + } + + if (contentInsetAdjustmentBehavior != + oldProps->contentInsetAdjustmentBehavior) { + switch (contentInsetAdjustmentBehavior) { + case ContentInsetAdjustmentBehavior::Never: + result["contentInsetAdjustmentBehavior"] = "never"; + break; + case ContentInsetAdjustmentBehavior::Automatic: + result["contentInsetAdjustmentBehavior"] = "automatic"; + break; + case ContentInsetAdjustmentBehavior::ScrollableAxes: + result["contentInsetAdjustmentBehavior"] = "scrollableAxes"; + break; + case ContentInsetAdjustmentBehavior::Always: + result["contentInsetAdjustmentBehavior"] = "always"; + break; + } + } + + if (scrollToOverflowEnabled != oldProps->scrollToOverflowEnabled) { + result["scrollToOverflowEnabled"] = scrollToOverflowEnabled; + } + + if (isInvertedVirtualizedList != oldProps->isInvertedVirtualizedList) { + result["isInvertedVirtualizedList"] = isInvertedVirtualizedList; + } + + if (sendMomentumEvents != oldProps->sendMomentumEvents) { + result["sendMomentumEvents"] = sendMomentumEvents; + } + + if (nestedScrollEnabled != oldProps->nestedScrollEnabled) { + result["nestedScrollEnabled"] = nestedScrollEnabled; + } + + return result; +} + +#endif + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h index 4bf8a991ce6..9a28f4e85db 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h @@ -82,6 +82,12 @@ class ScrollViewProps final : public ViewProps { #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList getDebugProps() const override; #endif + +#ifdef ANDROID + + folly::dynamic getDiffProps(const Props* prevProps) const override; + +#endif }; } // namespace facebook::react