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

feat: Add accessibility string to OtherUserProfile and search participants [WPB-9784] #3531

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
133d629
feat: Add accessibility strings to conversation deatils screen
borichellow Oct 10, 2024
5a6043a
Merge branch 'develop' into feat/add_accessibility_string_to_conversa…
borichellow Oct 10, 2024
05007ba
Fixed code-style
borichellow Oct 10, 2024
336bc0a
Fixed code-style one more
borichellow Oct 10, 2024
3460ba7
Merge branch 'develop' into feat/add_accessibility_string_to_conversa…
borichellow Oct 10, 2024
f4eadad
Fixed code-style again
borichellow Oct 10, 2024
787bc01
Fixed, but not everything yet
borichellow Oct 11, 2024
271ebb6
Merge branch 'develop' into feat/add_accessibility_string_to_conversa…
borichellow Oct 11, 2024
8a142c5
Ready for review
borichellow Oct 15, 2024
b5853c5
Merge branch 'develop' into feat/add_accessibility_string_to_conversa…
borichellow Oct 15, 2024
9e2d180
Code style fix
borichellow Oct 15, 2024
abd929c
Lint fixes
borichellow Oct 16, 2024
44b7000
Merge branch 'develop' into feat/add_accessibility_string_to_conversa…
borichellow Oct 16, 2024
9fb946e
Reverted useles changes
borichellow Oct 16, 2024
907ec52
Fixed lint again
borichellow Oct 16, 2024
22bae6f
Fixed lint again again
borichellow Oct 16, 2024
fa22524
Merge branch 'develop' into feat/add_accessibility_string_to_conversa…
borichellow Oct 16, 2024
818e59a
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 16, 2024
b977904
feat: Add Accessability strings to OtherUserProfile
borichellow Oct 17, 2024
80d2c74
feat: Add Accessability strings to OtherUserProfile: ready for review
borichellow Oct 21, 2024
39e90cb
Merge release/candidate into feat/add_accessibility_string_to_other_u…
borichellow Oct 22, 2024
a09199a
Fixed code style
borichellow Oct 22, 2024
ea30df6
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 22, 2024
6e84021
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 22, 2024
28964fe
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 23, 2024
1788706
Added comments to code
borichellow Oct 23, 2024
dd547c9
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 23, 2024
e5f320b
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 24, 2024
2ed3c12
Review fixes
borichellow Oct 24, 2024
f53335e
Merge branch 'release/candidate' into feat/add_accessibility_string_t…
borichellow Oct 24, 2024
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
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.onClick
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.wire.android.BuildConfig
Expand Down Expand Up @@ -101,6 +103,8 @@ private fun DeviceItemContent(
shouldShowE2EIInfo: Boolean,
modifier: Modifier = Modifier,
) {
val openDetailsDescription = stringResource(id = R.string.content_description_user_profile_open_device_btn)

Row(
verticalAlignment = Alignment.Top,
modifier = modifier
Expand All @@ -109,6 +113,9 @@ private fun DeviceItemContent(
onClickAction?.invoke(device)
}
}
.semantics {
if (isWholeItemClickable) onClick(openDetailsDescription) { false }
}
) {
Row(
modifier = Modifier
Expand All @@ -118,7 +125,7 @@ private fun DeviceItemContent(
Icon(
modifier = Modifier.shimmerPlaceholder(visible = placeholder),
imageVector = ImageVector.vectorResource(id = R.drawable.ic_devices),
contentDescription = stringResource(R.string.content_description_remove_devices_screen_device_item_icon)
contentDescription = null
)
Column(
horizontalAlignment = Alignment.Start,
Expand Down Expand Up @@ -199,7 +206,8 @@ private fun ColumnScope.DeviceItemTexts(
ProteusVerifiedIcon(
Modifier
.wrapContentWidth()
.align(Alignment.CenterVertically))
.align(Alignment.CenterVertically)
)
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.wire.android.ui.common

import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.wire.android.R
Expand All @@ -27,13 +28,14 @@ import com.wire.android.ui.common.button.WireSecondaryIconButton
@Composable
fun CopyButton(
onCopyClicked: () -> Unit,
state: WireButtonState = WireButtonState.Default,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
@StringRes contentDescription: Int = R.string.content_description_copy,
state: WireButtonState = WireButtonState.Default
) {
WireSecondaryIconButton(
onButtonClicked = onCopyClicked,
iconResource = R.drawable.ic_copy,
contentDescription = R.string.content_description_copy,
contentDescription = contentDescription,
state = state,
modifier = modifier
)
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ fun SearchBarInput(
placeholderAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
textStyle: TextStyle = LocalTextStyle.current,
isLoading: Boolean = false
isLoading: Boolean = false,
semanticDescription: String? = null
) {

WireTextField(
Expand Down Expand Up @@ -108,6 +109,7 @@ fun SearchBarInput(
placeholderAlignment = placeholderAlignment,
placeholderText = placeholderText,
lineLimits = TextFieldLineLimits.SingleLine,
semanticDescription = semanticDescription
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ internal fun WireTextField(
labelText: String? = null,
labelMandatoryIcon: Boolean = false,
descriptionText: String? = null,
semanticDescription: String? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
state: WireTextFieldState = WireTextFieldState.Default,
Expand Down Expand Up @@ -115,6 +116,7 @@ internal fun WireTextField(
labelText = labelText,
labelMandatoryIcon = labelMandatoryIcon,
descriptionText = descriptionText,
semanticDescription = semanticDescription,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
state = state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.TextStyle
Expand All @@ -55,6 +56,12 @@ import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.EMPTY
import io.github.esentsov.PackagePrivate

/**
* Priority in which fields are used for SemanticContentDescription:
* [semanticDescription] -> [labelText] -> [placeholderText] -> [descriptionText].
* If you need to make empty SemanticContentDescription (which is definitely bad idea for TextView)
* set [semanticDescription] = ""
*/
@PackagePrivate
@Composable
internal fun WireTextFieldLayout(
Expand All @@ -65,6 +72,7 @@ internal fun WireTextFieldLayout(
labelText: String? = null,
labelMandatoryIcon: Boolean = false,
descriptionText: String? = null,
semanticDescription: String? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
state: WireTextFieldState = WireTextFieldState.Default,
Expand Down Expand Up @@ -101,8 +109,8 @@ internal fun WireTextFieldLayout(
.fillMaxWidth()
.background(color = colors.backgroundColor(state).value, shape = shape)
.border(width = dimensions().spacing1x, color = colors.borderColor(state, interactionSource).value, shape = shape)
.semantics {
(labelText ?: placeholderText ?: descriptionText)?.let {
.semantics(mergeDescendants = true) {
(semanticDescription ?: labelText ?: placeholderText ?: descriptionText)?.let {
MohamadJaara marked this conversation as resolved.
Show resolved Hide resolved
contentDescription = it
}
}
Expand Down Expand Up @@ -178,7 +186,9 @@ private fun InnerTextLayout(
text = placeholderText,
style = placeholderTextStyle,
color = colors.placeholderColor(style).value,
modifier = Modifier.align(placeholderAlignment.toAlignment())
modifier = Modifier
.align(placeholderAlignment.toAlignment())
.clearAndSetSemantics {}
)
}
Box(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fun SearchTopBar(
searchQueryTextState: TextFieldState,
modifier: Modifier = Modifier,
isLoading: Boolean = false,
searchBarDescription: String? = null,
onCloseSearchClicked: (() -> Unit)? = null,
onActiveChanged: (isActive: Boolean) -> Unit = {},
bottomContent: @Composable ColumnScope.() -> Unit = {}
Expand Down Expand Up @@ -107,6 +108,7 @@ fun SearchTopBar(

SearchBarInput(
placeholderText = searchBarHint,
semanticDescription = searchBarDescription,
textState = searchQueryTextState,
isLoading = isLoading,
leadingIcon = {
Expand All @@ -118,7 +120,7 @@ fun SearchTopBar(
) {
Icon(
painter = painterResource(R.drawable.ic_search),
contentDescription = stringResource(R.string.content_description_conversation_search_icon),
contentDescription = null,
tint = MaterialTheme.wireColorScheme.onBackground,
)
}
Expand All @@ -129,7 +131,7 @@ fun SearchTopBar(
) {
Icon(
painter = rememberVectorPainter(image = Icons.Filled.ArrowBack),
contentDescription = stringResource(R.string.content_description_back_button),
contentDescription = stringResource(id = R.string.content_description_add_participants_back_btn),
tint = MaterialTheme.wireColorScheme.onBackground,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ fun ConversationMediaButton(
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_gallery),
contentDescription = stringResource(R.string.label_conversation_media),
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(end = dimensions().spacing8x)
)
}
},
onClickDescription = stringResource(id = R.string.content_description_see_media_in_conversation_btn)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import com.wire.android.R
import com.wire.android.appLogger
import com.wire.android.model.Clickable
import com.wire.android.model.ItemActionType
Expand Down Expand Up @@ -53,16 +57,15 @@ fun InternalContactSearchResultItem(
membership: Membership,
searchQuery: String,
connectionState: ConnectionState,
onCheckChange: (Boolean) -> Unit,
onCheckClickable: Clickable,
isSelected: Boolean,
clickable: Clickable,
actionType: ItemActionType,
modifier: Modifier = Modifier
) {
val selectedDescription = stringResource(id = R.string.content_description_selected_label)
RowItemTemplate(
leadingIcon = {
UserProfileAvatar(avatarData)
},
leadingIcon = { UserProfileAvatar(avatarData) },
titleStartPadding = dimensions().spacing0x,
title = {
Row(verticalAlignment = CenterVertically) {
Expand Down Expand Up @@ -101,14 +104,16 @@ fun InternalContactSearchResultItem(
}
},
clickable =
if (actionType.clickable) {
clickable
} else {
Clickable {
onCheckChange(!isSelected)
}
},
modifier = modifier.padding(start = dimensions().spacing8x)
if (actionType.clickable) {
clickable
} else {
onCheckClickable
},
modifier = modifier
.padding(start = dimensions().spacing8x)
.semantics {
if (actionType.checkable && isSelected) stateDescription = selectedDescription
}
)
}

Expand Down Expand Up @@ -155,15 +160,20 @@ fun ExternalContactSearchResultItem(
when (connectionState) {
ConnectionState.NOT_CONNECTED, ConnectionState.CANCELLED ->
AddContactButton(userId, name)

ConnectionState.PENDING, ConnectionState.IGNORED ->
Box(modifier = Modifier.padding(horizontal = dimensions().spacing12x)) { ConnectRequestBadge() }

ConnectionState.SENT ->
Box(modifier = Modifier.padding(horizontal = dimensions().spacing12x)) { ConnectPendingRequestBadge() }

ConnectionState.BLOCKED -> {
}

ConnectionState.MISSING_LEGALHOLD_CONSENT -> {
appLogger.e("Unhandled ConnectionState.MISSING_LEGALHOLD_CONSENT in ExternalContactSearchResultItem")
}

ConnectionState.ACCEPTED -> {
appLogger.e("ConnectionState.ACCEPTED should not appear in ExternalContactSearchResultItem")
}
Expand All @@ -184,12 +194,13 @@ fun PreviewInternalContactSearchResultItemCheckable() = WireTheme {
membership = Membership.None,
searchQuery = "",
connectionState = ConnectionState.ACCEPTED,
onCheckChange = {},
onCheckClickable = Clickable {},
isSelected = false,
clickable = Clickable {},
actionType = ItemActionType.CHECK,
)
}

@PreviewMultipleThemes
@Composable
fun PreviewInternalContactSearchResultItemClickable() = WireTheme {
Expand All @@ -200,7 +211,7 @@ fun PreviewInternalContactSearchResultItemClickable() = WireTheme {
membership = Membership.None,
searchQuery = "",
connectionState = ConnectionState.ACCEPTED,
onCheckChange = {},
onCheckClickable = Clickable {},
isSelected = false,
clickable = Clickable {},
actionType = ItemActionType.CLICK,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ import com.wire.android.ui.home.newconversation.model.Contact
import com.wire.android.ui.theme.WireTheme
import com.wire.android.util.extension.FolderType
import com.wire.android.util.extension.folderWithElements
import com.wire.android.util.ui.keepOnTopWhenNotScrolled
import com.wire.android.util.ui.PreviewMultipleThemes
import com.wire.android.util.ui.keepOnTopWhenNotScrolled
import com.wire.kalium.logic.data.user.ConnectionState
import com.wire.kalium.logic.data.user.UserId
import kotlinx.collections.immutable.ImmutableList
Expand Down Expand Up @@ -287,7 +287,13 @@ private fun LazyListScope.internalSuccessItem(
folderType = FolderType.Collapsing(expanded = expanded, onChanged = onExpansionChanged),
) { (contact, isSelected) ->
with(contact) {
val onClick = remember { { isChecked: Boolean -> onChecked(isChecked, this) } }
val onCheckDescription = stringResource(
id = if (isSelected) R.string.content_description_unselect_label else R.string.content_description_select_label
)
val clickDescription = stringResource(id = R.string.content_description_open_user_profile_label)
val onCheckClickable = remember(isSelected) {
Clickable(onClickDescription = onCheckDescription) { onChecked(!isSelected, this) }
}
InternalContactSearchResultItem(
avatarData = avatarData,
name = name,
Expand All @@ -296,9 +302,9 @@ private fun LazyListScope.internalSuccessItem(
searchQuery = searchQuery,
connectionState = connectionState,
isSelected = isSelected,
onCheckChange = onClick,
onCheckClickable = onCheckClickable,
actionType = actionType,
clickable = remember { Clickable(enabled = true) { onOpenUserProfile(contact) } }
clickable = remember { Clickable(onClickDescription = clickDescription) { onOpenUserProfile(contact) } }
)
}
}
Expand Down Expand Up @@ -344,6 +350,7 @@ private fun LazyListScope.externalSuccessItem(
folderType = FolderType.Collapsing(expanded = expanded, onChanged = onExpansionChanged),
) { contact ->
with(contact) {
val clickDescription = stringResource(id = R.string.content_description_open_user_profile_label)
ExternalContactSearchResultItem(
avatarData = avatarData,
userId = UserId(id, domain),
Expand All @@ -352,7 +359,7 @@ private fun LazyListScope.externalSuccessItem(
membership = membership,
connectionState = connectionState,
searchQuery = searchQuery,
clickable = remember { Clickable(enabled = true) { onOpenUserProfile(contact) } }
clickable = remember { Clickable(onClickDescription = clickDescription) { onOpenUserProfile(contact) } }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel
import com.wire.android.R
import com.wire.android.model.Clickable
Expand Down Expand Up @@ -110,6 +111,7 @@ private fun SuccessServicesList(
folderWithElements(
items = services.associateBy { it.id }
) {
val clickDescription = stringResource(id = R.string.content_description_open_service_label)
RowItemTemplate(
leadingIcon = {
Row {
Expand All @@ -132,7 +134,7 @@ private fun SuccessServicesList(
}
},
actions = {},
clickable = remember(it) { Clickable(enabled = true) { onServiceClicked(it) } },
clickable = remember(it) { Clickable(onClickDescription = clickDescription) { onServiceClicked(it) } },
modifier = Modifier.padding(start = dimensions().spacing8x)
)
}
Expand Down
Loading
Loading