Skip to content

Commit

Permalink
Add accessibility and view props required for Android to C++ layer
Browse files Browse the repository at this point in the history
Summary:
Parses a set of props previously missing from C++ representation (they weren't required for iOS and core processing before).

Changelog: [Internal] - Added missing fields for Android to C++ view props

Reviewed By: sammy-SC

Differential Revision: D33797489

fbshipit-source-id: 1625baa0c1a592fcef409a5f206496dff0368912
  • Loading branch information
Andrei Shikov authored and facebook-github-bot committed Feb 22, 2022
1 parent d264f1e commit da72b5d
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <butter/optional.h>
#include <cinttypes>
#include <string>
#include <vector>

namespace facebook {
namespace react {
Expand Down Expand Up @@ -75,6 +76,22 @@ constexpr bool operator!=(
return !(rhs == lhs);
}

struct AccessibilityLabelledBy {
std::vector<std::string> value{};
};

inline static bool operator==(
AccessibilityLabelledBy const &lhs,
AccessibilityLabelledBy const &rhs) {
return lhs.value == rhs.value;
}

inline static bool operator!=(
AccessibilityLabelledBy const &lhs,
AccessibilityLabelledBy const &rhs) {
return !(lhs == rhs);
}

struct AccessibilityValue {
butter::optional<int> min;
butter::optional<int> max;
Expand Down Expand Up @@ -102,5 +119,11 @@ enum class ImportantForAccessibility {
NoHideDescendants,
};

enum class AccessibilityLiveRegion {
None,
Polite,
Assertive,
};

} // namespace react
} // namespace facebook
18 changes: 18 additions & 0 deletions ReactCommon/react/renderer/components/view/AccessibilityProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ AccessibilityProps::AccessibilityProps(
"accessibilityLabel",
sourceProps.accessibilityLabel,
"")),
accessibilityLabelledBy(convertRawProp(
context,
rawProps,
"accessibilityLabelledBy",
sourceProps.accessibilityLabelledBy,
{})),
accessibilityLiveRegion(convertRawProp(
context,
rawProps,
"accessibilityLiveRegion",
sourceProps.accessibilityLiveRegion,
AccessibilityLiveRegion::None)),
accessibilityRole(convertRawProp(
context,
rawProps,
"accessibilityRole",
sourceProps.accessibilityRole,
"")),
accessibilityHint(convertRawProp(
context,
rawProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class AccessibilityProps {
AccessibilityTraits accessibilityTraits{AccessibilityTraits::None};
AccessibilityState accessibilityState;
std::string accessibilityLabel{""};
AccessibilityLabelledBy accessibilityLabelledBy{};
AccessibilityLiveRegion accessibilityLiveRegion{
AccessibilityLiveRegion::None};
std::string accessibilityRole{""};
std::string accessibilityHint{""};
AccessibilityValue accessibilityValue;
std::vector<AccessibilityAction> accessibilityActions{};
Expand Down
44 changes: 42 additions & 2 deletions ReactCommon/react/renderer/components/view/ViewProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,53 @@ ViewProps::ViewProps(
rawProps,
"removeClippedSubviews",
sourceProps.removeClippedSubviews,
false)),
false))
#ifdef ANDROID
,
elevation(convertRawProp(
context,
rawProps,
"elevation",
sourceProps.elevation,
{})){};
{})),
nativeBackground(convertRawProp(
context,
rawProps,
"nativeBackgroundAndroid",
sourceProps.nativeBackground,
{})),
nativeForeground(convertRawProp(
context,
rawProps,
"nativeForegroundAndroid",
sourceProps.nativeForeground,
{})),
focusable(convertRawProp(
context,
rawProps,
"focusable",
sourceProps.focusable,
{})),
hasTVPreferredFocus(convertRawProp(
context,
rawProps,
"hasTVPreferredFocus",
sourceProps.hasTVPreferredFocus,
{})),
needsOffscreenAlphaCompositing(convertRawProp(
context,
rawProps,
"needsOffscreenAlphaCompositing",
sourceProps.needsOffscreenAlphaCompositing,
{})),
renderToHardwareTextureAndroid(convertRawProp(
context,
rawProps,
"renderToHardwareTextureAndroid",
sourceProps.renderToHardwareTextureAndroid,
{}))
#endif
{};

#pragma mark - Convenience Methods

Expand Down
12 changes: 12 additions & 0 deletions ReactCommon/react/renderer/components/view/ViewProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps {

Float elevation{}; /* Android-only */

#ifdef ANDROID

butter::optional<NativeDrawable> nativeBackground{};
butter::optional<NativeDrawable> nativeForeground{};

bool focusable{false};
bool hasTVPreferredFocus{false};
bool needsOffscreenAlphaCompositing{false};
bool renderToHardwareTextureAndroid{false};

#endif

#pragma mark - Convenience Methods

BorderMetrics resolveBorderMetrics(LayoutMetrics const &layoutMetrics) const;
Expand Down
13 changes: 12 additions & 1 deletion ReactCommon/react/renderer/components/view/ViewShadowNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ void ViewShadowNode::initialize() noexcept {
viewProps.pointerEvents == PointerEventsMode::None ||
!viewProps.nativeId.empty() || viewProps.accessible ||
viewProps.opacity != 1.0 || viewProps.transform != Transform{} ||
viewProps.elevation != 0 ||
(viewProps.zIndex.has_value() &&
viewProps.yogaStyle.positionType() != YGPositionTypeStatic) ||
viewProps.yogaStyle.display() == YGDisplayNone ||
Expand All @@ -46,13 +45,25 @@ void ViewShadowNode::initialize() noexcept {
viewProps.importantForAccessibility != ImportantForAccessibility::Auto ||
viewProps.removeClippedSubviews;

#ifdef ANDROID
formsStackingContext = formsStackingContext || viewProps.elevation != 0;
#endif

bool formsView = formsStackingContext ||
isColorMeaningful(viewProps.backgroundColor) ||
isColorMeaningful(viewProps.foregroundColor) ||
viewProps.events.bits.any() ||
!(viewProps.yogaStyle.border() == YGStyle::Edges{}) ||
!viewProps.testId.empty();

#ifdef ANDROID
formsView = formsView || viewProps.nativeBackground.has_value() ||
viewProps.nativeForeground.has_value() || viewProps.focusable ||
viewProps.hasTVPreferredFocus ||
viewProps.needsOffscreenAlphaCompositing ||
viewProps.renderToHardwareTextureAndroid;
#endif

if (formsView) {
traits_.set(ShadowNodeTraits::Trait::FormsView);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,5 +263,38 @@ inline void fromRawValue(
}
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
AccessibilityLabelledBy &result) {
if (value.hasType<std::string>()) {
result.value.push_back((std::string)value);
} else if (value.hasType<std::vector<std::string>>()) {
result.value = (std::vector<std::string>)value;
}
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
AccessibilityLiveRegion &result) {
react_native_assert(value.hasType<std::string>());
if (value.hasType<std::string>()) {
auto string = (std::string)value;
if (string == "none") {
result = AccessibilityLiveRegion::None;
} else if (string == "polite") {
result = AccessibilityLiveRegion::Polite;
} else if (string == "assertive") {
result = AccessibilityLiveRegion::Assertive;
} else {
LOG(ERROR) << "Unsupported AccessibilityLiveRegion value: " << string;
react_native_assert(false);
}
} else {
LOG(ERROR) << "Unsupported AccessibilityLiveRegion type";
}
}

} // namespace react
} // namespace facebook
43 changes: 43 additions & 0 deletions ReactCommon/react/renderer/components/view/primitives.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,5 +219,48 @@ struct BorderMetrics {
}
};

#ifdef ANDROID

struct NativeDrawable {
enum class Kind {
Ripple,
ThemeAttr,
};

struct Ripple {
butter::optional<int32_t> color{};
bool borderless{false};
butter::optional<Float> rippleRadius{};

bool operator==(const Ripple &rhs) const {
return std::tie(this->color, this->borderless, this->rippleRadius) ==
std::tie(rhs.color, rhs.borderless, rhs.rippleRadius);
}
};

Kind kind;
std::string themeAttr;
Ripple ripple;

bool operator==(const NativeDrawable &rhs) const {
if (this->kind != rhs.kind)
return false;
switch (this->kind) {
case Kind::ThemeAttr:
return this->themeAttr == rhs.themeAttr;
case Kind::Ripple:
return this->ripple == rhs.ripple;
}
}

bool operator!=(const NativeDrawable &rhs) const {
return !(*this == rhs);
}

~NativeDrawable() = default;
};

#endif

} // namespace react
} // namespace facebook
53 changes: 53 additions & 0 deletions ReactCommon/react/renderer/components/view/propsConversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,5 +599,58 @@ static inline ViewEvents convertRawProp(
return result;
}

#ifdef ANDROID

static inline void fromRawValue(
const PropsParserContext &context,
RawValue const &rawValue,
NativeDrawable &result) {
auto map = (butter::map<std::string, RawValue>)rawValue;

auto typeIterator = map.find("type");
react_native_assert(
typeIterator != map.end() && typeIterator->second.hasType<std::string>());
std::string type = (std::string)typeIterator->second;

if (type == "ThemeAttrAndroid") {
auto attrIterator = map.find("attribute");
react_native_assert(
attrIterator != map.end() &&
attrIterator->second.hasType<std::string>());

result = NativeDrawable{
.kind = NativeDrawable::Kind::ThemeAttr,
.themeAttr = (std::string)attrIterator->second,
};
} else if (type == "RippleAndroid") {
auto color = map.find("color");
auto borderless = map.find("borderless");
auto rippleRadius = map.find("rippleRadius");

result = NativeDrawable{
.kind = NativeDrawable::Kind::Ripple,
.ripple =
NativeDrawable::Ripple{
.color = color != map.end() && color->second.hasType<int32_t>()
? (int32_t)color->second
: butter::optional<int32_t>{},
.borderless = borderless != map.end() &&
borderless->second.hasType<bool>()
? (bool)borderless->second
: false,
.rippleRadius = rippleRadius != map.end() &&
rippleRadius->second.hasType<Float>()
? (Float)rippleRadius->second
: butter::optional<Float>{},
},
};
} else {
LOG(ERROR) << "Unknown native drawable type: " << type;
react_native_assert(false);
}
}

#endif

} // namespace react
} // namespace facebook

0 comments on commit da72b5d

Please sign in to comment.