Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Accessibility strings founded issues #WPB-9784 🍒 #3667

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
17 changes: 12 additions & 5 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 @@ -168,6 +169,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 @@ -182,16 +185,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(
leadingCompose = leadingCompose,
selectedIndex = selectedIndex,
text = selectionText,
arrowRotation = arrowRotation,
modifier = Modifier.clickable(onClickLabel = stringResource(R.string.content_description_close_dropdown)) {
hidePopUp()
},
modifier = Modifier.clickable(onClickLabel = stringResource(R.string.content_description_close_dropdown)) { hidePopUp() }
)

List(items.size) { index ->
Expand Down Expand Up @@ -268,6 +270,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 @@ -287,8 +290,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 @@ -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 @@ -291,12 +294,19 @@ private fun DefaultInitialsAvatar(
type: UserProfileAvatarType,
size: Dp,
modifier: Modifier = Modifier,
contentDescription: String? = stringResource(R.string.content_description_user_avatar),
contentDescription: String? = null,
) {
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 @@ -312,6 +322,7 @@ private fun DefaultInitialsAvatar(
)
}
)
.then(semantics)
) {
Text(
text = nameBasedAvatar.initials,
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 @@ -78,6 +78,7 @@ fun HighlightSubtitle(
}
}
},
modifier = modifier,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = modifier
Expand Down
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 @@ -54,7 +54,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
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,18 @@
<string name="content_description_toggle_setting_label">toggle setting</string>
<string name="content_description_edit_guests_option_back_btn">Go back to conversation details</string>
<string name="content_description_edit_self_delete_back_btn">Go back to conversation details</string>
<string name="content_description_accept_or_ignore_connection_label">accept or ignore the request</string>
<string name="content_description_open_user_profile_label">open profile</string>
<string name="content_description_open_conversation_label">open conversation</string>
<string name="content_description_open_service_label">open service</string>
<string name="content_description_change_it_label">change it</string>
<string name="content_description_open_link_label">open link</string>
<string name="content_description_alert">Alert</string>
<string name="content_description_drop_down">Dropdown</string>
<string name="content_description_close_dropdown">close dropdown</string>
<string name="content_description_open_notification_settings_label">open notification settings</string>
<string name="content_description_new_conversation_close_btn">Close new conversation view</string>
<string name="content_description_new_group_conversation_back_btn">Go back to new conversation view</string>
<string name="content_description_new_conversation_name_back_btn">Go back to new conversation view</string>
<string name="content_description_new_conversation_name_field">Type group name</string>
<string name="content_description_new_conversation_options_heading">Conversation options</string>
Expand Down Expand Up @@ -624,6 +628,7 @@
<!-- Logout Wipe Data Dialog -->
<string name="dialog_logout_wipe_data_title">Clear Data?</string>
<string name="dialog_logout_wipe_data_checkbox">Delete all your personal information and conversations on this device</string>
<string name="dialog_logout_wipe_data_cancel_description">Cancel logout</string>
<!-- User Profile status dialog-->
<string name="user_profile_change_status_dialog_available_title">Set yourself to Available</string>
<string name="user_profile_change_status_dialog_available_text">You will appear as Available to other people. You will receive notifications for incoming calls and for messages according to the Notifications setting in each conversation.</string>
Expand Down
Loading
Loading