From 803a5292ba389ecc7bd533131ff2241695ea566d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 9 Jul 2025 17:03:50 +0200 Subject: [PATCH] [a11y] Improve accessibility of picto next to the timestamp. https://github.com/element-hq/customer-success/issues/572 --- .../components/TimelineEventTimestampView.kt | 29 ++++++++++--------- .../timeline/components/TimelineItemRow.kt | 5 +++- .../src/main/res/values/localazy.xml | 1 + 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index 644cbf2310..d8af3c1736 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -18,8 +18,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.hideFromAccessibility -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -44,15 +42,15 @@ fun TimelineEventTimestampView( modifier: Modifier = Modifier, ) { val formattedTime = event.sentTime - val hasError = event.localSendState is LocalEventSendState.Failed + val hasError = event.failedToSend val hasEncryptionCritical = event.messageShield?.isCritical.orFalse() val isMessageEdited = event.content.isEdited() val isMessageRedacted = event.content.isRedacted() val tint = if (hasError || hasEncryptionCritical && !isMessageRedacted) ElementTheme.colors.textCriticalPrimary else ElementTheme.colors.textSecondary Row( modifier = Modifier - .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) - .then(modifier), + .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) + .then(modifier), verticalAlignment = Alignment.CenterVertically, ) { if (isMessageEdited) { @@ -76,11 +74,13 @@ fun TimelineEventTimestampView( contentDescription = stringResource(id = CommonStrings.common_sending_failed), tint = tint, modifier = Modifier - .size(15.dp, 18.dp) - .clickable(isVerifiedUserSendFailure) { - eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event)) - } - .semantics { hideFromAccessibility() } + .size(15.dp, 18.dp) + .clickable( + enabled = isVerifiedUserSendFailure, + onClickLabel = stringResource(CommonStrings.action_open_context_menu), + ) { + eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event)) + } ) } @@ -89,13 +89,14 @@ fun TimelineEventTimestampView( Spacer(modifier = Modifier.width(2.dp)) Icon( imageVector = shield.toIcon(), - contentDescription = shield.toText(), + contentDescription = stringResource(id = CommonStrings.a11y_encryption_details), modifier = Modifier .size(15.dp) - .clickable { + .clickable( + onClickLabel = stringResource(CommonStrings.a11y_view_details), + ) { eventSink(TimelineEvents.ShowShieldDialog(shield)) - } - .semantics { hideFromAccessibility() }, + }, tint = shield.toIconColor(), ) Spacer(modifier = Modifier.width(4.dp)) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 9628fb2bb4..59ec63d842 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -140,7 +140,10 @@ internal fun TimelineItemRow( timelineItem.safeSenderName } // For Polls, allow the answers to be traversed by Talkback - isTraversalGroup = timelineItem.content is TimelineItemPollContent + isTraversalGroup = timelineItem.content is TimelineItemPollContent || + timelineItem.failedToSend || + timelineItem.messageShield != null + // TODO Also set to true when the event has link(s) } // Custom clickable that applies over the whole item for accessibility .then( diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 826dd2fe55..362b2310d4 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -8,6 +8,7 @@ "%1$d digits entered" "Edit avatar" + "Encryption details" "Hide password" "Join call" "Jump to bottom"