From d2e646a9a5d2b80e8e6f4ea72b932e5d5d7580d1 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 22 Jan 2025 09:34:08 -0800 Subject: [PATCH 1/4] [skip ci] Introduce getDiffProps for (#45552) Summary: In this diff I'm overriding the getDiffProps for ViewProps. The goal is to verify what's the impact of calculating diffs of props in Android, starting with ViewProps. Once we verify what are the implication we will automatic implement this diffing. The full implementation of this method will be implemented in the following diffs changelog: [internal] internal Reviewed By: NickGerleman Differential Revision: D59969328 --- .../components/view/HostPlatformViewProps.cpp | 21 +++++++++++++++++++ .../components/view/HostPlatformViewProps.h | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index dfbae60abd7..352b8274c92 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -133,4 +133,25 @@ SharedDebugStringConvertibleList HostPlatformViewProps::getDebugProps() const { } #endif +#ifdef ANDROID + +folly::dynamic HostPlatformViewProps::getDiffProps( + const Props* prevProps) const { + folly::dynamic result = folly::dynamic::object(); + + static const auto defaultProps = HostPlatformViewProps(); + + const HostPlatformViewProps* oldProps = prevProps == nullptr + ? &defaultProps + : static_cast(prevProps); + + if (focusable != oldProps->focusable) { + result["focusable"] = focusable; + } + + return result; +} + +#endif + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h index 25a6cd30529..d18d7e863bb 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h @@ -55,6 +55,12 @@ class HostPlatformViewProps : public BaseViewProps { #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList getDebugProps() const override; #endif + +#ifdef ANDROID + + folly::dynamic getDiffProps(const Props* prevProps) const override; + +#endif }; } // namespace facebook::react From f450be249f877a73275753ea846bfd29eaf128b6 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 22 Jan 2025 09:34:08 -0800 Subject: [PATCH 2/4] [skip ci] Implement prop diffing for basic props in (#48829) Summary: This diff implements the diffing for basic props of changelog: [internal] internal Reviewed By: NickGerleman Differential Revision: D59972040 --- .../components/view/HostPlatformViewProps.cpp | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index 352b8274c92..d46e6425f9c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -145,10 +145,116 @@ folly::dynamic HostPlatformViewProps::getDiffProps( ? &defaultProps : static_cast(prevProps); + if (this == oldProps) { + return result; + } if (focusable != oldProps->focusable) { result["focusable"] = focusable; } + if (hasTVPreferredFocus != oldProps->hasTVPreferredFocus) { + result["hasTVPreferredFocus"] = hasTVPreferredFocus; + } + + if (needsOffscreenAlphaCompositing != + oldProps->needsOffscreenAlphaCompositing) { + result["needsOffscreenAlphaCompositing"] = needsOffscreenAlphaCompositing; + } + + if (renderToHardwareTextureAndroid != + oldProps->renderToHardwareTextureAndroid) { + result["renderToHardwareTextureAndroid"] = renderToHardwareTextureAndroid; + } + + if (opacity != oldProps->opacity) { + result["opacity"] = opacity; + } + + if (backgroundColor != oldProps->backgroundColor) { + result["backgroundColor"] = *backgroundColor; + } + + if (shadowColor != oldProps->shadowColor) { + result["shadowColor"] = *shadowColor; + } + + if (shadowOpacity != oldProps->shadowOpacity) { + result["shadowOpacity"] = shadowOpacity; + } + + if (shadowRadius != oldProps->shadowRadius) { + result["shadowRadius"] = shadowRadius; + } + + if (shouldRasterize != oldProps->shouldRasterize) { + result["shouldRasterize"] = shouldRasterize; + } + + if (collapsable != oldProps->collapsable) { + result["collapsable"] = collapsable; + } + + if (removeClippedSubviews != oldProps->removeClippedSubviews) { + result["removeClippedSubviews"] = removeClippedSubviews; + } + + if (onLayout != oldProps->onLayout) { + result["onLayout"] = onLayout; + } + + if (zIndex != oldProps->zIndex) { + result["zIndex"] = zIndex.value(); + } + + if (pointerEvents != oldProps->pointerEvents) { + std::string value; + switch (pointerEvents) { + case PointerEventsMode::BoxOnly: + result["pointerEvents"] = "box-only"; + break; + case PointerEventsMode::BoxNone: + result["pointerEvents"] = "box-none"; + break; + case PointerEventsMode::None: + result["pointerEvents"] = "none"; + break; + default: + result["pointerEvents"] = "auto"; + break; + } + + if (nativeId != oldProps->nativeId) { + result["nativeId"] = nativeId; + } + + if (testId != oldProps->testId) { + result["testId"] = testId; + } + + if (accessible != oldProps->accessible) { + result["accessible"] = accessible; + } + + if (getClipsContentToBounds() != oldProps->getClipsContentToBounds()) { + result["overflow"] = getClipsContentToBounds() ? "hidden" : "visible"; + result["scroll"] = result["overflow"]; + } + + if (backfaceVisibility != oldProps->backfaceVisibility) { + switch (backfaceVisibility) { + case BackfaceVisibility::Auto: + result["backfaceVisibility"] = "auto"; + break; + case BackfaceVisibility::Visible: + result["backfaceVisibility"] = "visible"; + break; + case BackfaceVisibility::Hidden: + result["backfaceVisibility"] = "hidden"; + break; + } + } + } + return result; } From 373b2f752c4e2b8dc42665b46d33a576375e475e Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 22 Jan 2025 09:34:08 -0800 Subject: [PATCH 3/4] [skip ci] Implement prop diffing for event props in (#48830) Summary: This diff implements the diffing for event props of changelog: [internal] internal Reviewed By: javache Differential Revision: D59972038 --- .../components/view/HostPlatformViewProps.cpp | 218 ++++++++++++++++-- 1 file changed, 193 insertions(+), 25 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index d46e6425f9c..85eb8853686 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -135,6 +135,18 @@ SharedDebugStringConvertibleList HostPlatformViewProps::getDebugProps() const { #ifdef ANDROID +inline static void updateEventProp( + folly::dynamic& result, + const ViewEvents& newEvents, + const ViewEvents& oldEvents, + const ViewEvents::Offset& offset, + const std::string& name) { + if (newEvents[offset] != oldEvents[offset]) { + auto value = newEvents[offset]; + result[name] = value; + } +} + folly::dynamic HostPlatformViewProps::getDiffProps( const Props* prevProps) const { folly::dynamic result = folly::dynamic::object(); @@ -222,39 +234,195 @@ folly::dynamic HostPlatformViewProps::getDiffProps( result["pointerEvents"] = "auto"; break; } + } - if (nativeId != oldProps->nativeId) { - result["nativeId"] = nativeId; - } + if (nativeId != oldProps->nativeId) { + result["nativeId"] = nativeId; + } - if (testId != oldProps->testId) { - result["testId"] = testId; - } + if (testId != oldProps->testId) { + result["testId"] = testId; + } - if (accessible != oldProps->accessible) { - result["accessible"] = accessible; - } + if (accessible != oldProps->accessible) { + result["accessible"] = accessible; + } - if (getClipsContentToBounds() != oldProps->getClipsContentToBounds()) { - result["overflow"] = getClipsContentToBounds() ? "hidden" : "visible"; - result["scroll"] = result["overflow"]; - } + if (getClipsContentToBounds() != oldProps->getClipsContentToBounds()) { + result["overflow"] = getClipsContentToBounds() ? "hidden" : "visible"; + result["scroll"] = result["overflow"]; + } - if (backfaceVisibility != oldProps->backfaceVisibility) { - switch (backfaceVisibility) { - case BackfaceVisibility::Auto: - result["backfaceVisibility"] = "auto"; - break; - case BackfaceVisibility::Visible: - result["backfaceVisibility"] = "visible"; - break; - case BackfaceVisibility::Hidden: - result["backfaceVisibility"] = "hidden"; - break; - } + if (backfaceVisibility != oldProps->backfaceVisibility) { + switch (backfaceVisibility) { + case BackfaceVisibility::Auto: + result["backfaceVisibility"] = "auto"; + break; + case BackfaceVisibility::Visible: + result["backfaceVisibility"] = "visible"; + break; + case BackfaceVisibility::Hidden: + result["backfaceVisibility"] = "hidden"; + break; } } + // TODO T212662692: pass events as std::bitset<64> to java + if (events != oldProps->events) { + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerEnter, + "onPointerEnter"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerEnterCapture, + "onPointerEnterCapture"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerMove, + "onPointerMove"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerMoveCapture, + "onPointerMoveCapture"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerLeave, + "onPointerLeave"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerLeaveCapture, + "onPointerLeaveCapture"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerOver, + "onPointerOver"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::PointerOut, + "onPointerOut"); + updateEventProp( + result, events, oldProps->events, ViewEvents::Offset::Click, "onClick"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::MoveShouldSetResponder, + "onMoveShouldSetResponder"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::MoveShouldSetResponderCapture, + "onMoveShouldSetResponderCapture"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::StartShouldSetResponder, + "onStartShouldSetResponder"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::StartShouldSetResponderCapture, + "onStartShouldSetResponderCapture"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderGrant, + "onResponderGrant"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderReject, + "onResponderReject"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderStart, + "onResponderStart"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderEnd, + "onResponderEnd"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderRelease, + "onResponderRelease"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderMove, + "onResponderMove"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderTerminate, + "onResponderTerminate"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ResponderTerminationRequest, + "onResponderTerminationRequest"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::ShouldBlockNativeResponder, + "onShouldBlockNativeResponder"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::TouchStart, + "onTouchStart"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::TouchMove, + "onTouchMove"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::TouchEnd, + "onTouchEnd"); + updateEventProp( + result, + events, + oldProps->events, + ViewEvents::Offset::TouchCancel, + "onTouchCancel"); + } + return result; } From 28bcaa4bb6b67e71d91fe6280a5e6c4715bd22d9 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 22 Jan 2025 09:34:08 -0800 Subject: [PATCH 4/4] Implement prop diffing for border props in (#48831) Summary: This diff implements the diffing for border props of changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D59972037 --- .../components/view/HostPlatformViewProps.cpp | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index 85eb8853686..ed937db6e4e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -147,6 +147,192 @@ inline static void updateEventProp( } } +static void updateBorderWidthPropValue( + folly::dynamic& result, + const std::string& propName, + const std::optional& newValue, + const std::optional& oldValue) { + if (newValue != oldValue) { + if (newValue.has_value()) { + result[propName] = newValue.value(); + } else { + result[propName] = NULL; + } + } +} + +static void updateBorderWidthProps( + folly::dynamic& result, + const CascadedBorderWidths& newBorderWidths, + const CascadedBorderWidths& oldBorderWidths) { + updateBorderWidthPropValue( + result, "borderWidth", newBorderWidths.all, oldBorderWidths.all); + updateBorderWidthPropValue( + result, "borderTopWidth", newBorderWidths.top, oldBorderWidths.top); + updateBorderWidthPropValue( + result, "borderLeftWidth", newBorderWidths.left, oldBorderWidths.left); + updateBorderWidthPropValue( + result, "borderStartWidth", newBorderWidths.start, oldBorderWidths.start); + updateBorderWidthPropValue( + result, "borderEndWidth", newBorderWidths.end, oldBorderWidths.end); + updateBorderWidthPropValue( + result, "borderRightWidth", newBorderWidths.right, oldBorderWidths.right); + updateBorderWidthPropValue( + result, + "borderBottomWidth", + newBorderWidths.bottom, + oldBorderWidths.bottom); +} + +static void updateBorderRadiusPropValue( + folly::dynamic& result, + const std::string& propName, + const std::optional& newValue, + const std::optional& oldValue) { + if (newValue != oldValue) { + if (newValue.has_value()) { + if (newValue.value().unit == UnitType::Percent) { + result[propName] = std::to_string(newValue.value().value) + "%"; + } else { + result[propName] = newValue.value().value; + } + } else { + result[propName] = -1; + } + } +} + +static void updateBorderRadiusProps( + folly::dynamic& result, + const CascadedBorderRadii& newBorderRadii, + const CascadedBorderRadii& oldBorderRadii) { + updateBorderRadiusPropValue( + result, "borderRadius", newBorderRadii.all, oldBorderRadii.all); + updateBorderRadiusPropValue( + result, + "borderTopLeftRadius", + newBorderRadii.topLeft, + oldBorderRadii.topLeft); + updateBorderRadiusPropValue( + result, + "borderTopRightRadius", + newBorderRadii.topRight, + oldBorderRadii.topRight); + updateBorderRadiusPropValue( + result, + "borderBottomRightRadius", + newBorderRadii.bottomRight, + oldBorderRadii.bottomRight); + updateBorderRadiusPropValue( + result, + "borderBottomLeftRadius", + newBorderRadii.bottomLeft, + oldBorderRadii.bottomLeft); + updateBorderRadiusPropValue( + result, + "borderTopStartRadius", + newBorderRadii.topStart, + oldBorderRadii.topStart); + updateBorderRadiusPropValue( + result, + "borderTopEndRadius", + newBorderRadii.topEnd, + oldBorderRadii.topEnd); + updateBorderRadiusPropValue( + result, + "borderBottomStartRadius", + newBorderRadii.bottomStart, + oldBorderRadii.bottomStart); + updateBorderRadiusPropValue( + result, + "borderBottomEndRadius", + newBorderRadii.bottomEnd, + oldBorderRadii.bottomEnd); + updateBorderRadiusPropValue( + result, + "borderEndEndRadius", + newBorderRadii.endEnd, + oldBorderRadii.endEnd); + updateBorderRadiusPropValue( + result, "borderEndStartRadius", newBorderRadii.all, oldBorderRadii.all); + updateBorderRadiusPropValue( + result, + "borderStartEndRadius", + newBorderRadii.startEnd, + oldBorderRadii.startEnd); + updateBorderRadiusPropValue( + result, + "borderStartStartRadius", + newBorderRadii.startStart, + oldBorderRadii.startStart); +} + +static void updateBorderStyleProps( + folly::dynamic& result, + const CascadedBorderStyles& newBorderStyle, + const CascadedBorderStyles& oldBorderStyle) { + if (newBorderStyle.all != oldBorderStyle.all) { + if (newBorderStyle.all.has_value()) { + switch (newBorderStyle.all.value()) { + case BorderStyle::Solid: + result["borderStyle"] = "solid"; + break; + case BorderStyle::Dotted: + result["borderStyle"] = "dotted"; + break; + case BorderStyle::Dashed: + result["borderStyle"] = "dashed"; + break; + } + } else { + result["borderStyle"] = NULL; + } + } +} + +static void updateBorderColorPropValue( + folly::dynamic& result, + const std::string& propName, + const std::optional& newColor, + const std::optional& oldColor) { + if (newColor != oldColor) { + result[propName] = newColor.has_value() ? *newColor.value() : NULL; + } +} + +static void updateBorderColorsProps( + folly::dynamic& result, + const CascadedBorderColors& newBorderColor, + const CascadedBorderColors& oldBorderColor) { + updateBorderColorPropValue( + result, "borderColor", newBorderColor.all, oldBorderColor.all); + updateBorderColorPropValue( + result, "borderLeftColor", newBorderColor.left, oldBorderColor.left); + updateBorderColorPropValue( + result, "borderRightColor", newBorderColor.right, oldBorderColor.right); + updateBorderColorPropValue( + result, "borderTopColor", newBorderColor.top, oldBorderColor.top); + updateBorderColorPropValue( + result, + "borderBottomColor", + newBorderColor.bottom, + oldBorderColor.bottom); + updateBorderColorPropValue( + result, "borderStartColor", newBorderColor.start, oldBorderColor.start); + updateBorderColorPropValue( + result, "borderBlockColor", newBorderColor.block, oldBorderColor.block); + updateBorderColorPropValue( + result, + "borderBlockEndColor", + newBorderColor.blockEnd, + oldBorderColor.blockEnd); + updateBorderColorPropValue( + result, + "borderBlockStartColor", + newBorderColor.blockStart, + oldBorderColor.blockStart); +} + folly::dynamic HostPlatformViewProps::getDiffProps( const Props* prevProps) const { folly::dynamic result = folly::dynamic::object(); @@ -268,6 +454,7 @@ folly::dynamic HostPlatformViewProps::getDiffProps( } // TODO T212662692: pass events as std::bitset<64> to java + // Events if (events != oldProps->events) { updateEventProp( result, @@ -423,6 +610,25 @@ folly::dynamic HostPlatformViewProps::getDiffProps( "onTouchCancel"); } + // Borders + auto borderWidths = getBorderWidths(); + auto oldBorderWidths = oldProps->getBorderWidths(); + if (borderWidths != oldBorderWidths) { + updateBorderWidthProps(result, borderWidths, oldBorderWidths); + } + + if (borderStyles != oldProps->borderStyles) { + updateBorderStyleProps(result, borderStyles, oldProps->borderStyles); + } + + if (borderColors != oldProps->borderColors) { + updateBorderColorsProps(result, borderColors, oldProps->borderColors); + } + + if (borderRadii != oldProps->borderRadii) { + updateBorderRadiusProps(result, borderRadii, oldProps->borderRadii); + } + return result; }