diff --git a/Libraries/Components/View/ReactNativeViewAttributes.js b/Libraries/Components/View/ReactNativeViewAttributes.js index 90bd5ff4d13810..411b576269e959 100644 --- a/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/Libraries/Components/View/ReactNativeViewAttributes.js @@ -20,6 +20,8 @@ const UIView = { accessibilityRole: true, accessibilityState: true, accessibilityUnit: true, + accessibilityHours: true, + accessibilityMinutes: true, accessibilityValue: true, accessibilityHint: true, accessibilityLanguage: true, diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 6aaeb1e99282e3..b67094d45cc087 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -38,6 +38,8 @@ const View: React.AbstractComponent< accessibilityRole, accessibilityState, accessibilityUnit, + accessibilityHours, + accessibilityMinutes, accessibilityValue, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, diff --git a/Libraries/Components/View/ViewAccessibility.d.ts b/Libraries/Components/View/ViewAccessibility.d.ts index 626abcfed2567d..bef261bee887b5 100644 --- a/Libraries/Components/View/ViewAccessibility.d.ts +++ b/Libraries/Components/View/ViewAccessibility.d.ts @@ -47,6 +47,8 @@ export interface AccessibilityProps */ accessibilityState?: AccessibilityState | undefined; accessibilityUnit?: AccessibilityUnit | undefined; + accessibilityHours?: number | undefined; + accessibilityMinutes?: number | undefined; /** * alias for accessibilityState diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index bec5e2aa998adb..8c274034d8f7a7 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -503,6 +503,8 @@ export type ViewProps = $ReadOnly<{| */ accessibilityState?: ?AccessibilityState, accessibilityUnit?: ?Stringish, + accessibilityHours?: ?number, + accessibilityMinutes?: ?number, accessibilityValue?: ?AccessibilityValue, /** diff --git a/Libraries/NativeComponent/BaseViewConfig.android.js b/Libraries/NativeComponent/BaseViewConfig.android.js index f9f0525280fe9b..cf30ffa581302c 100644 --- a/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/Libraries/NativeComponent/BaseViewConfig.android.js @@ -177,6 +177,8 @@ const validAttributesForNonEventProps = { accessibilityCollectionItem: true, accessibilityState: true, accessibilityUnit: true, + accessibilityHours: true, + accessibilityMinutes: true, accessibilityActions: true, accessibilityValue: true, importantForAccessibility: true, diff --git a/Libraries/NativeComponent/BaseViewConfig.ios.js b/Libraries/NativeComponent/BaseViewConfig.ios.js index 0fe4d08d094018..3380670a4ca419 100644 --- a/Libraries/NativeComponent/BaseViewConfig.ios.js +++ b/Libraries/NativeComponent/BaseViewConfig.ios.js @@ -190,6 +190,8 @@ const validAttributesForNonEventProps = { accessibilityRole: true, accessibilityState: true, accessibilityUnit: false, + accessibilityHours: false, + accessibilityMinutes: false, nativeID: true, pointerEvents: true, removeClippedSubviews: true, diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 4a42219d75530b..4bef86162f15cf 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -225,6 +225,8 @@ const Text: React.AbstractComponent< {...restProps} accessibilityState={_accessibilityState} accessibilityUnit={props.accessibilityUnit} + accessibilityHours={props.accessibilityHours} + accessibilityMinutes={props.accessibilityMinutes} {...eventHandlersForText} accessibilityLabel={ariaLabel ?? accessibilityLabel} accessibilityRole={ @@ -245,6 +247,8 @@ const Text: React.AbstractComponent< {...restProps} {...eventHandlersForText} accessibilityUnit={props.accessibilityUnit} + accessibilityHours={props.accessibilityHours} + accessibilityMinutes={props.accessibilityMinutes} disabled={_disabled} selectable={_selectable} accessible={ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 36115a8a9be8e8..dab369a950e843 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -55,6 +55,8 @@ public class TextAttributeProps { public static final short TA_KEY_LAYOUT_DIRECTION = 21; public static final short TA_KEY_ACCESSIBILITY_ROLE = 22; public static final short TA_KEY_ACCESSIBILITY_UNIT = 47; + public static final short TA_KEY_ACCESSIBILITY_HOURS = 48; + public static final short TA_KEY_ACCESSIBILITY_MINUTES = 49; public static final int UNSET = -1; @@ -106,6 +108,7 @@ public class TextAttributeProps { protected boolean mIsAccessibilityRoleSet = false; protected @Nullable String mAccessibilityUnit = null; protected boolean mIsAccessibilityLink = false; + protected boolean mIsAccessibilityTtsSpan = false; protected int mFontStyle = UNSET; protected int mFontWeight = UNSET; @@ -211,6 +214,12 @@ public static TextAttributeProps fromMapBuffer(MapBuffer props) { case TA_KEY_ACCESSIBILITY_UNIT: result.setAccessibilityUnit(entry.getStringValue()); break; + case TA_KEY_ACCESSIBILITY_HOURS: + result.setAccessibilityHours(entry.getIntValue()); + break; + case TA_KEY_ACCESSIBILITY_MINUTES: + result.setAccessibilityMinutes(entry.getIntValue()); + break; } } @@ -612,15 +621,27 @@ private void setAccessibilityRole(@Nullable String accessibilityRole) { mIsAccessibilityLink = mAccessibilityRole.equals(AccessibilityRole.LINK); String roleClassName = AccessibilityRole.getValue(AccessibilityRole.fromValue(accessibilityRole)); - mAccessibilityUnit = - ReactTtsSpan.SUPPORTED_UNIT_TYPES.contains(roleClassName) ? roleClassName : null; + mIsAccessibilityTtsSpan = + ReactTtsSpan.SUPPORTED_UNIT_TYPES.contains(roleClassName) && Build.VERSION.SDK_INT >= 21; } } private void setAccessibilityUnit(@Nullable String accessibilityUnit) { - Log.w("TESTING::TextAttributeProps", "setAccessibilityUnit"); - Log.w("TESTING::TextAttributeProps", "accessibilityUnit: " + (accessibilityUnit)); - // not yet implemented + if (accessibilityUnit != null) { + mAccessibilityUnit = accessibilityUnit; + } + } + + private void setAccessibilityHours(@Nullable Integer accessibilityHours) { + if (accessibilityHours != null) { + Log.w("TESTING::TextAttributeProps", "accessibilityHours: " + (accessibilityHours)); + } + } + + private void setAccessibilityMinutes(@Nullable Integer accessibilityMinutes) { + if (accessibilityMinutes != null) { + Log.w("TESTING::TextAttributeProps", "accessibilityMinutes: " + (accessibilityMinutes)); + } } public static int getTextBreakStrategy(@Nullable String textBreakStrategy) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index ed321a89bfef2c..1d7027afe15596 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -19,6 +19,7 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.util.LayoutDirection; +import android.util.Log; import android.util.LruCache; import android.view.View; import androidx.annotation.NonNull; @@ -143,8 +144,12 @@ private static void buildSpannableFromFragment( if (textAttributes.mIsAccessibilityLink) { ops.add(new SetSpanOperation(start, end, new ReactClickableSpan(reactTag))); } - if (textAttributes.mAccessibilityUnit != null && Build.VERSION.SDK_INT >= 21) { + if (textAttributes.mIsAccessibilityTtsSpan) { + // check that textAttributes.mAccessibilityRole == "time" ReactTtsSpan.Builder builder = new ReactTtsSpan.Builder(ReactTtsSpan.TYPE_TIME); + Log.w( + "TESTING::TextLayoutManagerMapBuffer", + "textAttributes.mAccessibilityUnit: " + (textAttributes.mAccessibilityUnit)); builder.setIntArgument(ReactTtsSpan.ARG_HOURS, 10); builder.setIntArgument(ReactTtsSpan.ARG_MINUTES, 30); ops.add(new SetSpanOperation(start, end, builder.build())); diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp index 90fc6513cd226d..63dc72ee8a2dca 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp @@ -98,8 +98,12 @@ void TextAttributes::apply(TextAttributes textAttributes) { accessibilityRole = textAttributes.accessibilityRole.has_value() ? textAttributes.accessibilityRole : accessibilityRole; - accessibilityUnit = !textAttributes.accessibilityUnit.has_value() ? textAttributes.accessibilityUnit + accessibilityUnit = !textAttributes.accessibilityUnit.empty() ? textAttributes.accessibilityUnit : accessibilityUnit; + accessibilityHours = !textAttributes.accessibilityHours.empty() ? textAttributes.accessibilityHours + : accessibilityHours; + accessibilityMinutes = !textAttributes.accessibilityMinutes.empty() ? textAttributes.accessibilityMinutes + : accessibilityMinutes; } #pragma mark - Operators @@ -125,6 +129,8 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { layoutDirection, accessibilityRole, accessibilityUnit, + accessibilityHours, + accessibilityMinutes, textTransform) == std::tie( rhs.foregroundColor, @@ -146,6 +152,8 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { rhs.layoutDirection, rhs.accessibilityRole, rhs.accessibilityUnit, + rhs.accessibilityHours, + rhs.accessibilityMinutes, rhs.textTransform) && floatEquality(opacity, rhs.opacity) && floatEquality(fontSize, rhs.fontSize) && @@ -214,6 +222,8 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const { debugStringConvertibleItem("layoutDirection", layoutDirection), debugStringConvertibleItem("accessibilityRole", accessibilityRole), debugStringConvertibleItem("accessibilityUnit", accessibilityUnit), + debugStringConvertibleItem("accessibilityHours", accessibilityHours), + debugStringConvertibleItem("accessibilityMinutes", accessibilityMinutes), }; } #endif diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/ReactCommon/react/renderer/attributedstring/TextAttributes.h index 4bf42586f5a173..0eca094fad4876 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -79,7 +79,9 @@ class TextAttributes : public DebugStringConvertible { // construction. std::optional layoutDirection{}; std::optional accessibilityRole{}; - AccessibilityUnit accessibilityUnit{}; + std::string accessibilityUnit{}; + std::string accessibilityHours{}; + std::string accessibilityMinutes{}; #pragma mark - Operations @@ -133,7 +135,9 @@ struct hash { textAttributes.isHighlighted, textAttributes.layoutDirection, textAttributes.accessibilityRole, - textAttributes.accessibilityUnit); + textAttributes.accessibilityUnit, + textAttributes.accessibilityHours, + textAttributes.accessibilityMinutes); } }; } // namespace std diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 89451afb84c2c7..acbc5a9d254de5 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -1013,6 +1013,14 @@ inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { _textAttributes( "accessibilityUnit", textAttributes.accessibilityUnit); } + if (!textAttributes.accessibilityHours.empty()) { + _textAttributes( + "accessibilityHours", textAttributes.accessibilityHours); + } + if (!textAttributes.accessibilityMinutes.empty()) { + _textAttributes( + "accessibilityMinutes", textAttributes.accessibilityMinutes); + } return _textAttributes; } @@ -1088,6 +1096,8 @@ constexpr static MapBuffer::Key TA_KEY_LAYOUT_DIRECTION = 21; constexpr static MapBuffer::Key TA_KEY_ACCESSIBILITY_ROLE = 22; constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 23; constexpr static MapBuffer::Key TA_KEY_ACCESSIBILITY_UNIT = 47; +constexpr static MapBuffer::Key TA_KEY_ACCESSIBILITY_HOURS = 48; +constexpr static MapBuffer::Key TA_KEY_ACCESSIBILITY_MINUTES = 49; // constants for ParagraphAttributes serialization constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0; @@ -1240,6 +1250,16 @@ inline MapBuffer toMapBuffer(const TextAttributes &textAttributes) { builder.putString( TA_KEY_ACCESSIBILITY_UNIT, textAttributes.accessibilityUnit); } + if (!textAttributes.accessibilityHours.empty()) { + + builder.putString( + TA_KEY_ACCESSIBILITY_HOURS, textAttributes.accessibilityHours); + } + if (!textAttributes.accessibilityMinutes.empty()) { + + builder.putString( + TA_KEY_ACCESSIBILITY_MINUTES, textAttributes.accessibilityMinutes); + } return builder.build(); } diff --git a/ReactCommon/react/renderer/attributedstring/primitives.h b/ReactCommon/react/renderer/attributedstring/primitives.h index 69c7caffc4000e..39e8f31e18b4a6 100644 --- a/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/ReactCommon/react/renderer/attributedstring/primitives.h @@ -135,10 +135,6 @@ enum class AccessibilityRole { Toolbar, }; -struct AccessibilityUnit { - std::string hours{""}; -}; - enum class TextTransform { None, Uppercase, diff --git a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp index 3d6eddbf8ca7d1..eca8825010e530 100644 --- a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +++ b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp @@ -183,6 +183,18 @@ static TextAttributes convertRawProp( "accessibilityUnit", sourceTextAttributes.accessibilityUnit, defaultTextAttributes.accessibilityUnit); + textAttributes.accessibilityHours = convertRawProp( + context, + rawProps, + "accessibilityHours", + sourceTextAttributes.accessibilityHours, + defaultTextAttributes.accessibilityHours); + textAttributes.accessibilityMinutes = convertRawProp( + context, + rawProps, + "accessibilityMinutes", + sourceTextAttributes.accessibilityMinutes, + defaultTextAttributes.accessibilityMinutes); // Color (accessed in this order by ViewProps) textAttributes.opacity = convertRawProp( @@ -298,8 +310,20 @@ void BaseTextProps::setProp( defaults, value, textAttributes, - accessibilityRole, + accessibilityUnit, "accessibilityUnit"); + REBUILD_FIELD_SWITCH_CASE( + defaults, + value, + textAttributes, + accessibilityHours, + "accessibilityHours"); + REBUILD_FIELD_SWITCH_CASE( + defaults, + value, + textAttributes, + accessibilityMinutes, + "accessibilityMinutes"); REBUILD_FIELD_SWITCH_CASE( defaults, value, textAttributes, opacity, "opacity"); REBUILD_FIELD_SWITCH_CASE( diff --git a/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp b/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp index 80f0187564e20e..932e5d8b65b2cb 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -45,6 +45,24 @@ AccessibilityProps::AccessibilityProps( "accessibilityUnit", sourceProps.accessibilityUnit, {})), + accessibilityHours( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.accessibilityHours + : convertRawProp( + context, + rawProps, + "accessibilityHours", + sourceProps.accessibilityHours, + {})), + accessibilityMinutes( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.accessibilityMinutes + : convertRawProp( + context, + rawProps, + "accessibilityMinutes", + sourceProps.accessibilityMinutes, + {})), accessibilityLabel( CoreFeatures::enablePropIteratorSetter ? sourceProps.accessibilityLabel @@ -221,6 +239,8 @@ void AccessibilityProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(accessible, false); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityState, {}); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityUnit, {}); + RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityHours, {}); + RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityMinutes, {}); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabel, std::string{""}); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabelledBy, {}); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityHint, std::string{""}); diff --git a/ReactCommon/react/renderer/components/view/AccessibilityProps.h b/ReactCommon/react/renderer/components/view/AccessibilityProps.h index 387245325f24ab..106fb6ae092c71 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityProps.h +++ b/ReactCommon/react/renderer/components/view/AccessibilityProps.h @@ -40,6 +40,8 @@ class AccessibilityProps { bool accessible{false}; AccessibilityState accessibilityState; AccessibilityUnit accessibilityUnit; + AccessibilityUnit accessibilityHours; + AccessibilityUnit accessibilityMinutes; std::string accessibilityLabel{""}; AccessibilityLabelledBy accessibilityLabelledBy{}; AccessibilityLiveRegion accessibilityLiveRegion{ diff --git a/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h b/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h index f1d2a92fff8fd4..54f7fd1336b6f2 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h +++ b/ReactCommon/react/renderer/components/view/AccessibilityPropsMapBuffer.h @@ -24,6 +24,8 @@ constexpr MapBuffer::Key AP_ACCESSIBILITY_VALUE = 7; constexpr MapBuffer::Key AP_ACCESSIBLE = 8; constexpr MapBuffer::Key AP_IMPORTANT_FOR_ACCESSIBILITY = 19; constexpr MapBuffer::Key AP_ACCESSIBILITY_UNIT = 47; +constexpr MapBuffer::Key AP_ACCESSIBILITY_HOURS = 48; +constexpr MapBuffer::Key AP_ACCESSIBILITY_MINUTES = 49; // AccessibilityAction values constexpr MapBuffer::Key ACCESSIBILITY_ACTION_NAME = 0; diff --git a/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h b/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h index 6314b89768603f..a15bce9957e7bc 100644 --- a/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h +++ b/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h @@ -191,6 +191,13 @@ inline void fromRawValue( */ } +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + int &result) { + result = 9; +} + inline std::string toString( const AccessibilityUnit &accessibilityUnit) { return "default string"; diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index 039496f5f682b7..e8495e18951dab 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -172,7 +172,7 @@ class AccessibilityExample extends React.Component<{}> { My number is 17:00