Add accessibility and view props required for Android to C++ layer

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
This commit is contained in:
Andrei Shikov 2022-02-22 08:03:09 -08:00 коммит произвёл Facebook GitHub Bot
Родитель d264f1e725
Коммит da72b5d02c
9 изменённых файлов: 240 добавлений и 3 удалений

Просмотреть файл

@ -10,6 +10,7 @@
#include <butter/optional.h>
#include <cinttypes>
#include <string>
#include <vector>
namespace facebook {
namespace react {
@ -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;
@ -102,5 +119,11 @@ enum class ImportantForAccessibility {
NoHideDescendants,
};
enum class AccessibilityLiveRegion {
None,
Polite,
Assertive,
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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,

Просмотреть файл

@ -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{};

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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 ||
@ -46,6 +45,10 @@ 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) ||
@ -53,6 +56,14 @@ void ViewShadowNode::initialize() noexcept {
!(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 {

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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