Skip to content

Commit

Permalink
fix: Accessibility strings founded issues #WPB-9784 (#3657)
Browse files Browse the repository at this point in the history
  • Loading branch information
borichellow authored Nov 26, 2024
1 parent 9a791bf commit b5ec027
Show file tree
Hide file tree
Showing 23 changed files with 166 additions and 49 deletions.
8 changes: 8 additions & 0 deletions app/src/main/kotlin/com/wire/android/model/UserAvatarData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.wire.android.model

import androidx.compose.runtime.Stable
import com.wire.android.R
import com.wire.android.ui.home.conversationslist.model.Membership
import com.wire.android.util.EMPTY
import com.wire.kalium.logic.data.user.ConnectionState
Expand All @@ -37,6 +38,13 @@ data class UserAvatarData(
return asset == null && nameBasedAvatar != null &&
nameBasedAvatar.initials.isEmpty().not() && membership != Membership.Service
}

fun getAvailabilityStatusDescriptionId(): Int? = when (availabilityStatus) {
UserAvailabilityStatus.NONE -> null
UserAvailabilityStatus.AVAILABLE -> R.string.user_profile_status_available
UserAvailabilityStatus.AWAY -> R.string.user_profile_status_away
UserAvailabilityStatus.BUSY -> R.string.user_profile_status_busy
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ data class CreateAccountOverviewParams(
val contentText: String = "",
@DrawableRes val contentIconResId: Int = 0,
val learnMoreText: String = "",
val learnMoreUrl: String = ""
val learnMoreUrl: String = "",
val isContentTextSemanticAccessible: Boolean = false
)
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ fun CreateTeamAccountOverviewScreen(
contentText = stringResource(id = overviewResources.overviewContentTextResId),
contentIconResId = overviewResources.overviewContentIconResId,
learnMoreText = stringResource(id = overviewResources.overviewLearnMoreTextResId),
learnMoreUrl = viewModel.learnMoreUrl()
learnMoreUrl = viewModel.learnMoreUrl(),
isContentTextSemanticAccessible = true
)
)
}
Expand Down Expand Up @@ -193,7 +194,15 @@ private fun OverviewTexts(
text = overviewParams.contentText,
style = MaterialTheme.wireTypography.body02,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth().clearAndSetSemantics {}
modifier = Modifier
.fillMaxWidth()
.run {
if (overviewParams.isContentTextSemanticAccessible) {
this
} else {
clearAndSetSemantics {}
}
}
)
Text(
text = overviewParams.learnMoreText,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.wire.android.BuildConfig
Expand Down Expand Up @@ -189,13 +191,22 @@ private fun ColumnScope.DeviceItemTexts(
.fillMaxWidth()
.shimmerPlaceholder(visible = placeholder)
) {
val deviceName = device.name.asString()
val shouldAddNotVerifiedLabel = shouldShowVerifyLabel && !shouldShowE2EIInfo && !(device.isVerifiedProteus && !isCurrentClient)
val semantic = if (shouldAddNotVerifiedLabel) {
val notVerifiedLabel = stringResource(R.string.label_client_unverified)
Modifier.clearAndSetSemantics { contentDescription = "$deviceName, $notVerifiedLabel" }
} else {
Modifier
}
Text(
style = MaterialTheme.wireTypography.body02,
color = MaterialTheme.wireColorScheme.onBackground,
text = device.name.asString(),
text = deviceName,
modifier = Modifier
.wrapContentWidth()
.shimmerPlaceholder(visible = placeholder)
.then(semantic)
)
if (shouldShowVerifyLabel) {
if (shouldShowE2EIInfo) {
Expand Down Expand Up @@ -223,6 +234,16 @@ private fun ColumnScope.DeviceItemTexts(

Spacer(modifier = Modifier.height(MaterialTheme.wireDimensions.removeDeviceItemTitleVerticalPadding))

MLSDetails(device, placeholder)

ProteusDetails(device, placeholder)
}

@Composable
private fun MLSDetails(
device: Device,
placeholder: Boolean
) {
device.mlsClientIdentity?.let { identity ->
Text(
style = MaterialTheme.wireTypography.subline01,
Expand All @@ -238,7 +259,13 @@ private fun ColumnScope.DeviceItemTexts(
.shimmerPlaceholder(visible = placeholder)
)
}
}

@Composable
private fun ProteusDetails(
device: Device,
placeholder: Boolean
) {
val proteusDetails: String = if (!device.registrationTime.isNullOrBlank()) {
if (device.lastActiveInWholeWeeks != null) {
stringResource(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -248,12 +251,19 @@ private fun DefaultInitialsAvatar(
type: UserProfileAvatarType,
size: Dp,
modifier: Modifier = Modifier,
contentDescription: String? = null
) {
val contentDescription = stringResource(R.string.content_description_user_avatar)
val semantics = if (contentDescription != null) {
Modifier.semantics {
this.contentDescription = contentDescription
this.role = Role.Image
}
} else {
Modifier.clearAndSetSemantics { }
}
Box(
contentAlignment = Alignment.Center,
modifier = modifier
.semantics { this.contentDescription = contentDescription }
.size(size)
.clip(CircleShape)
.background(
Expand All @@ -266,6 +276,7 @@ private fun DefaultInitialsAvatar(
)
}
)
.then(semantics)
) {
Text(
text = nameBasedAvatar.initials,
Expand Down
21 changes: 15 additions & 6 deletions app/src/main/kotlin/com/wire/android/ui/common/WireDropDown.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.onClick
import androidx.compose.ui.semantics.paneTitle
import androidx.compose.ui.semantics.selected
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -164,6 +165,8 @@ private fun MenuPopUp(
hidePopUp: () -> Unit,
onChange: (selectedIndex: Int) -> Unit
) {
val dropdownDescription = stringResource(R.string.content_description_drop_down)

MaterialTheme(shapes = MaterialTheme.shapes.copy(extraSmall = shape)) {
// we want PopUp to cover the selection field, so we set this offset.
// "- 8.dp" is because DropdownMenu has inner top padding, which can't be changed,
Expand All @@ -178,14 +181,15 @@ private fun MenuPopUp(
.width(with(LocalDensity.current) { textFieldWidth.width.toDp() })
.background(color = MaterialTheme.wireColorScheme.secondaryButtonEnabled)
.border(width = 1.dp, color = borderColor, shape)
.semantics { paneTitle = dropdownDescription }
) {

SelectionField(
Modifier.clickable(onClickLabel = stringResource(R.string.content_description_close_dropdown)) { hidePopUp() },
leadingCompose,
selectedIndex,
selectionText,
arrowRotation
arrowRotation,
Modifier.clickable(onClickLabel = stringResource(R.string.content_description_close_dropdown)) { hidePopUp() }
)

List(items.size) { index ->
Expand All @@ -210,11 +214,11 @@ private fun MenuPopUp(

@Composable
private fun SelectionField(
modifier: Modifier = Modifier,
leadingCompose: @Composable ((index: Int) -> Unit)?,
selectedIndex: Int,
text: String,
arrowRotation: Float
arrowRotation: Float,
modifier: Modifier = Modifier
) {
Row(
modifier
Expand Down Expand Up @@ -262,6 +266,7 @@ private fun DropdownItem(
onClick: () -> Unit
) {
val selectLabel = stringResource(R.string.content_description_select_label)
val closeDropdownLabel = stringResource(R.string.content_description_close_dropdown)
return DropdownMenuItem(
text = {
Text(
Expand All @@ -281,8 +286,12 @@ private fun DropdownItem(
onClick = onClick,
modifier = Modifier
.semantics {
onClick(selectLabel) { false }
if (isSelected) selected = true
if (isSelected) {
selected = true
onClick(closeDropdownLabel) { false }
} else {
onClick(selectLabel) { false }
}
}
.background(
color = if (isSelected) MaterialTheme.wireColorScheme.secondaryButtonSelected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ 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.contentDescription
import androidx.compose.ui.semantics.semantics
import com.wire.android.BuildConfig
import com.wire.android.R
import com.wire.android.model.Clickable
Expand Down Expand Up @@ -124,10 +126,18 @@ fun ConversationParticipantItem(
}
},
subtitle = {
val userName = processUsername(uiParticipant)
// Availability status should be called after username by TalkBack
val subtitleModifier = uiParticipant.avatarData.getAvailabilityStatusDescriptionId()?.let {
val contentDescription = stringResource(it)
Modifier.semantics { this.contentDescription = "$userName, $contentDescription" }
} ?: Modifier

HighlightSubtitle(
subTitle = processUsername(uiParticipant),
subTitle = userName,
searchQuery = searchQuery,
prefix = processUsernamePrefix(uiParticipant)
prefix = processUsernamePrefix(uiParticipant),
modifier = subtitleModifier
)
},
actions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package com.wire.android.ui.home.conversations.search
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextOverflow
Expand All @@ -33,6 +34,7 @@ import com.wire.android.util.QueryMatchExtractor
@Composable
fun HighlightSubtitle(
subTitle: String,
modifier: Modifier = Modifier,
searchQuery: String = String.EMPTY,
prefix: String = "@"
) {
Expand Down Expand Up @@ -76,6 +78,7 @@ fun HighlightSubtitle(
}
}
},
modifier = modifier,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Expand All @@ -85,7 +88,8 @@ fun HighlightSubtitle(
style = MaterialTheme.wireTypography.subline01,
color = MaterialTheme.wireColorScheme.secondaryText,
maxLines = 1,
overflow = TextOverflow.Ellipsis
overflow = TextOverflow.Ellipsis,
modifier = modifier
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,11 @@ fun SearchUsersAndServicesScreen(
SearchPeopleScreenType.CONVERSATION_DETAILS ->
NavigationIconType.Close(R.string.content_description_add_participants_close)

SearchPeopleScreenType.NEW_CONVERSATION -> NavigationIconType.Close()
SearchPeopleScreenType.NEW_GROUP_CONVERSATION -> NavigationIconType.Back()
SearchPeopleScreenType.NEW_CONVERSATION ->
NavigationIconType.Close(R.string.content_description_new_conversation_close_btn)

SearchPeopleScreenType.NEW_GROUP_CONVERSATION ->
NavigationIconType.Back(R.string.content_description_new_group_conversation_back_btn)
},
onNavigationPressed = onClose
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import com.wire.android.R
import com.wire.android.model.Clickable
import com.wire.android.model.UserAvatarData
Expand Down Expand Up @@ -75,16 +76,24 @@ fun ConversationItemFactory(
) {
val openConversationOptionDescription = stringResource(R.string.content_description_conversation_details_more_btn)
val openUserProfileDescription = stringResource(R.string.content_description_open_user_profile_label)
val acceptOrIgnoreDescription = stringResource(R.string.content_description_accept_or_ignore_connection_label)
val openConversationDescription = stringResource(R.string.content_description_open_conversation_label)
val onConversationItemClick = remember(conversation) {
when (val lastEvent = conversation.lastMessageContent) {
is UILastMessageContent.Connection -> Clickable(
enabled = true,
onClick = { openUserProfile(lastEvent.userId) },
onLongClick = null,
onClickDescription = openUserProfileDescription,
onLongClickDescription = null
)
is UILastMessageContent.Connection -> {
val onClickDescription = if (conversation.badgeEventType == BadgeEventType.ReceivedConnectionRequest) {
acceptOrIgnoreDescription
} else {
openUserProfileDescription
}
Clickable(
enabled = true,
onClick = { openUserProfile(lastEvent.userId) },
onLongClick = null,
onClickDescription = onClickDescription,
onLongClickDescription = null
)
}

else -> Clickable(
enabled = true,
Expand All @@ -97,7 +106,7 @@ fun ConversationItemFactory(
}

GeneralConversationItem(
modifier = modifier,
modifier = modifier.semantics(mergeDescendants = true) { },
conversation = conversation,
isSelectable = isSelectableItem,
isChecked = isChecked,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ fun MessageEditActions(
WireTertiaryIconButton(
onButtonClicked = onEditCancelButtonClicked,
iconResource = R.drawable.ic_close,
contentDescription = R.string.content_description_close_button,
contentDescription = R.string.label_close,
shape = CircleShape,
minSize = MaterialTheme.wireDimensions.buttonCircleMinSize,
minClickableSize = MaterialTheme.wireDimensions.buttonMinClickableSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fun RecordAudioButtonClose(
WireTertiaryIconButton(
onButtonClicked = onClick,
iconResource = R.drawable.ic_close,
contentDescription = R.string.content_description_close_button,
contentDescription = R.string.label_close,
shape = CircleShape,
minSize = MaterialTheme.wireDimensions.buttonCircleMinSize,
minClickableSize = MaterialTheme.wireDimensions.buttonMinClickableSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ fun LogoutOptionsDialog(
dismissButtonProperties = WireDialogButtonProperties(
onClick = dialogState::dismiss,
text = stringResource(id = R.string.label_cancel),
state = WireButtonState.Default
state = WireButtonState.Default,
description = stringResource(R.string.dialog_logout_wipe_data_cancel_description)
),
optionButton1Properties = WireDialogButtonProperties(
onClick = remember(state) { { logout(state.shouldWipeData).also { dialogState.dismiss() } } },
Expand Down
Loading

0 comments on commit b5ec027

Please sign in to comment.