A11Y: improve accessibility on event reactions.
This commit is contained in:
parent
024a6b4f90
commit
4fb73497f1
4 changed files with 77 additions and 4 deletions
|
|
@ -28,7 +28,11 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.onClick
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
@ -47,6 +51,7 @@ import io.element.android.libraries.designsystem.theme.components.Surface
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||||
import io.element.android.libraries.matrix.ui.media.MediaRequestData
|
import io.element.android.libraries.matrix.ui.media.MediaRequestData
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("ModifierClickableOrder") // This is needed to display the right ripple shape
|
@Suppress("ModifierClickableOrder") // This is needed to display the right ripple shape
|
||||||
|
|
@ -68,6 +73,47 @@ fun MessagesReactionButton(
|
||||||
buttonColor
|
buttonColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val a11yText = when (content) {
|
||||||
|
is MessagesReactionsButtonContent.Icon -> stringResource(id = R.string.screen_room_timeline_add_reaction)
|
||||||
|
is MessagesReactionsButtonContent.Text -> content.text
|
||||||
|
is MessagesReactionsButtonContent.Reaction -> {
|
||||||
|
val reaction = if (content.reaction.key.startsWith("mxc://")) {
|
||||||
|
stringResource(CommonStrings.common_an_image)
|
||||||
|
} else {
|
||||||
|
content.reaction.key
|
||||||
|
}
|
||||||
|
if (content.isHighlighted) {
|
||||||
|
if (content.reaction.count == 1) {
|
||||||
|
stringResource(R.string.screen_room_timeline_reaction_you_a11y, reaction)
|
||||||
|
} else {
|
||||||
|
pluralStringResource(
|
||||||
|
R.plurals.screen_room_timeline_reaction_including_you_a11y,
|
||||||
|
content.reaction.count - 1,
|
||||||
|
content.reaction.count - 1,
|
||||||
|
reaction,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pluralStringResource(
|
||||||
|
R.plurals.screen_room_timeline_reaction_a11y,
|
||||||
|
content.reaction.count,
|
||||||
|
content.reaction.count,
|
||||||
|
reaction,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val a11yClickLabel = if (content is MessagesReactionsButtonContent.Reaction) {
|
||||||
|
if (content.isHighlighted) {
|
||||||
|
stringResource(id = CommonStrings.a11y_remove_reaction_with, content.reaction.key)
|
||||||
|
} else {
|
||||||
|
stringResource(id = CommonStrings.a11y_react_with, content.reaction.key)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.background(Color.Transparent)
|
.background(Color.Transparent)
|
||||||
|
|
@ -86,7 +132,18 @@ fun MessagesReactionButton(
|
||||||
// Inner border, to highlight when selected
|
// Inner border, to highlight when selected
|
||||||
.border(BorderStroke(1.dp, borderColor), RoundedCornerShape(corner = CornerSize(12.dp)))
|
.border(BorderStroke(1.dp, borderColor), RoundedCornerShape(corner = CornerSize(12.dp)))
|
||||||
.background(buttonColor, RoundedCornerShape(corner = CornerSize(12.dp)))
|
.background(buttonColor, RoundedCornerShape(corner = CornerSize(12.dp)))
|
||||||
.padding(vertical = 4.dp, horizontal = 10.dp),
|
.padding(vertical = 4.dp, horizontal = 10.dp)
|
||||||
|
.clearAndSetSemantics {
|
||||||
|
contentDescription = a11yText
|
||||||
|
if (content is MessagesReactionsButtonContent.Reaction) {
|
||||||
|
onClick(
|
||||||
|
label = a11yClickLabel
|
||||||
|
) {
|
||||||
|
onClick()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
color = buttonColor
|
color = buttonColor
|
||||||
) {
|
) {
|
||||||
when (content) {
|
when (content) {
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,22 @@
|
||||||
<string name="screen_room_mentions_at_room_title">"Everyone"</string>
|
<string name="screen_room_mentions_at_room_title">"Everyone"</string>
|
||||||
<string name="screen_room_retry_send_menu_send_again_action">"Send again"</string>
|
<string name="screen_room_retry_send_menu_send_again_action">"Send again"</string>
|
||||||
<string name="screen_room_retry_send_menu_title">"Your message failed to send"</string>
|
<string name="screen_room_retry_send_menu_title">"Your message failed to send"</string>
|
||||||
<string name="screen_room_timeline_add_reaction">"Add emoji"</string>
|
<string name="screen_room_timeline_add_reaction">"Add a reaction"</string>
|
||||||
<string name="screen_room_timeline_beginning_of_room">"This is the beginning of %1$s."</string>
|
<string name="screen_room_timeline_beginning_of_room">"This is the beginning of %1$s."</string>
|
||||||
<string name="screen_room_timeline_beginning_of_room_no_name">"This is the beginning of this conversation."</string>
|
<string name="screen_room_timeline_beginning_of_room_no_name">"This is the beginning of this conversation."</string>
|
||||||
<string name="screen_room_timeline_legacy_call">"Unsupported call. Ask if the caller can use the new Element X app."</string>
|
<string name="screen_room_timeline_legacy_call">"Unsupported call. Ask if the caller can use the new Element X app."</string>
|
||||||
<string name="screen_room_timeline_less_reactions">"Show less"</string>
|
<string name="screen_room_timeline_less_reactions">"Show less"</string>
|
||||||
<string name="screen_room_timeline_message_copied">"Message copied"</string>
|
<string name="screen_room_timeline_message_copied">"Message copied"</string>
|
||||||
<string name="screen_room_timeline_no_permission_to_post">"You do not have permission to post to this room"</string>
|
<string name="screen_room_timeline_no_permission_to_post">"You do not have permission to post to this room"</string>
|
||||||
|
<plurals name="screen_room_timeline_reaction_a11y">
|
||||||
|
<item quantity="one">"%1$d member reacted with %2$s"</item>
|
||||||
|
<item quantity="other">"%1$d members reacted with %2$s"</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="screen_room_timeline_reaction_including_you_a11y">
|
||||||
|
<item quantity="one">"You and %1$d member reacted with %2$s"</item>
|
||||||
|
<item quantity="other">"You and %1$d members reacted with %2$s"</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="screen_room_timeline_reaction_you_a11y">"You reacted with %1$s"</string>
|
||||||
<string name="screen_room_timeline_reactions_show_less">"Show less"</string>
|
<string name="screen_room_timeline_reactions_show_less">"Show less"</string>
|
||||||
<string name="screen_room_timeline_reactions_show_more">"Show more"</string>
|
<string name="screen_room_timeline_reactions_show_more">"Show more"</string>
|
||||||
<string name="screen_room_timeline_read_marker_title">"New"</string>
|
<string name="screen_room_timeline_read_marker_title">"New"</string>
|
||||||
|
|
|
||||||
|
|
@ -391,7 +391,10 @@ class MessagesViewTest {
|
||||||
rule.setMessagesView(
|
rule.setMessagesView(
|
||||||
state = state,
|
state = state,
|
||||||
)
|
)
|
||||||
rule.onAllNodesWithText("👍️").onFirst().performClick()
|
rule.onAllNodesWithText(
|
||||||
|
text = "👍️",
|
||||||
|
useUnmergedTree = true,
|
||||||
|
).onFirst().performClick()
|
||||||
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("👍️", timelineItem.eventOrTransactionId))
|
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("👍️", timelineItem.eventOrTransactionId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -411,7 +414,10 @@ class MessagesViewTest {
|
||||||
rule.setMessagesView(
|
rule.setMessagesView(
|
||||||
state = state,
|
state = state,
|
||||||
)
|
)
|
||||||
rule.onAllNodesWithText("👍️").onFirst().performTouchInput { longClick() }
|
rule.onAllNodesWithText(
|
||||||
|
text = "👍️",
|
||||||
|
useUnmergedTree = true,
|
||||||
|
).onFirst().performTouchInput { longClick() }
|
||||||
eventsRecorder.assertSingle(ReactionSummaryEvents.ShowReactionSummary(timelineItem.eventId!!, timelineItem.reactionsState.reactions, "👍️"))
|
eventsRecorder.assertSingle(ReactionSummaryEvents.ShowReactionSummary(timelineItem.eventId!!, timelineItem.reactionsState.reactions, "👍️"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@
|
||||||
<string name="common_acceptable_use_policy">"Acceptable use policy"</string>
|
<string name="common_acceptable_use_policy">"Acceptable use policy"</string>
|
||||||
<string name="common_adding_caption">"Adding caption"</string>
|
<string name="common_adding_caption">"Adding caption"</string>
|
||||||
<string name="common_advanced_settings">"Advanced settings"</string>
|
<string name="common_advanced_settings">"Advanced settings"</string>
|
||||||
|
<string name="common_an_image">"an image"</string>
|
||||||
<string name="common_analytics">"Analytics"</string>
|
<string name="common_analytics">"Analytics"</string>
|
||||||
<string name="common_appearance">"Appearance"</string>
|
<string name="common_appearance">"Appearance"</string>
|
||||||
<string name="common_audio">"Audio"</string>
|
<string name="common_audio">"Audio"</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue