diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt index 97c9fb513b0..7218daf70cf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactMapBufferPropSetter.kt @@ -62,6 +62,8 @@ object ReactMapBufferPropSetter { private const val VP_POINTER_OUT_CAPTURE = 42 private const val VP_POINTER_OVER = 43 private const val VP_POINTER_OVER_CAPTURE = 44 + private const val VP_BORDER_CURVES = 45 // iOS only + private const val VP_FG_COLOR = 46 // iOS only? // Yoga values private const val YG_BORDER_WIDTH = 100 @@ -141,6 +143,9 @@ object ReactMapBufferPropSetter { // TODO: color for some reason can be object in Java but not in C++ viewManager.backgroundColor(view, entry.intValue) } + VP_FG_COLOR -> { + // Prop not used on Android? + } VP_BORDER_COLOR -> { viewManager.borderColor(view, entry.mapBufferValue) } @@ -148,7 +153,10 @@ object ReactMapBufferPropSetter { viewManager.borderRadius(view, entry.mapBufferValue) } VP_BORDER_STYLE -> { - viewManager.borderStyle(view, entry.intValue) + val styleBuffer = entry.mapBufferValue + if (styleBuffer.contains(CORNER_ALL)) { + viewManager.borderStyle(view, (styleBuffer.getDouble(CORNER_ALL)).toInt()) + } } VP_ELEVATION -> { viewManager.setElevation(view, entry.doubleValue.toFloat()) diff --git a/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index 4d11993a38e..a26aeeb4895 100644 --- a/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -9,7 +9,6 @@ #include "CppViewMutationsWrapper.h" #include "EventEmitterWrapper.h" #include "StateWrapperImpl.h" -#include "viewPropConversions.h" #include #include @@ -264,12 +263,11 @@ local_ref FabricMountingManager::getProps( react_native_assert( newShadowView.props->rawProps.empty() && "Raw props must be empty when views are using mapbuffer"); - auto oldProps = oldShadowView.props != nullptr - ? static_cast(*oldShadowView.props) - : ViewProps{}; - auto newProps = static_cast(*newShadowView.props); - return JReadableMapBuffer::createWithContents( - viewPropsDiff(oldProps, newProps)); + + // MapBufferBuilder must be constructed and live in this scope, + MapBufferBuilder builder; + newShadowView.props->propsDiffMapBuffer(&*oldShadowView.props, builder); + return JReadableMapBuffer::createWithContents(builder.build()); } else { return ReadableNativeMap::newObjectCxxArgs(newShadowView.props->rawProps); } diff --git a/ReactAndroid/src/main/jni/react/fabric/viewPropConversions.h b/ReactAndroid/src/main/jni/react/fabric/viewPropConversions.h index 1271fe3e903..fe44e662340 100644 --- a/ReactAndroid/src/main/jni/react/fabric/viewPropConversions.h +++ b/ReactAndroid/src/main/jni/react/fabric/viewPropConversions.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include #include @@ -19,58 +20,6 @@ namespace facebook { namespace react { namespace { -// ViewProps values -constexpr MapBuffer::Key VP_ACCESSIBILITY_ACTIONS = 0; -constexpr MapBuffer::Key VP_ACCESSIBILITY_HINT = 1; -constexpr MapBuffer::Key VP_ACCESSIBILITY_LABEL = 2; -constexpr MapBuffer::Key VP_ACCESSIBILITY_LABELLED_BY = 3; -constexpr MapBuffer::Key VP_ACCESSIBILITY_LIVE_REGION = 4; -constexpr MapBuffer::Key VP_ACCESSIBILITY_ROLE = 5; -constexpr MapBuffer::Key VP_ACCESSIBILITY_STATE = 6; -constexpr MapBuffer::Key VP_ACCESSIBILITY_VALUE = 7; -constexpr MapBuffer::Key VP_ACCESSIBLE = 8; -constexpr MapBuffer::Key VP_BACKFACE_VISIBILITY = 9; -constexpr MapBuffer::Key VP_BG_COLOR = 10; -constexpr MapBuffer::Key VP_BORDER_COLOR = 11; -constexpr MapBuffer::Key VP_BORDER_RADII = 12; -constexpr MapBuffer::Key VP_BORDER_STYLE = 13; -constexpr MapBuffer::Key VP_COLLAPSABLE = 14; -constexpr MapBuffer::Key VP_ELEVATION = 15; -constexpr MapBuffer::Key VP_FOCUSABLE = 16; -constexpr MapBuffer::Key VP_HAS_TV_FOCUS = 17; -constexpr MapBuffer::Key VP_HIT_SLOP = 18; -constexpr MapBuffer::Key VP_IMPORTANT_FOR_ACCESSIBILITY = 19; -constexpr MapBuffer::Key VP_NATIVE_BACKGROUND = 20; -constexpr MapBuffer::Key VP_NATIVE_FOREGROUND = 21; -constexpr MapBuffer::Key VP_NATIVE_ID = 22; -constexpr MapBuffer::Key VP_OFFSCREEN_ALPHA_COMPOSITING = 23; -constexpr MapBuffer::Key VP_OPACITY = 24; -constexpr MapBuffer::Key VP_POINTER_EVENTS = 25; -constexpr MapBuffer::Key VP_POINTER_ENTER = 26; -constexpr MapBuffer::Key VP_POINTER_LEAVE = 27; -constexpr MapBuffer::Key VP_POINTER_MOVE = 28; -constexpr MapBuffer::Key VP_REMOVE_CLIPPED_SUBVIEW = 29; -constexpr MapBuffer::Key VP_RENDER_TO_HARDWARE_TEXTURE = 30; -constexpr MapBuffer::Key VP_SHADOW_COLOR = 31; -constexpr MapBuffer::Key VP_TEST_ID = 32; -constexpr MapBuffer::Key VP_TRANSFORM = 33; -constexpr MapBuffer::Key VP_ZINDEX = 34; -constexpr MapBuffer::Key VP_POINTER_ENTER_CAPTURE = 38; -constexpr MapBuffer::Key VP_POINTER_LEAVE_CAPTURE = 39; -constexpr MapBuffer::Key VP_POINTER_MOVE_CAPTURE = 40; -constexpr MapBuffer::Key VP_POINTER_OVER = 41; -constexpr MapBuffer::Key VP_POINTER_OVER_CAPTURE = 42; -constexpr MapBuffer::Key VP_POINTER_OUT = 43; -constexpr MapBuffer::Key VP_POINTER_OUT_CAPTURE = 44; - -// Yoga values -constexpr MapBuffer::Key YG_BORDER_WIDTH = 100; -constexpr MapBuffer::Key YG_OVERFLOW = 101; - -// AccessibilityAction values -constexpr MapBuffer::Key ACCESSIBILITY_ACTION_NAME = 0; -constexpr MapBuffer::Key ACCESSIBILITY_ACTION_LABEL = 1; - static MapBuffer convertAccessibilityActions( std::vector const &actions) { MapBufferBuilder builder(actions.size()); @@ -262,294 +211,5 @@ MapBuffer convertTransform(Transform const &transform) { } } // namespace -/** - * Diffs two sets of ViewProps into MapBuffer. - * TODO: Currently unsupported: nextFocusForward/Left/Up/Right/Down - */ -static inline MapBuffer viewPropsDiff( - ViewProps const &oldProps, - ViewProps const &newProps) { - MapBufferBuilder builder; - if (oldProps.accessibilityActions != newProps.accessibilityActions) { - builder.putMapBuffer( - VP_ACCESSIBILITY_ACTIONS, - convertAccessibilityActions(newProps.accessibilityActions)); - } - - if (oldProps.accessibilityHint != newProps.accessibilityHint) { - builder.putString(VP_ACCESSIBILITY_HINT, newProps.accessibilityHint); - } - - if (oldProps.accessibilityLabel != newProps.accessibilityLabel) { - builder.putString(VP_ACCESSIBILITY_LABEL, newProps.accessibilityLabel); - } - - if (oldProps.accessibilityLabelledBy != newProps.accessibilityLabelledBy) { - builder.putMapBuffer( - VP_ACCESSIBILITY_LABELLED_BY, - convertAccessibilityLabelledBy(newProps.accessibilityLabelledBy)); - } - - if (oldProps.accessibilityLiveRegion != newProps.accessibilityLiveRegion) { - int value; - switch (newProps.accessibilityLiveRegion) { - case AccessibilityLiveRegion::None: - value = 0; - break; - case AccessibilityLiveRegion::Polite: - value = 1; - break; - case AccessibilityLiveRegion::Assertive: - value = 2; - break; - } - builder.putInt(VP_ACCESSIBILITY_LIVE_REGION, value); - } - - if (oldProps.accessibilityRole != newProps.accessibilityRole) { - builder.putString(VP_ACCESSIBILITY_ROLE, newProps.accessibilityRole); - } - - if (oldProps.accessibilityState != newProps.accessibilityState) { - builder.putMapBuffer( - VP_ACCESSIBILITY_STATE, - convertAccessibilityState(newProps.accessibilityState)); - } - - if (oldProps.accessibilityValue != newProps.accessibilityValue) { - builder.putString( - VP_ACCESSIBILITY_VALUE, newProps.accessibilityValue.text.value_or("")); - } - - if (oldProps.accessible != newProps.accessible) { - builder.putBool(VP_ACCESSIBLE, newProps.accessible); - } - - if (oldProps.backfaceVisibility != newProps.backfaceVisibility) { - int value; - switch (newProps.backfaceVisibility) { - case BackfaceVisibility::Auto: - value = 0; - break; - case BackfaceVisibility::Visible: - value = 1; - break; - case BackfaceVisibility::Hidden: - value = 2; - break; - } - builder.putInt(VP_BACKFACE_VISIBILITY, value); - } - - if (oldProps.backgroundColor != newProps.backgroundColor) { - builder.putInt(VP_BG_COLOR, toAndroidRepr(newProps.backgroundColor)); - } - - if (oldProps.borderColors != newProps.borderColors) { - builder.putMapBuffer( - VP_BORDER_COLOR, convertBorderColors(newProps.borderColors)); - } - - if (oldProps.borderRadii != newProps.borderRadii) { - builder.putMapBuffer( - VP_BORDER_RADII, convertBorderRadii(newProps.borderRadii)); - } - - if (oldProps.borderStyles != newProps.borderStyles) { - int value = -1; - if (newProps.borderStyles.all.has_value()) { - switch (newProps.borderStyles.all.value()) { - case BorderStyle::Solid: - value = 0; - break; - case BorderStyle::Dotted: - value = 1; - break; - case BorderStyle::Dashed: - value = 2; - break; - } - } - builder.putInt(VP_BORDER_STYLE, value); - } - - if (oldProps.elevation != newProps.elevation) { - builder.putDouble(VP_ELEVATION, newProps.elevation); - } - -#ifdef ANDROID - if (oldProps.focusable != newProps.focusable) { - builder.putBool(VP_FOCUSABLE, newProps.focusable); - } - - if (oldProps.hasTVPreferredFocus != newProps.hasTVPreferredFocus) { - builder.putBool(VP_HAS_TV_FOCUS, newProps.hasTVPreferredFocus); - } -#endif - - if (oldProps.hitSlop != newProps.hitSlop) { - builder.putMapBuffer(VP_HIT_SLOP, convertEdgeInsets(newProps.hitSlop)); - } - - if (oldProps.importantForAccessibility != - newProps.importantForAccessibility) { - int value; - switch (newProps.importantForAccessibility) { - case ImportantForAccessibility::Auto: - value = 0; - break; - case ImportantForAccessibility::Yes: - value = 1; - break; - case ImportantForAccessibility::No: - value = 2; - break; - case ImportantForAccessibility::NoHideDescendants: - value = 3; - break; - } - builder.putInt(VP_IMPORTANT_FOR_ACCESSIBILITY, value); - } - -#ifdef ANDROID - if (oldProps.nativeBackground != newProps.nativeBackground) { - builder.putMapBuffer( - VP_NATIVE_BACKGROUND, - convertNativeBackground(newProps.nativeBackground)); - } - - if (oldProps.nativeForeground != newProps.nativeForeground) { - builder.putMapBuffer( - VP_NATIVE_FOREGROUND, - convertNativeBackground(newProps.nativeForeground)); - } -#endif - - if (oldProps.nativeId != newProps.nativeId) { - builder.putString(VP_NATIVE_ID, newProps.nativeId); - } - -#ifdef ANDROID - if (oldProps.needsOffscreenAlphaCompositing != - newProps.needsOffscreenAlphaCompositing) { - builder.putBool( - VP_OFFSCREEN_ALPHA_COMPOSITING, - newProps.needsOffscreenAlphaCompositing); - } -#endif - - if (oldProps.opacity != newProps.opacity) { - builder.putDouble(VP_OPACITY, newProps.opacity); - } - - if (oldProps.pointerEvents != newProps.pointerEvents) { - int value; - switch (newProps.pointerEvents) { - case PointerEventsMode::Auto: - value = 0; - break; - case PointerEventsMode::None: - value = 1; - break; - case PointerEventsMode::BoxNone: - value = 2; - break; - case PointerEventsMode::BoxOnly: - value = 3; - break; - } - - builder.putInt(VP_POINTER_EVENTS, value); - } - - if (oldProps.events != newProps.events) { - builder.putBool( - VP_POINTER_ENTER, newProps.events[ViewEvents::Offset::PointerEnter]); - builder.putBool( - VP_POINTER_LEAVE, newProps.events[ViewEvents::Offset::PointerLeave]); - builder.putBool( - VP_POINTER_MOVE, newProps.events[ViewEvents::Offset::PointerMove]); - - builder.putBool( - VP_POINTER_ENTER_CAPTURE, - newProps.events[ViewEvents::Offset::PointerEnterCapture]); - builder.putBool( - VP_POINTER_LEAVE_CAPTURE, - newProps.events[ViewEvents::Offset::PointerLeaveCapture]); - builder.putBool( - VP_POINTER_MOVE_CAPTURE, - newProps.events[ViewEvents::Offset::PointerMoveCapture]); - builder.putBool( - VP_POINTER_OVER, newProps.events[ViewEvents::Offset::PointerOver]); - builder.putBool( - VP_POINTER_OVER_CAPTURE, - newProps.events[ViewEvents::Offset::PointerOverCapture]); - - builder.putBool( - VP_POINTER_OUT, newProps.events[ViewEvents::Offset::PointerOut]); - builder.putBool( - VP_POINTER_OUT_CAPTURE, - newProps.events[ViewEvents::Offset::PointerOutCapture]); - } - - if (oldProps.removeClippedSubviews != newProps.removeClippedSubviews) { - builder.putBool(VP_REMOVE_CLIPPED_SUBVIEW, newProps.removeClippedSubviews); - } - -#ifdef ANDROID - if (oldProps.renderToHardwareTextureAndroid != - newProps.renderToHardwareTextureAndroid) { - builder.putBool( - VP_RENDER_TO_HARDWARE_TEXTURE, newProps.renderToHardwareTextureAndroid); - } -#endif - - if (oldProps.shadowColor != newProps.shadowColor) { - builder.putInt(VP_SHADOW_COLOR, toAndroidRepr(newProps.shadowColor)); - } - - if (oldProps.testId != newProps.testId) { - builder.putString(VP_TEST_ID, newProps.testId); - } - - // TODO: seems like transform covers rotation/translate/scale/skew? - - if (oldProps.transform != newProps.transform) { - builder.putMapBuffer(VP_TRANSFORM, convertTransform(newProps.transform)); - } - - if (oldProps.zIndex != newProps.zIndex) { - builder.putInt(VP_ZINDEX, newProps.zIndex.value_or(0)); - } - - if (oldProps.yogaStyle != newProps.yogaStyle) { - auto const &oldStyle = oldProps.yogaStyle; - auto const &newStyle = newProps.yogaStyle; - - if (!(oldStyle.border() == newStyle.border())) { - builder.putMapBuffer( - YG_BORDER_WIDTH, convertBorderWidths(newStyle.border())); - } - - if (oldStyle.overflow() != newStyle.overflow()) { - int value; - switch (newStyle.overflow()) { - case YGOverflowVisible: - value = 0; - break; - case YGOverflowHidden: - value = 1; - break; - case YGOverflowScroll: - value = 2; - break; - } - builder.putInt(YG_OVERFLOW, value); - } - } - - return builder.build(); -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/components/view/AccessibilityProps.h b/ReactCommon/react/renderer/components/view/AccessibilityProps.h index e9e6aa7b3f0..a2ee2f2d08c 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityProps.h +++ b/ReactCommon/react/renderer/components/view/AccessibilityProps.h @@ -32,6 +32,11 @@ class AccessibilityProps { static bool enablePropIteratorSetter; +#ifdef ANDROID + void propsDiffMapBuffer(Props const *oldProps, MapBufferBuilder &builder) + const; +#endif + #pragma mark - Props bool accessible{false}; diff --git a/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp b/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp new file mode 100644 index 00000000000..31f34b3e75b --- /dev/null +++ b/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.cpp @@ -0,0 +1,168 @@ +/* + * 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 "AccessibilityPropsMapBuffer.h" +#include "AccessibilityProps.h" + +#include + +namespace facebook { +namespace react { + +#ifdef ANDROID + +static MapBuffer convertAccessibilityActions( + std::vector const &actions) { + MapBufferBuilder builder(actions.size()); + for (auto i = 0; i < actions.size(); i++) { + auto const &action = actions[i]; + MapBufferBuilder actionsBuilder(2); + actionsBuilder.putString(ACCESSIBILITY_ACTION_NAME, action.name); + if (action.label.has_value()) { + actionsBuilder.putString( + ACCESSIBILITY_ACTION_LABEL, action.label.value()); + } + builder.putMapBuffer(i, actionsBuilder.build()); + } + return builder.build(); +} + +static MapBuffer convertAccessibilityLabelledBy( + AccessibilityLabelledBy const &labelledBy) { + MapBufferBuilder builder(labelledBy.value.size()); + for (auto i = 0; i < labelledBy.value.size(); i++) { + builder.putString(i, labelledBy.value[i]); + } + return builder.build(); +} + +// AccessibilityState values +constexpr MapBuffer::Key ACCESSIBILITY_STATE_BUSY = 0; +constexpr MapBuffer::Key ACCESSIBILITY_STATE_DISABLED = 1; +constexpr MapBuffer::Key ACCESSIBILITY_STATE_EXPANDED = 2; +constexpr MapBuffer::Key ACCESSIBILITY_STATE_SELECTED = 3; +constexpr MapBuffer::Key ACCESSIBILITY_STATE_CHECKED = 4; + +MapBuffer convertAccessibilityState(AccessibilityState const &state) { + MapBufferBuilder builder(5); + builder.putBool(ACCESSIBILITY_STATE_BUSY, state.busy); + builder.putBool(ACCESSIBILITY_STATE_DISABLED, state.disabled); + builder.putBool(ACCESSIBILITY_STATE_EXPANDED, state.expanded); + builder.putBool(ACCESSIBILITY_STATE_SELECTED, state.selected); + int checked; + switch (state.checked) { + case AccessibilityState::Unchecked: + checked = 0; + break; + case AccessibilityState::Checked: + checked = 1; + break; + case AccessibilityState::Mixed: + checked = 2; + break; + case AccessibilityState::None: + checked = 3; + break; + } + builder.putInt(ACCESSIBILITY_STATE_CHECKED, checked); + return builder.build(); +} + +// TODO: Currently unsupported: nextFocusForward/Left/Up/Right/Down +void AccessibilityProps::propsDiffMapBuffer( + Props const *oldPropsPtr, + MapBufferBuilder &builder) const { + // Call with default props if necessary + if (oldPropsPtr == nullptr) { + AccessibilityProps defaultProps{}; + propsDiffMapBuffer(reinterpret_cast(&defaultProps), builder); + return; + } + + AccessibilityProps const &oldProps = + *(reinterpret_cast(oldPropsPtr)); + AccessibilityProps const &newProps = *this; + + if (oldProps.accessibilityActions != newProps.accessibilityActions) { + builder.putMapBuffer( + AP_ACCESSIBILITY_ACTIONS, + convertAccessibilityActions(newProps.accessibilityActions)); + } + + if (oldProps.accessibilityHint != newProps.accessibilityHint) { + builder.putString(AP_ACCESSIBILITY_HINT, newProps.accessibilityHint); + } + + if (oldProps.accessibilityLabel != newProps.accessibilityLabel) { + builder.putString(AP_ACCESSIBILITY_LABEL, newProps.accessibilityLabel); + } + + if (oldProps.accessibilityLabelledBy != newProps.accessibilityLabelledBy) { + builder.putMapBuffer( + AP_ACCESSIBILITY_LABELLED_BY, + convertAccessibilityLabelledBy(newProps.accessibilityLabelledBy)); + } + + if (oldProps.accessibilityLiveRegion != newProps.accessibilityLiveRegion) { + int value; + switch (newProps.accessibilityLiveRegion) { + case AccessibilityLiveRegion::None: + value = 0; + break; + case AccessibilityLiveRegion::Polite: + value = 1; + break; + case AccessibilityLiveRegion::Assertive: + value = 2; + break; + } + builder.putInt(AP_ACCESSIBILITY_LIVE_REGION, value); + } + + if (oldProps.accessibilityRole != newProps.accessibilityRole) { + builder.putString(AP_ACCESSIBILITY_ROLE, newProps.accessibilityRole); + } + + if (oldProps.accessibilityState != newProps.accessibilityState) { + builder.putMapBuffer( + AP_ACCESSIBILITY_STATE, + convertAccessibilityState(newProps.accessibilityState)); + } + + if (oldProps.accessibilityValue != newProps.accessibilityValue) { + builder.putString( + AP_ACCESSIBILITY_VALUE, newProps.accessibilityValue.text.value_or("")); + } + + if (oldProps.accessible != newProps.accessible) { + builder.putBool(AP_ACCESSIBLE, newProps.accessible); + } + + if (oldProps.importantForAccessibility != + newProps.importantForAccessibility) { + int value; + switch (newProps.importantForAccessibility) { + case ImportantForAccessibility::Auto: + value = 0; + break; + case ImportantForAccessibility::Yes: + value = 1; + break; + case ImportantForAccessibility::No: + value = 2; + break; + case ImportantForAccessibility::NoHideDescendants: + value = 3; + break; + } + builder.putInt(AP_IMPORTANT_FOR_ACCESSIBILITY, value); + } +} +#endif + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h b/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h new file mode 100644 index 00000000000..a4aa6c927ad --- /dev/null +++ b/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h @@ -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. + */ + +#pragma once + +#include + +namespace facebook { +namespace react { + +#ifdef ANDROID +constexpr MapBuffer::Key AP_ACCESSIBILITY_ACTIONS = 0; +constexpr MapBuffer::Key AP_ACCESSIBILITY_HINT = 1; +constexpr MapBuffer::Key AP_ACCESSIBILITY_LABEL = 2; +constexpr MapBuffer::Key AP_ACCESSIBILITY_LABELLED_BY = 3; +constexpr MapBuffer::Key AP_ACCESSIBILITY_LIVE_REGION = 4; +constexpr MapBuffer::Key AP_ACCESSIBILITY_ROLE = 5; +constexpr MapBuffer::Key AP_ACCESSIBILITY_STATE = 6; +constexpr MapBuffer::Key AP_ACCESSIBILITY_VALUE = 7; +constexpr MapBuffer::Key AP_ACCESSIBLE = 8; +constexpr MapBuffer::Key AP_IMPORTANT_FOR_ACCESSIBILITY = 19; + +// AccessibilityAction values +constexpr MapBuffer::Key ACCESSIBILITY_ACTION_NAME = 0; +constexpr MapBuffer::Key ACCESSIBILITY_ACTION_LABEL = 1; +#endif + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/view/ViewProps.h b/ReactCommon/react/renderer/components/view/ViewProps.h index cc09768ad73..ea08ea8defb 100644 --- a/ReactCommon/react/renderer/components/view/ViewProps.h +++ b/ReactCommon/react/renderer/components/view/ViewProps.h @@ -41,6 +41,11 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps { const char *propName, RawValue const &value); +#ifdef ANDROID + void propsDiffMapBuffer(Props const *oldProps, MapBufferBuilder &builder) + const override; +#endif + #pragma mark - Props // Color @@ -51,7 +56,7 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps { // Borders CascadedBorderRadii borderRadii{}; CascadedBorderColors borderColors{}; - CascadedBorderCurves borderCurves{}; + CascadedBorderCurves borderCurves{}; // iOS only? CascadedBorderStyles borderStyles{}; // Shadow diff --git a/ReactCommon/react/renderer/components/view/ViewPropsMapBuffer.cpp b/ReactCommon/react/renderer/components/view/ViewPropsMapBuffer.cpp new file mode 100644 index 00000000000..4136842c3b8 --- /dev/null +++ b/ReactCommon/react/renderer/components/view/ViewPropsMapBuffer.cpp @@ -0,0 +1,202 @@ +/* + * 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. + */ + +#ifdef ANDROID + +#include "ViewPropsMapBuffer.h" +#include "ViewProps.h" + +#include "viewPropConversions.h" + +#include +#include + +namespace facebook { +namespace react { + +// TODO: Currently unsupported: nextFocusForward/Left/Up/Right/Down +void ViewProps::propsDiffMapBuffer( + Props const *oldPropsPtr, + MapBufferBuilder &builder) const { + // Call with default props if necessary + if (oldPropsPtr == nullptr) { + ViewProps defaultProps{}; + propsDiffMapBuffer(&defaultProps, builder); + return; + } + + // Delegate to base classes + YogaStylableProps::propsDiffMapBuffer(oldPropsPtr, builder); + AccessibilityProps::propsDiffMapBuffer(oldPropsPtr, builder); + + ViewProps const &oldProps = *(static_cast(oldPropsPtr)); + ViewProps const &newProps = *this; + + if (oldProps.backfaceVisibility != newProps.backfaceVisibility) { + int value; + switch (newProps.backfaceVisibility) { + case BackfaceVisibility::Auto: + value = 0; + break; + case BackfaceVisibility::Visible: + value = 1; + break; + case BackfaceVisibility::Hidden: + value = 2; + break; + } + builder.putInt(VP_BACKFACE_VISIBILITY, value); + } + + if (oldProps.backgroundColor != newProps.backgroundColor) { + builder.putInt(VP_BG_COLOR, toAndroidRepr(newProps.backgroundColor)); + } + + if (oldProps.foregroundColor != newProps.foregroundColor) { + builder.putInt(VP_FG_COLOR, toAndroidRepr(newProps.foregroundColor)); + } + + if (oldProps.borderCurves != newProps.borderCurves) { + builder.putMapBuffer( + VP_BORDER_CURVES, convertCascadedCorners(newProps.borderCurves)); + } + + if (oldProps.borderColors != newProps.borderColors) { + builder.putMapBuffer( + VP_BORDER_COLOR, convertBorderColors(newProps.borderColors)); + } + + if (oldProps.borderRadii != newProps.borderRadii) { + builder.putMapBuffer( + VP_BORDER_RADII, convertCascadedCorners(newProps.borderRadii)); + } + + if (oldProps.borderStyles != newProps.borderStyles) { + builder.putMapBuffer( + VP_BORDER_STYLE, convertCascadedEdges(newProps.borderStyles)); + } + + if (oldProps.elevation != newProps.elevation) { + builder.putDouble(VP_ELEVATION, newProps.elevation); + } + + if (oldProps.focusable != newProps.focusable) { + builder.putBool(VP_FOCUSABLE, newProps.focusable); + } + + if (oldProps.hasTVPreferredFocus != newProps.hasTVPreferredFocus) { + builder.putBool(VP_HAS_TV_FOCUS, newProps.hasTVPreferredFocus); + } + + if (oldProps.hitSlop != newProps.hitSlop) { + builder.putMapBuffer(VP_HIT_SLOP, convertEdgeInsets(newProps.hitSlop)); + } + + if (oldProps.nativeBackground != newProps.nativeBackground) { + builder.putMapBuffer( + VP_NATIVE_BACKGROUND, + convertNativeBackground(newProps.nativeBackground)); + } + + if (oldProps.nativeForeground != newProps.nativeForeground) { + builder.putMapBuffer( + VP_NATIVE_FOREGROUND, + convertNativeBackground(newProps.nativeForeground)); + } + + if (oldProps.needsOffscreenAlphaCompositing != + newProps.needsOffscreenAlphaCompositing) { + builder.putBool( + VP_OFFSCREEN_ALPHA_COMPOSITING, + newProps.needsOffscreenAlphaCompositing); + } + + if (oldProps.opacity != newProps.opacity) { + builder.putDouble(VP_OPACITY, newProps.opacity); + } + + if (oldProps.pointerEvents != newProps.pointerEvents) { + int value; + switch (newProps.pointerEvents) { + case PointerEventsMode::Auto: + value = 0; + break; + case PointerEventsMode::None: + value = 1; + break; + case PointerEventsMode::BoxNone: + value = 2; + break; + case PointerEventsMode::BoxOnly: + value = 3; + break; + } + + builder.putInt(VP_POINTER_EVENTS, value); + } + + if (oldProps.events != newProps.events) { + builder.putBool( + VP_POINTER_ENTER, newProps.events[ViewEvents::Offset::PointerEnter]); + builder.putBool( + VP_POINTER_LEAVE, newProps.events[ViewEvents::Offset::PointerLeave]); + builder.putBool( + VP_POINTER_MOVE, newProps.events[ViewEvents::Offset::PointerMove]); + + builder.putBool( + VP_POINTER_ENTER_CAPTURE, + newProps.events[ViewEvents::Offset::PointerEnterCapture]); + builder.putBool( + VP_POINTER_LEAVE_CAPTURE, + newProps.events[ViewEvents::Offset::PointerLeaveCapture]); + builder.putBool( + VP_POINTER_MOVE_CAPTURE, + newProps.events[ViewEvents::Offset::PointerMoveCapture]); + builder.putBool( + VP_POINTER_OVER, newProps.events[ViewEvents::Offset::PointerOver]); + builder.putBool( + VP_POINTER_OVER_CAPTURE, + newProps.events[ViewEvents::Offset::PointerOverCapture]); + + builder.putBool( + VP_POINTER_OUT, newProps.events[ViewEvents::Offset::PointerOut]); + builder.putBool( + VP_POINTER_OUT_CAPTURE, + newProps.events[ViewEvents::Offset::PointerOutCapture]); + } + + if (oldProps.removeClippedSubviews != newProps.removeClippedSubviews) { + builder.putBool(VP_REMOVE_CLIPPED_SUBVIEW, newProps.removeClippedSubviews); + } + + if (oldProps.renderToHardwareTextureAndroid != + newProps.renderToHardwareTextureAndroid) { + builder.putBool( + VP_RENDER_TO_HARDWARE_TEXTURE, newProps.renderToHardwareTextureAndroid); + } + + if (oldProps.shadowColor != newProps.shadowColor) { + builder.putInt(VP_SHADOW_COLOR, toAndroidRepr(newProps.shadowColor)); + } + + if (oldProps.testId != newProps.testId) { + builder.putString(VP_TEST_ID, newProps.testId); + } + + if (oldProps.transform != newProps.transform) { + builder.putMapBuffer(VP_TRANSFORM, convertTransform(newProps.transform)); + } + + if (oldProps.zIndex != newProps.zIndex) { + builder.putInt(VP_ZINDEX, newProps.zIndex.value_or(0)); + } +} + +} // namespace react +} // namespace facebook + +#endif diff --git a/ReactCommon/react/renderer/components/view/ViewPropsMapBuffer.h b/ReactCommon/react/renderer/components/view/ViewPropsMapBuffer.h new file mode 100644 index 00000000000..45a583575ae --- /dev/null +++ b/ReactCommon/react/renderer/components/view/ViewPropsMapBuffer.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + +#pragma once + +#include + +namespace facebook { +namespace react { + +#ifdef ANDROID +constexpr MapBuffer::Key VP_BACKFACE_VISIBILITY = 9; +constexpr MapBuffer::Key VP_BG_COLOR = 10; +constexpr MapBuffer::Key VP_BORDER_COLOR = 11; +constexpr MapBuffer::Key VP_BORDER_RADII = 12; +constexpr MapBuffer::Key VP_BORDER_STYLE = 13; +constexpr MapBuffer::Key VP_COLLAPSABLE = 14; +constexpr MapBuffer::Key VP_ELEVATION = 15; +constexpr MapBuffer::Key VP_FOCUSABLE = 16; +constexpr MapBuffer::Key VP_HAS_TV_FOCUS = 17; +constexpr MapBuffer::Key VP_HIT_SLOP = 18; +constexpr MapBuffer::Key VP_NATIVE_BACKGROUND = 20; +constexpr MapBuffer::Key VP_NATIVE_FOREGROUND = 21; +constexpr MapBuffer::Key VP_OFFSCREEN_ALPHA_COMPOSITING = 23; +constexpr MapBuffer::Key VP_OPACITY = 24; +constexpr MapBuffer::Key VP_POINTER_EVENTS = 25; +constexpr MapBuffer::Key VP_POINTER_ENTER = 26; +constexpr MapBuffer::Key VP_POINTER_LEAVE = 27; +constexpr MapBuffer::Key VP_POINTER_MOVE = 28; +constexpr MapBuffer::Key VP_REMOVE_CLIPPED_SUBVIEW = 29; +constexpr MapBuffer::Key VP_RENDER_TO_HARDWARE_TEXTURE = 30; +constexpr MapBuffer::Key VP_SHADOW_COLOR = 31; +constexpr MapBuffer::Key VP_TEST_ID = 32; +constexpr MapBuffer::Key VP_TRANSFORM = 33; +constexpr MapBuffer::Key VP_ZINDEX = 34; +constexpr MapBuffer::Key VP_POINTER_ENTER_CAPTURE = 38; +constexpr MapBuffer::Key VP_POINTER_LEAVE_CAPTURE = 39; +constexpr MapBuffer::Key VP_POINTER_MOVE_CAPTURE = 40; +constexpr MapBuffer::Key VP_POINTER_OVER = 41; +constexpr MapBuffer::Key VP_POINTER_OVER_CAPTURE = 42; +constexpr MapBuffer::Key VP_POINTER_OUT = 43; +constexpr MapBuffer::Key VP_POINTER_OUT_CAPTURE = 44; +constexpr MapBuffer::Key VP_BORDER_CURVES = 45; +constexpr MapBuffer::Key VP_FG_COLOR = 46; + +// Yoga values +constexpr MapBuffer::Key YG_BORDER_WIDTH = 100; +constexpr MapBuffer::Key YG_OVERFLOW = 101; +#endif + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/view/YogaStylableProps.h b/ReactCommon/react/renderer/components/view/YogaStylableProps.h index 86cf60e81be..b19a90df2f0 100644 --- a/ReactCommon/react/renderer/components/view/YogaStylableProps.h +++ b/ReactCommon/react/renderer/components/view/YogaStylableProps.h @@ -31,6 +31,11 @@ class YogaStylableProps : public Props { const char *propName, RawValue const &value); +#ifdef ANDROID + void propsDiffMapBuffer(Props const *oldProps, MapBufferBuilder &builder) + const override; +#endif + #pragma mark - Props YGStyle yogaStyle{}; @@ -39,7 +44,7 @@ class YogaStylableProps : public Props { #pragma mark - DebugStringConvertible (Partial) - SharedDebugStringConvertibleList getDebugProps() const; + SharedDebugStringConvertibleList getDebugProps() const override; #endif }; diff --git a/ReactCommon/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp b/ReactCommon/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp new file mode 100644 index 00000000000..ac8a3c2ad55 --- /dev/null +++ b/ReactCommon/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp @@ -0,0 +1,87 @@ +/* + * 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. + */ + +#ifdef ANDROID + +#include "ViewProps.h" +#include "ViewPropsMapBuffer.h" + +#include "viewPropConversions.h" + +#include + +namespace facebook { +namespace react { + +MapBuffer convertBorderWidths(YGStyle::Edges const &border) { + MapBufferBuilder builder(7); + putOptionalFloat( + builder, EDGE_TOP, optionalFloatFromYogaValue(border[YGEdgeTop])); + putOptionalFloat( + builder, EDGE_RIGHT, optionalFloatFromYogaValue(border[YGEdgeRight])); + putOptionalFloat( + builder, EDGE_BOTTOM, optionalFloatFromYogaValue(border[YGEdgeBottom])); + putOptionalFloat( + builder, EDGE_LEFT, optionalFloatFromYogaValue(border[YGEdgeLeft])); + putOptionalFloat( + builder, EDGE_START, optionalFloatFromYogaValue(border[YGEdgeStart])); + putOptionalFloat( + builder, EDGE_END, optionalFloatFromYogaValue(border[YGEdgeEnd])); + putOptionalFloat( + builder, EDGE_ALL, optionalFloatFromYogaValue(border[YGEdgeAll])); + return builder.build(); +} + +// TODO: Currently unsupported: nextFocusForward/Left/Up/Right/Down +void YogaStylableProps::propsDiffMapBuffer( + Props const *oldPropsPtr, + MapBufferBuilder &builder) const { + // Call with default props if necessary + if (oldPropsPtr == nullptr) { + YogaStylableProps defaultProps{}; + propsDiffMapBuffer(&defaultProps, builder); + return; + } + + // Delegate to base classes + Props::propsDiffMapBuffer(oldPropsPtr, builder); + + YogaStylableProps const &oldProps = + *(static_cast(oldPropsPtr)); + YogaStylableProps const &newProps = *this; + + if (oldProps.yogaStyle != newProps.yogaStyle) { + auto const &oldStyle = oldProps.yogaStyle; + auto const &newStyle = newProps.yogaStyle; + + if (!(oldStyle.border() == newStyle.border())) { + builder.putMapBuffer( + YG_BORDER_WIDTH, convertBorderWidths(newStyle.border())); + } + + if (oldStyle.overflow() != newStyle.overflow()) { + int value; + switch (newStyle.overflow()) { + case YGOverflowVisible: + value = 0; + break; + case YGOverflowHidden: + value = 1; + break; + case YGOverflowScroll: + value = 2; + break; + } + builder.putInt(YG_OVERFLOW, value); + } + } +} + +} // namespace react +} // namespace facebook + +#endif diff --git a/ReactCommon/react/renderer/components/view/YogaStylablePropsMapBuffer.h b/ReactCommon/react/renderer/components/view/YogaStylablePropsMapBuffer.h new file mode 100644 index 00000000000..69b0e419b71 --- /dev/null +++ b/ReactCommon/react/renderer/components/view/YogaStylablePropsMapBuffer.h @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#pragma once + +#ifdef ANDROID + +#include + +namespace facebook { +namespace react { + +// Yoga values +constexpr MapBuffer::Key YG_BORDER_WIDTH = 100; +constexpr MapBuffer::Key YG_OVERFLOW = 101; + +} // namespace react +} // namespace facebook + +#endif diff --git a/ReactCommon/react/renderer/components/view/viewPropConversions.h b/ReactCommon/react/renderer/components/view/viewPropConversions.h new file mode 100644 index 00000000000..6a672aef01a --- /dev/null +++ b/ReactCommon/react/renderer/components/view/viewPropConversions.h @@ -0,0 +1,198 @@ +/* + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace facebook { +namespace react { + +namespace { + +constexpr MapBuffer::Key EDGE_TOP = 0; +constexpr MapBuffer::Key EDGE_LEFT = 1; +constexpr MapBuffer::Key EDGE_RIGHT = 2; +constexpr MapBuffer::Key EDGE_BOTTOM = 3; +constexpr MapBuffer::Key EDGE_START = 4; +constexpr MapBuffer::Key EDGE_END = 5; +constexpr MapBuffer::Key EDGE_ALL = 6; + +constexpr MapBuffer::Key CORNER_TOP_LEFT = 0; +constexpr MapBuffer::Key CORNER_TOP_RIGHT = 1; +constexpr MapBuffer::Key CORNER_BOTTOM_RIGHT = 2; +constexpr MapBuffer::Key CORNER_BOTTOM_LEFT = 3; +constexpr MapBuffer::Key CORNER_TOP_START = 4; +constexpr MapBuffer::Key CORNER_TOP_END = 5; +constexpr MapBuffer::Key CORNER_BOTTOM_END = 6; +constexpr MapBuffer::Key CORNER_BOTTOM_START = 7; +constexpr MapBuffer::Key CORNER_ALL = 8; + +inline void putOptionalFloat( + MapBufferBuilder &builder, + MapBuffer::Key key, + std::optional const &value) { + builder.putDouble(key, value.value_or(NAN)); +} + +inline std::optional optionalFromValue( + std::optional const &value) { + if (!value) { + return {}; + } + + return {value.value() == BorderCurve::Circular ? 1 : 2}; +} + +inline std::optional optionalFromValue( + std::optional const &value) { + return value; +} + +inline std::optional optionalFromValue( + std::optional const &value) { + if (!value) { + return {}; + } + + int intValue = -1; + switch (value.value()) { + case BorderStyle::Solid: + intValue = 0; + break; + case BorderStyle::Dotted: + intValue = 1; + break; + case BorderStyle::Dashed: + intValue = 2; + break; + } + + return {intValue}; +} + +inline void putOptionalColor( + MapBufferBuilder &builder, + MapBuffer::Key key, + std::optional const &color) { + builder.putInt(key, color.has_value() ? toAndroidRepr(color.value()) : -1); +} + +inline MapBuffer convertBorderColors(CascadedBorderColors const &colors) { + MapBufferBuilder builder(7); + putOptionalColor(builder, EDGE_TOP, colors.top); + putOptionalColor(builder, EDGE_RIGHT, colors.right); + putOptionalColor(builder, EDGE_BOTTOM, colors.bottom); + putOptionalColor(builder, EDGE_LEFT, colors.left); + putOptionalColor(builder, EDGE_START, colors.start); + putOptionalColor(builder, EDGE_END, colors.end); + putOptionalColor(builder, EDGE_ALL, colors.all); + return builder.build(); +} + +template +MapBuffer convertCascadedEdges(CascadedRectangleEdges const &edges) { + MapBufferBuilder builder(7); + putOptionalFloat(builder, EDGE_TOP, optionalFromValue(edges.top)); + putOptionalFloat(builder, EDGE_RIGHT, optionalFromValue(edges.right)); + putOptionalFloat(builder, EDGE_BOTTOM, optionalFromValue(edges.bottom)); + putOptionalFloat(builder, EDGE_LEFT, optionalFromValue(edges.left)); + putOptionalFloat(builder, EDGE_START, optionalFromValue(edges.start)); + putOptionalFloat(builder, EDGE_END, optionalFromValue(edges.end)); + putOptionalFloat(builder, EDGE_ALL, optionalFromValue(edges.all)); + return builder.build(); +} + +template +MapBuffer convertCascadedCorners(CascadedRectangleCorners const &corners) { + MapBufferBuilder builder(9); + putOptionalFloat( + builder, CORNER_TOP_LEFT, optionalFromValue(corners.topLeft)); + putOptionalFloat( + builder, CORNER_TOP_RIGHT, optionalFromValue(corners.topRight)); + putOptionalFloat( + builder, CORNER_BOTTOM_RIGHT, optionalFromValue(corners.bottomRight)); + putOptionalFloat( + builder, CORNER_BOTTOM_LEFT, optionalFromValue(corners.bottomLeft)); + putOptionalFloat( + builder, CORNER_TOP_START, optionalFromValue(corners.topStart)); + putOptionalFloat(builder, CORNER_TOP_END, optionalFromValue(corners.topEnd)); + putOptionalFloat( + builder, CORNER_BOTTOM_END, optionalFromValue(corners.bottomEnd)); + putOptionalFloat( + builder, CORNER_BOTTOM_START, optionalFromValue(corners.bottomStart)); + putOptionalFloat(builder, CORNER_ALL, optionalFromValue(corners.all)); + return builder.build(); +} + +inline MapBuffer convertEdgeInsets(EdgeInsets const &insets) { + MapBufferBuilder builder(4); + builder.putDouble(EDGE_TOP, insets.top); + builder.putDouble(EDGE_RIGHT, insets.right); + builder.putDouble(EDGE_BOTTOM, insets.bottom); + builder.putDouble(EDGE_LEFT, insets.left); + return builder.build(); +} + +#ifdef ANDROID + +constexpr MapBuffer::Key NATIVE_DRAWABLE_KIND = 0; +constexpr MapBuffer::Key NATIVE_DRAWABLE_ATTRIBUTE = 1; +constexpr MapBuffer::Key NATIVE_DRAWABLE_COLOR = 2; +constexpr MapBuffer::Key NATIVE_DRAWABLE_BORDERLESS = 3; +constexpr MapBuffer::Key NATIVE_DRAWABLE_RIPPLE_RADIUS = 4; + +inline MapBuffer convertNativeBackground( + std::optional const &value) { + if (!value.has_value()) { + return MapBufferBuilder::EMPTY(); + } + + auto const &drawable = value.value(); + MapBufferBuilder builder(4); + switch (drawable.kind) { + case NativeDrawable::Kind::ThemeAttr: + builder.putInt(NATIVE_DRAWABLE_KIND, 0); + builder.putString(NATIVE_DRAWABLE_ATTRIBUTE, drawable.themeAttr); + break; + case NativeDrawable::Kind::Ripple: + builder.putInt(NATIVE_DRAWABLE_KIND, 1); + if (drawable.ripple.color.has_value()) { + builder.putInt(NATIVE_DRAWABLE_COLOR, drawable.ripple.color.value()); + } + + builder.putBool(NATIVE_DRAWABLE_BORDERLESS, drawable.ripple.borderless); + if (drawable.ripple.rippleRadius.has_value()) { + builder.putDouble( + NATIVE_DRAWABLE_RIPPLE_RADIUS, + drawable.ripple.rippleRadius.value()); + } + break; + } + return builder.build(); +} + +#endif + +inline MapBuffer convertTransform(Transform const &transform) { + MapBufferBuilder builder(16); + for (int32_t i = 0; i < transform.matrix.size(); i++) { + builder.putDouble(i, transform.matrix[i]); + } + return builder.build(); +} +} // namespace + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/core/CMakeLists.txt b/ReactCommon/react/renderer/core/CMakeLists.txt index 09627498c93..d776881dda1 100644 --- a/ReactCommon/react/renderer/core/CMakeLists.txt +++ b/ReactCommon/react/renderer/core/CMakeLists.txt @@ -26,4 +26,5 @@ target_link_libraries(react_render_core react_debug react_render_debug react_render_graphics + react_render_mapbuffer react_utils) diff --git a/ReactCommon/react/renderer/core/Props.cpp b/ReactCommon/react/renderer/core/Props.cpp index cdca7cc8fbe..e78db62c209 100644 --- a/ReactCommon/react/renderer/core/Props.cpp +++ b/ReactCommon/react/renderer/core/Props.cpp @@ -6,6 +6,7 @@ */ #include "Props.h" +#include "PropsMapBuffer.h" #include #include diff --git a/ReactCommon/react/renderer/core/Props.h b/ReactCommon/react/renderer/core/Props.h index a6f4113caad..8daeb35dbe5 100644 --- a/ReactCommon/react/renderer/core/Props.h +++ b/ReactCommon/react/renderer/core/Props.h @@ -16,6 +16,10 @@ #include #include +#ifdef ANDROID +#include +#endif + namespace facebook { namespace react { @@ -71,6 +75,10 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible { #ifdef ANDROID folly::dynamic rawProps = folly::dynamic::object(); + + virtual void propsDiffMapBuffer( + Props const *oldProps, + MapBufferBuilder &builder) const; #endif }; diff --git a/ReactCommon/react/renderer/core/PropsMapBuffer.cpp b/ReactCommon/react/renderer/core/PropsMapBuffer.cpp new file mode 100644 index 00000000000..6ce2241ef46 --- /dev/null +++ b/ReactCommon/react/renderer/core/PropsMapBuffer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "PropsMapBuffer.h" +#include "Props.h" + +#include + +namespace facebook { +namespace react { + +#ifdef ANDROID +void Props::propsDiffMapBuffer( + Props const *oldPropsPtr, + MapBufferBuilder &builder) const { + // Call with default props if necessary + if (oldPropsPtr == nullptr) { + Props defaultProps{}; + propsDiffMapBuffer(&defaultProps, builder); + return; + } + + Props const &oldProps = *oldPropsPtr; + Props const &newProps = *this; + + if (oldProps.nativeId != newProps.nativeId) { + builder.putString(PROPS_NATIVE_ID, nativeId); + } +} +#endif + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/core/PropsMapBuffer.h b/ReactCommon/react/renderer/core/PropsMapBuffer.h new file mode 100644 index 00000000000..ad6b9bd08df --- /dev/null +++ b/ReactCommon/react/renderer/core/PropsMapBuffer.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +#pragma once + +#ifdef ANDROID + +#include + +namespace facebook { +namespace react { + +constexpr MapBuffer::Key PROPS_MAX = 1; +constexpr MapBuffer::Key PROPS_NATIVE_ID = 1; + +} // namespace react +} // namespace facebook + +#endif