From 133d629f52b676025ab653bdb9b57dd048892953 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Thu, 10 Oct 2024 12:18:14 +0300 Subject: [PATCH 01/16] feat: Add accessibility strings to conversation deatils screen --- .../devices/register/RegisterDeviceScreen.kt | 2 +- .../devices/remove/RemoveDeviceTopBar.kt | 2 +- .../ui/authentication/login/LoginScreen.kt | 1 + .../authentication/welcome/WelcomeScreen.kt | 2 +- .../wire/android/ui/common/MoreOptionIcon.kt | 4 +- .../com/wire/android/ui/common/WireSwitch.kt | 17 +++- .../com/wire/android/ui/common/WireTabRow.kt | 7 ++ .../bottomsheet/RichMenuBottomSheetItem.kt | 6 +- .../conversation/HomeSheetContent.kt | 7 +- .../conversation/MutingOptionsSheetContent.kt | 3 + .../com/wire/android/ui/debug/DebugScreen.kt | 2 +- .../ui/e2eiEnrollment/E2EIEnrollmentScreen.kt | 2 +- .../ui/home/appLock/set/SetLockCodeScreen.kt | 2 +- .../conversations/ConversationTopAppBar.kt | 2 +- .../details/GroupConversationDetailsScreen.kt | 28 +++++-- .../editguestaccess/EditGuestAccessScreen.kt | 11 ++- .../details/editguestaccess/GuestOption.kt | 4 +- .../EditSelfDeletingMessagesScreen.kt | 15 +++- .../SelfDeletingMessageOption.kt | 4 +- .../options/GroupConversationOptions.kt | 77 +++++++++++++++++-- .../options/GroupConversationOptionsItem.kt | 4 + .../ConversationParticipantItem.kt | 21 ++++- .../GroupConversationAllParticipantsScreen.kt | 2 +- .../GroupConversationParticipantList.kt | 25 ++++-- .../media/ConversationMediaScreen.kt | 3 +- .../media/preview/ImagesPreviewScreen.kt | 2 +- .../messagedetails/MessageDetailsScreen.kt | 4 +- .../search/SearchUsersAndServicesScreen.kt | 7 +- .../gallery/MediaGalleryScreenTopAppBar.kt | 2 +- .../ui/home/settings/SettingsOptionSwitch.kt | 4 +- .../ui/settings/about/AboutThisAppScreen.kt | 2 +- .../e2ei/E2eiCertificateDetailsScreen.kt | 2 +- .../android/ui/sharing/ImportMediaScreen.kt | 8 +- .../other/OtherUserProfileScreen.kt | 11 +-- .../userprofile/self/SelfUserProfileScreen.kt | 2 +- .../android/util/extension/LazyListScope.kt | 7 ++ app/src/main/res/values/strings.xml | 33 ++++++++ .../common/bottomsheet/MenuBottomSheetItem.kt | 4 + .../bottomsheet/ModalSheetHeaderItem.kt | 5 +- .../android/ui/common/button/WireButton.kt | 11 ++- .../ui/common/button/WirePrimaryButton.kt | 5 +- .../ui/common/button/WireSecondaryButton.kt | 3 + .../common/topappbar/NavigationIconButton.kt | 20 +++-- .../topappbar/WireCenterAlignedTopAppBar.kt | 16 +++- .../feature/sketch/DrawingCanvasScreen.kt | 2 +- 45 files changed, 329 insertions(+), 74 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/register/RegisterDeviceScreen.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/register/RegisterDeviceScreen.kt index c5d649590fa..16cd474d994 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/register/RegisterDeviceScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/register/RegisterDeviceScreen.kt @@ -146,7 +146,7 @@ private fun RegisterDeviceContent( WireCenterAlignedTopAppBar( elevation = dimensions().spacing0x, title = stringResource(id = R.string.register_device_title), - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onNavigationPressed = onBackButtonClicked ) }, diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/remove/RemoveDeviceTopBar.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/remove/RemoveDeviceTopBar.kt index 5c9a08a7d2f..5456ef8c224 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/remove/RemoveDeviceTopBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/remove/RemoveDeviceTopBar.kt @@ -39,7 +39,7 @@ fun RemoveDeviceTopBar(elevation: Dp, onBackButtonClicked: () -> Unit) { WireCenterAlignedTopAppBar( elevation = elevation, title = stringResource(R.string.remove_device_title), - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onNavigationPressed = onBackButtonClicked ) { Text( diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt index 791a58e8727..8685794ff99 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt @@ -344,6 +344,7 @@ enum class LoginTabItem(@StringRes val titleResId: Int) : TabItem { EMAIL(R.string.login_tab_email), SSO(R.string.login_tab_sso); override val title: UIText = UIText.StringResource(titleResId) + override val contentDescription: UIText? = null // TODO set contentDescription if needed } @PreviewMultipleThemes diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/welcome/WelcomeScreen.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/welcome/WelcomeScreen.kt index 304b9d06c9b..05b8b90b963 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/welcome/WelcomeScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/welcome/WelcomeScreen.kt @@ -135,7 +135,7 @@ private fun WelcomeContent( WireCenterAlignedTopAppBar( elevation = dimensions().spacing0x, title = "", - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onNavigationPressed = navigateBack ) } else { diff --git a/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt b/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt index 0717b3ddcbf..f925bdeff07 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt @@ -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 @@ -28,12 +29,13 @@ import com.wire.android.ui.common.button.WireSecondaryIconButton fun MoreOptionIcon( onButtonClicked: () -> Unit, state: WireButtonState = WireButtonState.Default, + @StringRes contentDescription: Int = R.string.content_description_show_more_options, modifier: Modifier = Modifier ) { WireSecondaryIconButton( onButtonClicked = onButtonClicked, iconResource = R.drawable.ic_more, - contentDescription = R.string.content_description_show_more_options, + contentDescription = contentDescription, state = state, modifier = modifier ) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt index 06d394b3ead..63dd0528b9e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt @@ -29,6 +29,8 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.wire.android.ui.theme.wireColorScheme @@ -43,9 +45,20 @@ fun WireSwitch( thumbContent: @Composable () -> Unit = { }, enabled: Boolean = true, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - colors: SwitchColors = wireSwitchColors() + colors: SwitchColors = wireSwitchColors(), + contentDescription: String? = null ) { - Switch(checked, onCheckedChange, modifier, thumbContent, enabled, colors, interactionSource) + Switch( + checked, + onCheckedChange, + modifier.semantics { + if (enabled) contentDescription?.let { this.contentDescription = contentDescription } + }, + thumbContent, + enabled, + colors, + interactionSource + ) } @Composable diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt index f64ca4a9203..a21d2f7d7f5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt @@ -35,6 +35,8 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireTypography @@ -70,8 +72,12 @@ fun WireTabRow( val text = tabItem.title.asString().let { if (upperCaseTitles) it.uppercase() else it } + val contentDescription = tabItem.contentDescription?.asString() Tab( + modifier = Modifier.semantics { + contentDescription?.let { this.contentDescription = contentDescription } + }, enabled = true, text = { Text( @@ -108,4 +114,5 @@ fun PagerState.calculateCurrentTab() = // change the tab if we go over half the interface TabItem { val title: UIText + val contentDescription: UIText? } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt index d817bd43f51..23871816f5b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt @@ -34,6 +34,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import com.wire.android.model.Clickable import com.wire.android.ui.common.WireCheckIcon @@ -53,7 +55,8 @@ fun SelectableMenuBottomSheetItem( subLine: String? = null, icon: @Composable () -> Unit = { }, onItemClick: Clickable = Clickable(enabled = false) {}, - state: RichMenuItemState = RichMenuItemState.DEFAULT + state: RichMenuItemState = RichMenuItemState.DEFAULT, + contentDescription: String? = null ) { Row( verticalAlignment = Alignment.CenterVertically, @@ -63,6 +66,7 @@ fun SelectableMenuBottomSheetItem( .defaultMinSize(minHeight = dimensions().spacing48x) .let { if (isSelectedItem(state)) it.background(MaterialTheme.wireColorScheme.secondaryButtonSelected) else it } .clickable(onItemClick) + .semantics { this.contentDescription = contentDescription ?: title } .padding(vertical = dimensions().spacing12x, horizontal = dimensions().spacing16x) ) { icon() diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt index 05f6bb05776..88a9c7fee1a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt @@ -94,6 +94,10 @@ internal fun ConversationMainSheetContent( menuItems = buildList<@Composable () -> Unit> { if (conversationSheetContent.canEditNotifications() && !conversationSheetContent.isArchived) { add { + val contentDescription = stringResource( + id = R.string.content_description_conversation_menu_notification_setting, + conversationSheetContent.mutingConversationState.getMutedStatusTextResource() + ) MenuBottomSheetItem( title = stringResource(R.string.label_notifications), icon = { @@ -103,7 +107,8 @@ internal fun ConversationMainSheetContent( ) }, action = { NotificationsOptionsItemAction(conversationSheetContent.mutingConversationState) }, - onItemClick = navigateToNotification + onItemClick = navigateToNotification, + contentDescription = contentDescription ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt index 6c07ffead89..ab991f46a1d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt @@ -52,6 +52,7 @@ internal fun MutingOptionsSheetContent( title = stringResource(id = R.string.muting_option_all_allowed_title), subLine = stringResource(id = R.string.muting_option_all_allowed_text), onItemClick = Clickable { onMuteConversation(MutedConversationStatus.AllAllowed) }, + contentDescription = stringResource(id = R.string.content_description_muting_menu_everything), state = if (mutingConversationState == MutedConversationStatus.AllAllowed) RichMenuItemState.SELECTED else RichMenuItemState.DEFAULT ) @@ -61,6 +62,7 @@ internal fun MutingOptionsSheetContent( title = stringResource(id = R.string.muting_option_only_mentions_title), subLine = stringResource(id = R.string.muting_option_only_mentions_text), onItemClick = Clickable { onMuteConversation(MutedConversationStatus.OnlyMentionsAndRepliesAllowed) }, + contentDescription = stringResource(id = R.string.content_description_muting_menu_calls), state = if (mutingConversationState == MutedConversationStatus.OnlyMentionsAndRepliesAllowed) RichMenuItemState.SELECTED else RichMenuItemState.DEFAULT ) @@ -70,6 +72,7 @@ internal fun MutingOptionsSheetContent( title = stringResource(id = R.string.muting_option_all_muted_title), subLine = stringResource(id = R.string.muting_option_all_muted_text), onItemClick = Clickable { onMuteConversation(MutedConversationStatus.AllMuted) }, + contentDescription = stringResource(id = R.string.content_description_muting_menu_nothing), state = if (mutingConversationState == MutedConversationStatus.AllMuted) RichMenuItemState.SELECTED else RichMenuItemState.DEFAULT ) diff --git a/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt b/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt index 5fa57d82b8a..d33c57e431f 100644 --- a/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/debug/DebugScreen.kt @@ -84,7 +84,7 @@ internal fun UserDebugContent( WireCenterAlignedTopAppBar( title = stringResource(R.string.label_debug_title), elevation = dimensions().spacing0x, - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), onNavigationPressed = onNavigationPressed ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/e2eiEnrollment/E2EIEnrollmentScreen.kt b/app/src/main/kotlin/com/wire/android/ui/e2eiEnrollment/E2EIEnrollmentScreen.kt index 09235816b2e..d00c112ab4a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/e2eiEnrollment/E2EIEnrollmentScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/e2eiEnrollment/E2EIEnrollmentScreen.kt @@ -138,7 +138,7 @@ private fun E2EIEnrollmentScreenContent( WireCenterAlignedTopAppBar( elevation = dimensions().spacing0x, title = stringResource(id = R.string.end_to_end_identity_required_dialog_title), - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onNavigationPressed = onBackButtonClicked ) }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/appLock/set/SetLockCodeScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/appLock/set/SetLockCodeScreen.kt index f67a808ea67..95dfdd4f7c3 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/appLock/set/SetLockCodeScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/appLock/set/SetLockCodeScreen.kt @@ -115,7 +115,7 @@ fun SetLockCodeScreenContent( topBar = { WireCenterAlignedTopAppBar( onNavigationPressed = onBackPress, - navigationIconType = if (state.isEditable) NavigationIconType.Back else null, + navigationIconType = if (state.isEditable) NavigationIconType.Back() else null, elevation = dimensions().spacing0x, title = stringResource(id = R.string.settings_set_lock_screen_title) ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/ConversationTopAppBar.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/ConversationTopAppBar.kt index f6d92a9ce44..dc6c011668d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/ConversationTopAppBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/ConversationTopAppBar.kt @@ -154,7 +154,7 @@ private fun ConversationScreenTopAppBarContent( } }, navigationIcon = { - NavigationIconButton(NavigationIconType.Back, onBackButtonClick) + NavigationIconButton(NavigationIconType.Back(), onBackButtonClick) }, actions = { Row( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt index ef8a870b355..2640f2e559d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt @@ -332,13 +332,19 @@ private fun GroupConversationDetailsContent( WireTopAppBarTitle( title = stringResource(R.string.conversation_details_title), style = MaterialTheme.wireTypography.title01, - maxLines = 2 + maxLines = 2, + contentDescription = stringResource(id = R.string.content_description_conversation_details_header) ) VerificationInfo(conversationSheetContent) }, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(R.string.content_description_conversation_details_close_btn), onNavigationPressed = onBackPressed, - actions = { MoreOptionIcon(onButtonClicked = sheetState::show) } + actions = { + MoreOptionIcon( + contentDescription = R.string.content_description_conversation_details_more_btn, + onButtonClicked = sheetState::show + ) + } ) }, topBarCollapsing = { @@ -558,11 +564,21 @@ private fun VerifiedLabel(text: String, color: Color, icon: @Composable RowScope } } -enum class GroupConversationDetailsTabItem(@StringRes val titleResId: Int) : TabItem { - OPTIONS(R.string.conversation_details_options_tab), - PARTICIPANTS(R.string.conversation_details_participants_tab); +enum class GroupConversationDetailsTabItem( + @StringRes val titleResId: Int, + @StringRes val contentDescriptionResId: Int +) : TabItem { + OPTIONS( + R.string.conversation_details_options_tab, + R.string.content_description_conversation_details_options_tab_header + ), + PARTICIPANTS( + R.string.conversation_details_participants_tab, + R.string.content_description_conversation_details_participants_tab_header + ); override val title: UIText = UIText.StringResource(titleResId) + override val contentDescription: UIText? = UIText.StringResource(contentDescriptionResId) } @PreviewMultipleThemes diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt index a9154ecdcf6..025978dd464 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt @@ -37,6 +37,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import com.ramcosta.composedestinations.annotation.RootNavGraph @@ -51,6 +53,7 @@ import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.rememberTopBarElevationState import com.wire.android.ui.common.scaffold.WireScaffold import com.wire.android.ui.common.snackbar.LocalSnackbarHostState +import com.wire.android.ui.common.topappbar.NavigationIconType import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar import com.wire.android.ui.destinations.CreatePasswordProtectedGuestLinkScreenDestination import com.wire.android.ui.home.conversations.details.editguestaccess.createPasswordProtectedGuestLink.CreatePasswordGuestLinkNavArgs @@ -103,8 +106,10 @@ fun EditGuestAccessScreen( topBar = { WireCenterAlignedTopAppBar( elevation = scrollState.rememberTopBarElevationState().value, + navigationIconType = NavigationIconType.Back(R.string.content_description_edit_guests_option_back_btn), onNavigationPressed = navigator::navigateBack, - title = stringResource(id = R.string.conversation_options_guests_label) + title = stringResource(id = R.string.conversation_options_guests_label), + titleContentDescription = stringResource(id = R.string.content_description_edit_guests_option_title) ) } ) { internalPadding -> @@ -128,14 +133,17 @@ fun EditGuestAccessScreen( } } item { + val contentDescription = stringResource(id = R.string.content_description_edit_guests_option_link_header) FolderHeader( name = stringResource(id = R.string.folder_label_guest_link), modifier = Modifier .fillMaxWidth() .background(MaterialTheme.wireColorScheme.background) + .semantics { this.contentDescription = contentDescription } ) } item { + val contentDestination = stringResource(id = R.string.content_description_edit_guests_option_link_description) Column( modifier = Modifier .fillMaxSize() @@ -146,6 +154,7 @@ fun EditGuestAccessScreen( bottom = dimensions().spacing8x, top = dimensions().spacing8x, ) + .semantics { this.contentDescription = contentDestination } ) { with(editGuestAccessViewModel) { Text( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt index d27783a3324..0a2417ce385 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt @@ -42,7 +42,9 @@ fun GuestOption( isSwitchEnabled -> R.string.conversation_options_guest_description isSwitchVisible -> R.string.conversation_options_guest_not_editable_description else -> null - } + }, + contentDescriptionRes = R.string.content_description_edit_guests_option, + switcherContentDescriptionRes = R.string.content_description_switch_btn ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt index 9909919d9cb..062836ab8c9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt @@ -35,6 +35,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel @@ -50,6 +52,7 @@ import com.wire.android.ui.common.rememberTopBarElevationState import com.wire.android.ui.common.scaffold.WireScaffold import com.wire.android.ui.common.selectableBackground import com.wire.android.ui.common.spacers.HorizontalSpace +import com.wire.android.ui.common.topappbar.NavigationIconType import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar import com.wire.android.ui.home.messagecomposer.SelfDeletionDuration import com.wire.android.ui.theme.wireColorScheme @@ -74,7 +77,9 @@ fun EditSelfDeletingMessagesScreen( WireCenterAlignedTopAppBar( elevation = scrollState.rememberTopBarElevationState().value, onNavigationPressed = navigator::navigateBack, - title = stringResource(id = R.string.self_deleting_messages_title) + title = stringResource(id = R.string.self_deleting_messages_title), + titleContentDescription = stringResource(id = R.string.content_description_edit_self_delete_title), + navigationIconType = NavigationIconType.Back(R.string.content_description_edit_self_delete_back_btn) ) }) { internalPadding -> with(editSelfDeletingMessagesViewModel) { @@ -138,17 +143,23 @@ fun SelectableSelfDeletingItem( isSelected: Boolean, onSelfDeletionDurationSelected: (SelfDeletionDuration) -> Unit ) { + val text = duration.longLabel.asString() + val contentDestinationSuffix = stringResource( + id = if (isSelected) R.string.content_description_selected_suffix + else R.string.content_description_not_selected_suffix + ) Row( modifier = Modifier .fillMaxWidth() .selectableBackground(isSelected, onClick = { onSelfDeletionDurationSelected(duration) }) .background(color = MaterialTheme.wireColorScheme.surface) .padding(all = MaterialTheme.wireDimensions.spacing16x) + .semantics { contentDescription = "$text$contentDestinationSuffix" } ) { RadioButton(selected = isSelected, onClick = null) HorizontalSpace.x8() Text( - text = duration.longLabel.asString(), + text = text, style = MaterialTheme.wireTypography.body01, color = MaterialTheme.wireColorScheme.onBackground ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt index 65352f8c44e..f160a968038 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt @@ -36,7 +36,9 @@ fun SelfDeletingMessageOption( onClick = onCheckedChange, isLoading = isLoading, title = R.string.self_deleting_messages_option, - subTitle = R.string.self_deleting_messages_option_description + subTitle = R.string.self_deleting_messages_option_description, + contentDescriptionRes = R.string.content_description_conversation_details_self_deleting_option, + switcherContentDescriptionRes = R.string.content_description_switch_btn ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt index c2d9bfaf8df..b66bcf25081 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt @@ -32,6 +32,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import androidx.hilt.navigation.compose.hiltViewModel import com.wire.android.BuildConfig @@ -53,6 +55,8 @@ import com.wire.android.util.ui.PreviewMultipleThemes import com.wire.android.util.ui.UIText import com.wire.kalium.logic.data.conversation.Conversation import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.message.SelfDeletionTimer +import kotlin.time.Duration.Companion.days @Composable fun GroupConversationOptions( @@ -105,15 +109,27 @@ fun GroupConversationSettings( ) } if (state.areAccessOptionsAvailable) { - item { FolderHeader(name = stringResource(R.string.folder_label_access)) } + item { + val contentDescription = stringResource(id = R.string.content_description_conversation_details_accesses_header) + FolderHeader( + name = stringResource(R.string.folder_label_access), + modifier = Modifier.semantics { this.contentDescription = contentDescription } + ) + } item { + val isOnText = stringResource( + if (state.isGuestAllowed) R.string.label_system_message_receipt_mode_on + else R.string.label_system_message_receipt_mode_off + ) + val contentDescription = stringResource(id = R.string.content_description_conversation_details_guests_option, isOnText) GroupConversationOptionsItem( title = stringResource(id = R.string.conversation_options_guests_label), subtitle = stringResource(id = R.string.conversation_details_guest_description), switchState = SwitchState.TextOnly(value = state.isGuestAllowed), arrowType = if (state.isUpdatingGuestAllowed) ArrowType.TITLE_ALIGNED else ArrowType.NONE, clickable = Clickable(enabled = state.isUpdatingGuestAllowed, onClick = onGuestItemClicked, onLongClick = {}), + contentDescription = contentDescription ) } @@ -128,9 +144,18 @@ fun GroupConversationSettings( ) } } - item { FolderHeader(name = stringResource(id = R.string.folder_label_messaging)) } + item { + val contentDescription = stringResource(id = R.string.content_description_conversation_details_messages_header) + FolderHeader( + name = stringResource(id = R.string.folder_label_messaging), + modifier = Modifier.semantics { this.contentDescription = contentDescription } + ) + } + if (!state.selfDeletionTimer.isDisabled) { item { + val isOnText = stringResource(R.string.label_system_message_receipt_mode_on) + val contentDescription = stringResource(R.string.content_description_conversation_details_self_deleting_option, isOnText) GroupConversationOptionsItem( title = stringResource(id = R.string.conversation_options_self_deleting_messages_label), subtitle = stringResource(id = R.string.conversation_options_self_deleting_messages_description), @@ -150,6 +175,7 @@ fun GroupConversationSettings( onClick = onSelfDeletingClicked, onLongClick = {} ), + contentDescription = contentDescription ) } } @@ -213,6 +239,7 @@ private fun GroupNameItem( canBeChanged: Boolean, onClick: () -> Unit = {}, ) { + val contentDescription = stringResource(id = R.string.content_description_conversation_details_group_name, groupName) GroupConversationOptionsItem( label = stringResource(id = R.string.conversation_details_options_group_name), title = groupName, @@ -220,7 +247,8 @@ private fun GroupNameItem( enabled = canBeChanged, onClick = onClick, onLongClick = { /* not handled */ }), - arrowType = if (!canBeChanged) ArrowType.NONE else ArrowType.CENTER_ALIGNED + arrowType = if (!canBeChanged) ArrowType.NONE else ArrowType.CENTER_ALIGNED, + contentDescription = contentDescription ) HorizontalDivider(thickness = Dp.Hairline, color = MaterialTheme.wireColorScheme.divider) } @@ -249,7 +277,9 @@ private fun ServicesOption( isLoading = isLoading, onClick = onCheckedChange, title = R.string.conversation_options_services_label, - subTitle = if (isSwitchEnabledAndVisible) R.string.conversation_options_services_description else null + subTitle = if (isSwitchEnabledAndVisible) R.string.conversation_options_services_description else null, + contentDescriptionRes = R.string.content_description_conversation_details_services_option, + switcherContentDescriptionRes = R.string.content_description_switch_btn ) } @@ -267,7 +297,9 @@ private fun ReadReceiptOption( isLoading = isLoading, onClick = onCheckedChange, title = R.string.conversation_options_read_receipt_label, - subTitle = R.string.conversation_options_read_receipt_description + subTitle = R.string.conversation_options_read_receipt_description, + contentDescriptionRes = R.string.content_description_conversation_details_read_receipts_option, + switcherContentDescriptionRes = R.string.content_description_switch_btn ) } @@ -279,17 +311,31 @@ fun GroupOptionWithSwitch( isLoading: Boolean, onClick: (Boolean) -> Unit, @StringRes title: Int, - @StringRes subTitle: Int? + @StringRes subTitle: Int?, + @StringRes contentDescriptionRes: Int, + @StringRes switcherContentDescriptionRes: Int ) { + val isOnText = stringResource( + if (switchState) R.string.label_system_message_receipt_mode_on + else R.string.label_system_message_receipt_mode_off + ) + val contentDescription = stringResource(id = contentDescriptionRes, isOnText) + val switcherContentDescription = stringResource(id = switcherContentDescriptionRes, isOnText) GroupConversationOptionsItem( title = stringResource(id = title), subtitle = subTitle?.let { stringResource(id = it) }, switchState = when { !switchVisible -> SwitchState.TextOnly(value = switchState) - switchClickable && !isLoading -> SwitchState.Enabled(value = switchState, onCheckedChange = onClick) + switchClickable && !isLoading -> SwitchState.Enabled( + value = switchState, + onCheckedChange = onClick, + contentDescription = switcherContentDescription + ) + else -> SwitchState.Disabled(value = switchState) }, - arrowType = ArrowType.NONE + arrowType = ArrowType.NONE, + contentDescription = contentDescription ) HorizontalDivider(thickness = Dp.Hairline, color = MaterialTheme.wireColorScheme.divider) } @@ -424,3 +470,18 @@ fun PreviewNormalGroupConversationOptions() = WireTheme { {}, {}, {}, {}, {} ) } + +@PreviewMultipleThemes +@Composable +fun PreviewNormalGroupConversationOptionsWithSelfDelet() = WireTheme { + GroupConversationSettings( + GroupConversationOptionsState( + conversationId = ConversationId("someValue", "someDomain"), + groupName = "Normal Group Conversation", + areAccessOptionsAvailable = false, + selfDeletionTimer = SelfDeletionTimer.Enabled(3.days), + isUpdatingSelfDeletingAllowed = true + ), + {}, {}, {}, {}, {} + ) +} diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt index 8cd3137eec6..91760d5f2e5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt @@ -34,6 +34,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -64,10 +66,12 @@ fun GroupConversationOptionsItem( switchState: SwitchState = SwitchState.None, titleStyle: TextStyle = MaterialTheme.wireTypography.body02, arrowType: ArrowType = ArrowType.CENTER_ALIGNED, + contentDescription: String? = null ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier + .semantics { contentDescription?.let { this.contentDescription = contentDescription } } .padding( top = MaterialTheme.wireDimensions.spacing12x, bottom = MaterialTheme.wireDimensions.spacing12x, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt index cd8f9af6d87..b6650963c5d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt @@ -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 @@ -68,8 +70,9 @@ fun ConversationParticipantItem( searchQuery: String = String.EMPTY, showRightArrow: Boolean = true ) { + val contentDescription = participantContentDescription(uiParticipant) RowItemTemplate( - modifier = modifier, + modifier = modifier.semantics { this.contentDescription = contentDescription }, leadingIcon = { UserProfileAvatar( avatarData = uiParticipant.avatarData, @@ -162,6 +165,22 @@ private fun processUsername(uiParticipant: UIParticipant) = when { else -> uiParticipant.handle } +@Composable +private fun participantContentDescription(uiParticipant: UIParticipant): String { + val resId = if (uiParticipant.isSelf) R.string.content_description_conversation_details_member_self + else R.string.content_description_conversation_details_member + + val membership = if (uiParticipant.membership.stringResourceId != -1) stringResource(id = uiParticipant.membership.stringResourceId) + else null + val mlsVerification = if (uiParticipant.isMLSVerified) stringResource(id = R.string.content_description_mls_verified) + else null + val proteusVerification = if (uiParticipant.isProteusVerified) stringResource(id = R.string.content_description_proteus_verified) + else null + val membershipAndVerificationText = listOfNotNull(membership, mlsVerification, proteusVerification).joinToString(", ") + + return stringResource(id = resId, uiParticipant.name, uiParticipant.handle, membershipAndVerificationText) +} + @PreviewMultipleThemes @Composable fun PreviewGroupConversationParticipantItem() { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationAllParticipantsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationAllParticipantsScreen.kt index 8365ea4bf79..5a86be9e0dd 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationAllParticipantsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationAllParticipantsScreen.kt @@ -85,7 +85,7 @@ private fun GroupConversationAllParticipantsContent( WireCenterAlignedTopAppBar( elevation = lazyListState.rememberTopBarElevationState().value, title = stringResource(R.string.conversation_details_group_participants_title), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), onNavigationPressed = onBackPressed ) { // TODO add search bar diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt index 82653621e8c..5003c306a63 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt @@ -26,6 +26,7 @@ import com.wire.android.model.Clickable import com.wire.android.ui.common.divider.WireDivider import com.wire.android.ui.home.conversations.details.participants.model.UIParticipant import com.wire.android.util.extension.folderWithElements +import com.wire.android.util.ui.UIText fun LazyListScope.participantsFoldersWithElements( context: Context, @@ -35,12 +36,20 @@ fun LazyListScope.participantsFoldersWithElements( folderWithElements( header = context.getString(R.string.conversation_details_group_admins, state.data.allAdminsCount), items = state.data.admins, - onRowItemClicked = onRowItemClicked + onRowItemClicked = onRowItemClicked, + folderContentDescription = context.getString( + R.string.content_description_conversation_details_admins_header, + state.data.allAdminsCount + ) ) folderWithElements( header = context.getString(R.string.conversation_details_group_members, state.data.allParticipantsCount), items = state.data.participants, - onRowItemClicked = onRowItemClicked + onRowItemClicked = onRowItemClicked, + folderContentDescription = context.getString( + R.string.content_description_conversation_details_members_header, + state.data.allAdminsCount + ) ) } @@ -48,7 +57,8 @@ fun LazyListScope.folderWithElements( header: String, items: List, onRowItemClicked: (UIParticipant) -> Unit, - showRightArrow: Boolean = true + showRightArrow: Boolean = true, + folderContentDescription: String? = null ) = folderWithElements( header = header, items = items.associateBy { it.id.toString() }, @@ -60,14 +70,16 @@ fun LazyListScope.folderWithElements( showRightArrow = showRightArrow ) }, - divider = { WireDivider() } + divider = { WireDivider() }, + folderContentDescription = folderContentDescription ) fun LazyListScope.folderWithElements( header: String, items: Map, onRowItemClicked: (UIParticipant) -> Unit, - showRightArrow: Boolean = true + showRightArrow: Boolean = true, + folderContentDescription: String? = null ) = folderWithElements( header = header, items = items, @@ -79,5 +91,6 @@ fun LazyListScope.folderWithElements( showRightArrow = showRightArrow ) }, - divider = { WireDivider() } + divider = { WireDivider() }, + folderContentDescription = folderContentDescription ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt index 4be35628394..9bc4c1ce858 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt @@ -193,7 +193,7 @@ private fun Content( WireCenterAlignedTopAppBar( elevation = elevationState, title = stringResource(id = R.string.label_conversation_media), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), onNavigationPressed = onNavigationPressed, bottomContent = { WireTabRow( @@ -271,6 +271,7 @@ enum class ConversationMediaScreenTabItem(@StringRes val titleResId: Int) : TabI FILES(R.string.label_conversation_files); override val title: UIText = UIText.StringResource(titleResId) + override val contentDescription: UIText? = null // TODO set contentDescription if needed } data class AssetOptionsData(val messageId: String, val isMyMessage: Boolean) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/preview/ImagesPreviewScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/preview/ImagesPreviewScreen.kt index bcda40e083d..b6a1784edda 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/preview/ImagesPreviewScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/preview/ImagesPreviewScreen.kt @@ -145,7 +145,7 @@ private fun Content( topBar = { WireCenterAlignedTopAppBar( title = previewState.conversationName, - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), onNavigationPressed = onNavigationPressed, ) }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt index 7056604c256..125034a9c9e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt @@ -129,7 +129,7 @@ private fun MessageDetailsScreenContent( WireCenterAlignedTopAppBar( elevation = elevationState, title = stringResource(R.string.message_details_title), - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onNavigationPressed = onBackPressed ) { WireTabRow( @@ -184,4 +184,6 @@ sealed class MessageDetailsTabItem(@StringRes val titleResId: Int, argument: Str data class Reactions(val count: Int) : MessageDetailsTabItem(R.string.message_details_reactions_tab, "$count") data class ReadReceipts(val count: Int) : MessageDetailsTabItem(R.string.message_details_read_receipts_tab, "$count") + + override val contentDescription: UIText? = null // TODO set contentDescription if needed } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt index f4e2e3b3746..2aaed55f2f4 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt @@ -114,9 +114,9 @@ fun SearchUsersAndServicesScreen( elevation = dimensions().spacing0x, // CollapsingTopBarScaffold already manages elevation title = searchTitle, navigationIconType = when (screenType) { - SearchPeopleScreenType.CONVERSATION_DETAILS -> NavigationIconType.Close - SearchPeopleScreenType.NEW_CONVERSATION -> NavigationIconType.Close - SearchPeopleScreenType.NEW_GROUP_CONVERSATION -> NavigationIconType.Back + SearchPeopleScreenType.CONVERSATION_DETAILS -> NavigationIconType.Close() + SearchPeopleScreenType.NEW_CONVERSATION -> NavigationIconType.Close() + SearchPeopleScreenType.NEW_GROUP_CONVERSATION -> NavigationIconType.Back() }, onNavigationPressed = onClose ) @@ -221,6 +221,7 @@ enum class SearchPeopleTabItem(@StringRes val titleResId: Int) : TabItem { PEOPLE(R.string.label_add_member_people), SERVICES(R.string.label_add_member_services); override val title: UIText = UIText.StringResource(titleResId) + override val contentDescription: UIText? = null // TODO set contentDescription if needed } enum class SearchPeopleScreenType { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/gallery/MediaGalleryScreenTopAppBar.kt b/app/src/main/kotlin/com/wire/android/ui/home/gallery/MediaGalleryScreenTopAppBar.kt index 3f98135a29e..7d8483eb96d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/gallery/MediaGalleryScreenTopAppBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/gallery/MediaGalleryScreenTopAppBar.kt @@ -34,7 +34,7 @@ fun MediaGalleryScreenTopAppBar( WireCenterAlignedTopAppBar( onNavigationPressed = onCloseClick, title = title, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), elevation = 0.dp, actions = { WireSecondaryIconButton( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt index db02c38da47..3f2d41cffd0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt @@ -57,7 +57,8 @@ fun SettingsOptionSwitch( WireSwitch( checked = switchState.value, enabled = switchState is SwitchState.Enabled, - onCheckedChange = (switchState as? SwitchState.Enabled)?.onCheckedChange + onCheckedChange = (switchState as? SwitchState.Enabled)?.onCheckedChange, + contentDescription = (switchState as? SwitchState.Enabled)?.contentDescription ) } } @@ -75,6 +76,7 @@ sealed class SwitchState { data class Enabled( override val value: Boolean = false, override val isOnOffVisible: Boolean = true, + val contentDescription: String? = null, val onCheckedChange: ((Boolean) -> Unit)? ) : Visible(value = value, isOnOffVisible = isOnOffVisible, isSwitchVisible = true) diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/about/AboutThisAppScreen.kt b/app/src/main/kotlin/com/wire/android/ui/settings/about/AboutThisAppScreen.kt index ab76ad9d666..569a4b129aa 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/about/AboutThisAppScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/about/AboutThisAppScreen.kt @@ -85,7 +85,7 @@ private fun AboutThisAppContent( WireCenterAlignedTopAppBar( title = stringResource(id = R.string.about_app_screen_title), elevation = dimensions().spacing0x, - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), onNavigationPressed = onBackPressed ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/e2ei/E2eiCertificateDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/e2ei/E2eiCertificateDetailsScreen.kt index 436426334ae..4e816e2e029 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/e2ei/E2eiCertificateDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/e2ei/E2eiCertificateDetailsScreen.kt @@ -75,7 +75,7 @@ fun E2eiCertificateDetailsScreen( WireCenterAlignedTopAppBar( onNavigationPressed = navigator::navigateBack, title = stringResource(R.string.e2ei_certificate_details_screen_title), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), actions = { WireSecondaryIconButton( onButtonClicked = sheetState::show, diff --git a/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaScreen.kt b/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaScreen.kt index e0fafd05850..9484ab6fcf1 100644 --- a/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaScreen.kt @@ -160,7 +160,7 @@ private fun ImportMediaLoadingContent(navigateBack: () -> Unit) { WireCenterAlignedTopAppBar( elevation = dimensions().spacing0x, onNavigationPressed = navigateBack, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), title = stringResource(id = R.string.import_media_content_title), ) }, @@ -261,7 +261,7 @@ fun ImportMediaRestrictedContent( WireCenterAlignedTopAppBar( elevation = dimensions().spacing0x, onNavigationPressed = navigateBack, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), title = stringResource(id = R.string.import_media_content_title), actions = { UserProfileAvatar( @@ -307,7 +307,7 @@ fun ImportMediaRegularContent( WireCenterAlignedTopAppBar( elevation = lazyListState.topBarElevation(maxAppBarElevation), onNavigationPressed = navigateBack, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), title = stringResource(id = R.string.import_media_content_title), actions = { UserProfileAvatar( @@ -378,7 +378,7 @@ fun ImportMediaLoggedOutContent( WireCenterAlignedTopAppBar( elevation = dimensions().spacing0x, onNavigationPressed = navigateBack, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), title = stringResource(id = R.string.import_media_content_title), ) }, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index 40b5900e539..bc2cb2760bf 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -193,7 +193,7 @@ fun OtherUserProfileScreen( }, onSearchConversationMessagesClick = onSearchConversationMessagesClick, navigateBack = navigator::navigateBack, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onConversationMediaClick = onConversationMediaClick, onLegalHoldLearnMoreClick = remember { { legalHoldSubjectDialogState.show(Unit) } }, ) @@ -597,6 +597,7 @@ enum class OtherUserProfileTabItem(@StringRes val titleResId: Int) : TabItem { DEVICES(R.string.user_profile_devices_tab); override val title: UIText = UIText.StringResource(titleResId) + override val contentDescription: UIText? = null // TODO set contentDescription if needed } @OptIn(ExperimentalMaterial3Api::class) @@ -610,7 +611,7 @@ fun PreviewOtherProfileScreenGroupMemberContent() { connectionState = ConnectionState.ACCEPTED, isUnderLegalHold = true, ), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, @@ -634,7 +635,7 @@ fun PreviewOtherProfileScreenContent() { isUnderLegalHold = true, groupState = null ), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, @@ -657,7 +658,7 @@ fun PreviewOtherProfileScreenContentNotConnected() { connectionState = ConnectionState.CANCELLED, isUnderLegalHold = true, ), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, @@ -682,7 +683,7 @@ fun PreviewOtherProfileScreenTempUser() { isUnderLegalHold = true, expiresAt = Instant.DISTANT_FUTURE ), - navigationIconType = NavigationIconType.Back, + navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt index 16c3ed064c8..449c59e2b59 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt @@ -329,7 +329,7 @@ private fun SelfUserProfileTopBar( WireCenterAlignedTopAppBar( onNavigationPressed = onCloseClick, title = stringResource(id = R.string.user_profile_title), - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), elevation = 0.dp, actions = { WireSecondaryButton( diff --git a/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt b/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt index 4fe3adfb8c1..1dc5328a4ea 100644 --- a/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt +++ b/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt @@ -25,8 +25,11 @@ import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import com.wire.android.ui.home.conversationslist.common.CollapsingFolderHeader import com.wire.android.ui.home.conversationslist.common.FolderHeader +import com.wire.android.util.ui.UIText @Suppress("LongParameterList") inline fun LazyListScope.folderWithElements( @@ -34,6 +37,7 @@ inline fun LazyListScope.folderWithElements( items: Map, animateItemPlacement: Boolean = true, folderType: FolderType = FolderType.Regular, + folderContentDescription: String? = null, crossinline divider: @Composable () -> Unit = {}, crossinline factory: @Composable (T) -> Unit ) { @@ -49,12 +53,15 @@ inline fun LazyListScope.folderWithElements( name = header, modifier = Modifier .fillMaxWidth() + .semantics { folderContentDescription?.let { contentDescription = it } } .let { if (animateItemPlacement) it.animateItem() else it } ) + is FolderType.Regular -> FolderHeader( name = header, modifier = Modifier .fillMaxWidth() + .semantics { folderContentDescription?.let { contentDescription = it } } .let { if (animateItemPlacement) it.animateItem() else it } ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b20e3344f83..b811141ab51 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -179,6 +179,39 @@ All of all participants are verified (Proteus) Scroll to end of conversation Location item + Conversation details, heading + Open conversation options + Options, tab, 1 of 2, double-tap to select + Participants, selected, tab, 2 of 2 + Close conversation details + Add participants + Group admins %d, in list + Group members %d, in list + %1$s, %2$s, %3$s, double tap to open profile + %1$s, you, %2$s, %3$s, double tap to open profile + %s, double-tap to edit + Access, in list + Messaging, in list + Guests, %s, when this is on, people from outside your team can join this conversation, double-tap to adjust guest access + Services, %s, turn this option on to open this conversation to services + Read receipts, %s, when this is on, people can see when their messages in this conversation are read. + Self-deleting messages, %s, when this is on, all messages in this group will disappear after a certain time, double-tap to adjust service access + Guests, %s, turn this option on to open this conversation to people outside your team, even if they don\'t have Wire + Guests, heading + Go back to conversation details + Guest link, in list + Invite others with a link to this conversation. Anyone with the link can join the conversation, even if they don’t have Wire. + Self-deleting messages, heading + Go back to conversation details + Notifications, %s, double tap to open notification settings + Everything, receive notifications for this conversation about everything,including audio and video calls, selected + Calls, mentions and replies, only receive notifications for this conversation when someone calls, mentions you or replies to you, double tap to select + Nothing, receive no notifications for this conversation at all, double tap to select + , selected + , double tab to select + Verified (MLS) + Verified (Proteus) + switch button, %s, double tap to toggle setting https://medium.com/wire-news/android-updates/home https://medium.com/feed/wire-news/tagged/android diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt index 0d4a3b67566..02e3de30fd1 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt @@ -37,6 +37,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.wire.android.model.ClickBlockParams @@ -56,6 +58,7 @@ fun MenuBottomSheetItem( itemProvidedColor: Color = MaterialTheme.colorScheme.secondary, onItemClick: () -> Unit = {}, enabled: Boolean = true, + contentDescription: String? = null ) { CompositionLocalProvider(LocalContentColor provides itemProvidedColor) { val clickable = remember(onItemClick, clickBlockParams) { @@ -72,6 +75,7 @@ fun MenuBottomSheetItem( .fillMaxWidth() .clickable(clickable) .padding(MaterialTheme.wireDimensions.conversationBottomSheetItemPadding) + .semantics { this.contentDescription = contentDescription ?: title } ) { if (icon != null) { icon() diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/ModalSheetHeaderItem.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/ModalSheetHeaderItem.kt index c2c9882ce5b..1f00db1864c 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/ModalSheetHeaderItem.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/ModalSheetHeaderItem.kt @@ -30,6 +30,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.divider.WireDivider @@ -57,7 +59,8 @@ fun ModalSheetHeaderItem(header: MenuModalSheetHeader = MenuModalSheetHeader.Gon Spacer(modifier = Modifier.width(dimensions().spacing8x)) Text( text = header.title, - style = MaterialTheme.wireTypography.title02 + style = MaterialTheme.wireTypography.title02, + modifier = Modifier.semantics { contentDescription = header.title } ) } WireDivider() diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt index eba73bd9a11..69e75abf57e 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt @@ -18,6 +18,7 @@ package com.wire.android.ui.common.button +import androidx.annotation.StringRes import androidx.compose.animation.Crossfade import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.interaction.MutableInteractionSource @@ -49,6 +50,9 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.layout import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize @@ -88,7 +92,8 @@ fun WireButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + @StringRes contentDescriptionRes: Int? = null ) { val border = when { borderWidth > 0.dp -> BorderStroke(width = borderWidth, color = colors.outlineColor(state).value) @@ -102,12 +107,16 @@ fun WireButton( disabledContentColor = colors.rippleColor(state).value, ) val onClickWithSyncObserver = rememberClickBlockAction(clickBlockParams, onClick) + val contentDescription = contentDescriptionRes?.let { stringResource(id = it) } ?: text CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides min(minClickableSize.width, minClickableSize.height)) { Button( onClick = onClickWithSyncObserver, modifier = modifier .let { if (fillMaxWidth) it.fillMaxWidth() else it.wrapContentWidth() } .sizeIn(minHeight = minSize.height, minWidth = minSize.width) + .semantics { + contentDescription?.let { this.contentDescription = it } + } .layout { measurable, constraints -> val placeable = measurable.measure(constraints) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt index 9abf8a1c644..beeae10caa4 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt @@ -18,6 +18,7 @@ package com.wire.android.ui.common.button +import androidx.annotation.StringRes import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -70,6 +71,7 @@ fun WirePrimaryButton( vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + @StringRes contentDescriptionRes: Int? = null, modifier: Modifier = Modifier, ) = WireButton( onClick = onClick, @@ -91,7 +93,8 @@ fun WirePrimaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, - modifier = modifier + modifier = modifier, + contentDescriptionRes = contentDescriptionRes ) @Preview(name = "Default WirePrimaryButton") diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt index f2f03e37ad0..e21a66a2373 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt @@ -18,6 +18,7 @@ package com.wire.android.ui.common.button +import androidx.annotation.StringRes import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -69,6 +70,7 @@ fun WireSecondaryButton( vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + @StringRes contentDescriptionRes: Int? = null, modifier: Modifier = Modifier, ) = WireButton( onClick = onClick, @@ -90,6 +92,7 @@ fun WireSecondaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, + contentDescriptionRes = contentDescriptionRes, modifier = modifier ) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/NavigationIconButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/NavigationIconButton.kt index 349a65f3fdc..f0618adca53 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/NavigationIconButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/NavigationIconButton.kt @@ -20,7 +20,7 @@ package com.wire.android.ui.common.topappbar import androidx.annotation.StringRes import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.Menu @@ -40,11 +40,17 @@ fun NavigationIconButton(iconType: NavigationIconType, onClick: () -> Unit, modi } @Composable -fun BackNavigationIconButton(onBackButtonClick: () -> Unit) { NavigationIconButton(NavigationIconType.Back, onBackButtonClick) } +fun BackNavigationIconButton(onBackButtonClick: () -> Unit) { + NavigationIconButton(NavigationIconType.Back(), onBackButtonClick) +} + +sealed class NavigationIconType(val icon: ImageVector, @StringRes open val contentDescription: Int) { + data class Back(@StringRes override val contentDescription: Int = R.string.content_description_back_button) : + NavigationIconType(Icons.AutoMirrored.Filled.ArrowBack, contentDescription) + + data class Close(@StringRes override val contentDescription: Int = R.string.content_description_close_button) : + NavigationIconType(Icons.Filled.Close, contentDescription) -enum class NavigationIconType(val icon: ImageVector, @StringRes val contentDescription: Int) { - Back(Icons.Filled.ArrowBack, R.string.content_description_back_button), - Close(Icons.Filled.Close, R.string.content_description_close_button), - Menu(Icons.Filled.Menu, R.string.content_description_menu_button), - Collapse(Icons.Filled.KeyboardArrowDown, R.string.content_description_drop_down_icon) + data object Menu : NavigationIconType(Icons.Filled.Menu, R.string.content_description_menu_button) + data object Collapse : NavigationIconType(Icons.Filled.KeyboardArrowDown, R.string.content_description_drop_down_icon) } diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt index c76c91c5ced..91e0cc8f4bd 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt @@ -34,6 +34,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.rememberTextMeasurer @@ -56,8 +58,9 @@ fun WireCenterAlignedTopAppBar( maxLines: Int = 2, subtitleContent: @Composable ColumnScope.() -> Unit = {}, onNavigationPressed: () -> Unit = {}, - navigationIconType: NavigationIconType? = NavigationIconType.Back, + navigationIconType: NavigationIconType? = NavigationIconType.Back(), elevation: Dp = MaterialTheme.wireDimensions.topBarShadowElevation, + titleContentDescription: String? = null, actions: @Composable RowScope.() -> Unit = {}, bottomContent: @Composable ColumnScope.() -> Unit = {} ) { @@ -66,7 +69,8 @@ fun WireCenterAlignedTopAppBar( WireTopAppBarTitle( title = title, style = titleStyle, - maxLines = maxLines + maxLines = maxLines, + contentDescription = titleContentDescription ) }, subtitleContent = subtitleContent, @@ -86,7 +90,7 @@ fun WireCenterAlignedTopAppBar( modifier: Modifier = Modifier, subtitleContent: @Composable ColumnScope.() -> Unit = {}, onNavigationPressed: () -> Unit = {}, - navigationIconType: NavigationIconType? = NavigationIconType.Back, + navigationIconType: NavigationIconType? = NavigationIconType.Back(), elevation: Dp = MaterialTheme.wireDimensions.topBarShadowElevation, actions: @Composable RowScope.() -> Unit = {}, bottomContent: @Composable ColumnScope.() -> Unit = {} @@ -118,7 +122,8 @@ fun WireTopAppBarTitle( title: String, style: TextStyle, modifier: Modifier = Modifier, - maxLines: Int = 2 + maxLines: Int = 2, + contentDescription: String? = null ) { // There's an ongoing issue about multiline text taking all width available instead of wrapping visible text. // https://issuetracker.google.com/issues/206039942 @@ -127,6 +132,9 @@ fun WireTopAppBarTitle( // This workaround is based on this: https://stackoverflow.com/a/69947555, but instead of using SubcomposeLayout, we just measure text. BoxWithConstraints( modifier = modifier + .semantics { + contentDescription?.let { this.contentDescription = contentDescription } + } .padding(horizontal = dimensions().spacing6x) ) { val textMeasurer = rememberTextMeasurer() diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasScreen.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasScreen.kt index a0f9ec7e18c..0f3ec7aa91e 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasScreen.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasScreen.kt @@ -196,7 +196,7 @@ internal fun DrawingTopBar( ) { WireCenterAlignedTopAppBar( title = conversationTitle, - navigationIconType = NavigationIconType.Close, + navigationIconType = NavigationIconType.Close(), onNavigationPressed = dismissAction, actions = { WireSecondaryIconButton( From 05007bab795426ca09186a5be9bac6c97d0c57fd Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Thu, 10 Oct 2024 13:26:54 +0300 Subject: [PATCH 02/16] Fixed code-style --- .../editguestaccess/EditGuestAccessScreen.kt | 6 +- .../EditSelfDeletingMessagesScreen.kt | 13 ++-- .../options/GroupConversationOptions.kt | 74 +++++++++++++------ .../ConversationParticipantItem.kt | 22 ++++-- .../GroupConversationParticipantList.kt | 1 - .../android/util/extension/LazyListScope.kt | 3 +- .../ui/common/button/WirePrimaryButton.kt | 4 +- 7 files changed, 79 insertions(+), 44 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt index 025978dd464..d566d61c6eb 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt @@ -133,7 +133,8 @@ fun EditGuestAccessScreen( } } item { - val contentDescription = stringResource(id = R.string.content_description_edit_guests_option_link_header) + val contentDescription = + stringResource(id = R.string.content_description_edit_guests_option_link_header) FolderHeader( name = stringResource(id = R.string.folder_label_guest_link), modifier = Modifier @@ -143,7 +144,8 @@ fun EditGuestAccessScreen( ) } item { - val contentDestination = stringResource(id = R.string.content_description_edit_guests_option_link_description) + val contentDestination = + stringResource(id = R.string.content_description_edit_guests_option_link_description) Column( modifier = Modifier .fillMaxSize() diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt index 062836ab8c9..dbf50806c28 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt @@ -81,7 +81,8 @@ fun EditSelfDeletingMessagesScreen( titleContentDescription = stringResource(id = R.string.content_description_edit_self_delete_title), navigationIconType = NavigationIconType.Back(R.string.content_description_edit_self_delete_back_btn) ) - }) { internalPadding -> + } + ) { internalPadding -> with(editSelfDeletingMessagesViewModel) { Column(modifier = Modifier.padding(internalPadding)) { SelfDeletingMessageOption( @@ -144,10 +145,12 @@ fun SelectableSelfDeletingItem( onSelfDeletionDurationSelected: (SelfDeletionDuration) -> Unit ) { val text = duration.longLabel.asString() - val contentDestinationSuffix = stringResource( - id = if (isSelected) R.string.content_description_selected_suffix - else R.string.content_description_not_selected_suffix - ) + val contentDescriptionId = if (isSelected) { + R.string.content_description_selected_suffix + } else { + R.string.content_description_not_selected_suffix + } + val contentDestinationSuffix = stringResource(id = contentDescriptionId) Row( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt index b66bcf25081..29c750b306a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt @@ -110,7 +110,8 @@ fun GroupConversationSettings( } if (state.areAccessOptionsAvailable) { item { - val contentDescription = stringResource(id = R.string.content_description_conversation_details_accesses_header) + val contentDescription = + stringResource(id = R.string.content_description_conversation_details_accesses_header) FolderHeader( name = stringResource(R.string.folder_label_access), modifier = Modifier.semantics { this.contentDescription = contentDescription } @@ -119,8 +120,11 @@ fun GroupConversationSettings( item { val isOnText = stringResource( - if (state.isGuestAllowed) R.string.label_system_message_receipt_mode_on - else R.string.label_system_message_receipt_mode_off + if (state.isGuestAllowed) { + R.string.label_system_message_receipt_mode_on + } else { + R.string.label_system_message_receipt_mode_off + } ) val contentDescription = stringResource(id = R.string.content_description_conversation_details_guests_option, isOnText) GroupConversationOptionsItem( @@ -145,7 +149,8 @@ fun GroupConversationSettings( } } item { - val contentDescription = stringResource(id = R.string.content_description_conversation_details_messages_header) + val contentDescription = + stringResource(id = R.string.content_description_conversation_details_messages_header) FolderHeader( name = stringResource(id = R.string.folder_label_messaging), modifier = Modifier.semantics { this.contentDescription = contentDescription } @@ -155,7 +160,8 @@ fun GroupConversationSettings( if (!state.selfDeletionTimer.isDisabled) { item { val isOnText = stringResource(R.string.label_system_message_receipt_mode_on) - val contentDescription = stringResource(R.string.content_description_conversation_details_self_deleting_option, isOnText) + val contentDescription = + stringResource(R.string.content_description_conversation_details_self_deleting_option, isOnText) GroupConversationOptionsItem( title = stringResource(id = R.string.conversation_options_self_deleting_messages_label), subtitle = stringResource(id = R.string.conversation_options_self_deleting_messages_description), @@ -239,7 +245,8 @@ private fun GroupNameItem( canBeChanged: Boolean, onClick: () -> Unit = {}, ) { - val contentDescription = stringResource(id = R.string.content_description_conversation_details_group_name, groupName) + val contentDescription = + stringResource(id = R.string.content_description_conversation_details_group_name, groupName) GroupConversationOptionsItem( label = stringResource(id = R.string.conversation_details_options_group_name), title = groupName, @@ -316,8 +323,7 @@ fun GroupOptionWithSwitch( @StringRes switcherContentDescriptionRes: Int ) { val isOnText = stringResource( - if (switchState) R.string.label_system_message_receipt_mode_on - else R.string.label_system_message_receipt_mode_off + if (switchState) R.string.label_system_message_receipt_mode_on else R.string.label_system_message_receipt_mode_off ) val contentDescription = stringResource(id = contentDescriptionRes, isOnText) val switcherContentDescription = stringResource(id = switcherContentDescriptionRes, isOnText) @@ -373,7 +379,7 @@ fun DisableConformationDialog(@StringRes title: Int, @StringRes text: Int, onCon @Composable fun PreviewAdminTeamGroupConversationOptions() = WireTheme { GroupConversationSettings( - GroupConversationOptionsState( + state = GroupConversationOptionsState( conversationId = ConversationId("someValue", "someDomain"), groupName = "Team Group Conversation", areAccessOptionsAvailable = true, @@ -387,11 +393,11 @@ fun PreviewAdminTeamGroupConversationOptions() = WireTheme { isReadReceiptAllowed = true, mlsEnabled = true ), - {}, - {}, - {}, - {}, - {} + onGuestItemClicked = {}, + onSelfDeletingClicked = {}, + onServiceSwitchClicked = {}, + onReadReceiptSwitchClicked = {}, + onEditGroupName = {}, ) } @@ -399,7 +405,7 @@ fun PreviewAdminTeamGroupConversationOptions() = WireTheme { @Composable fun PreviewGuestAdminTeamGroupConversationOptions() = WireTheme { GroupConversationSettings( - GroupConversationOptionsState( + state = GroupConversationOptionsState( conversationId = ConversationId("someValue", "someDomain"), groupName = "Team Group Conversation", areAccessOptionsAvailable = true, @@ -412,7 +418,11 @@ fun PreviewGuestAdminTeamGroupConversationOptions() = WireTheme { isServicesAllowed = true, isReadReceiptAllowed = true, ), - {}, {}, {}, {}, {} + onGuestItemClicked = {}, + onSelfDeletingClicked = {}, + onServiceSwitchClicked = {}, + onReadReceiptSwitchClicked = {}, + onEditGroupName = {}, ) } @@ -420,7 +430,7 @@ fun PreviewGuestAdminTeamGroupConversationOptions() = WireTheme { @Composable fun PreviewExternalMemberAdminTeamGroupConversationOptions() = WireTheme { GroupConversationSettings( - GroupConversationOptionsState( + state = GroupConversationOptionsState( conversationId = ConversationId("someValue", "someDomain"), groupName = "Team Group Conversation", areAccessOptionsAvailable = true, @@ -433,7 +443,11 @@ fun PreviewExternalMemberAdminTeamGroupConversationOptions() = WireTheme { isServicesAllowed = true, isReadReceiptAllowed = true, ), - {}, {}, {}, {}, {} + onGuestItemClicked = {}, + onSelfDeletingClicked = {}, + onServiceSwitchClicked = {}, + onReadReceiptSwitchClicked = {}, + onEditGroupName = {}, ) } @@ -441,7 +455,7 @@ fun PreviewExternalMemberAdminTeamGroupConversationOptions() = WireTheme { @Composable fun PreviewMemberTeamGroupConversationOptions() = WireTheme { GroupConversationSettings( - GroupConversationOptionsState( + state = GroupConversationOptionsState( conversationId = ConversationId("someValue", "someDomain"), groupName = "Normal Group Conversation", areAccessOptionsAvailable = true, @@ -454,7 +468,11 @@ fun PreviewMemberTeamGroupConversationOptions() = WireTheme { isServicesAllowed = true, isReadReceiptAllowed = true, ), - {}, {}, {}, {}, {} + onGuestItemClicked = {}, + onSelfDeletingClicked = {}, + onServiceSwitchClicked = {}, + onReadReceiptSwitchClicked = {}, + onEditGroupName = {}, ) } @@ -462,12 +480,16 @@ fun PreviewMemberTeamGroupConversationOptions() = WireTheme { @Composable fun PreviewNormalGroupConversationOptions() = WireTheme { GroupConversationSettings( - GroupConversationOptionsState( + state = GroupConversationOptionsState( conversationId = ConversationId("someValue", "someDomain"), groupName = "Normal Group Conversation", areAccessOptionsAvailable = false ), - {}, {}, {}, {}, {} + onGuestItemClicked = {}, + onSelfDeletingClicked = {}, + onServiceSwitchClicked = {}, + onReadReceiptSwitchClicked = {}, + onEditGroupName = {}, ) } @@ -475,13 +497,17 @@ fun PreviewNormalGroupConversationOptions() = WireTheme { @Composable fun PreviewNormalGroupConversationOptionsWithSelfDelet() = WireTheme { GroupConversationSettings( - GroupConversationOptionsState( + state = GroupConversationOptionsState( conversationId = ConversationId("someValue", "someDomain"), groupName = "Normal Group Conversation", areAccessOptionsAvailable = false, selfDeletionTimer = SelfDeletionTimer.Enabled(3.days), isUpdatingSelfDeletingAllowed = true ), - {}, {}, {}, {}, {} + onGuestItemClicked = {}, + onSelfDeletingClicked = {}, + onServiceSwitchClicked = {}, + onReadReceiptSwitchClicked = {}, + onEditGroupName = {}, ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt index b6650963c5d..728011a51c6 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt @@ -167,15 +167,21 @@ private fun processUsername(uiParticipant: UIParticipant) = when { @Composable private fun participantContentDescription(uiParticipant: UIParticipant): String { - val resId = if (uiParticipant.isSelf) R.string.content_description_conversation_details_member_self - else R.string.content_description_conversation_details_member + val resId = if (uiParticipant.isSelf) { + R.string.content_description_conversation_details_member_self + } else { + R.string.content_description_conversation_details_member + } - val membership = if (uiParticipant.membership.stringResourceId != -1) stringResource(id = uiParticipant.membership.stringResourceId) - else null - val mlsVerification = if (uiParticipant.isMLSVerified) stringResource(id = R.string.content_description_mls_verified) - else null - val proteusVerification = if (uiParticipant.isProteusVerified) stringResource(id = R.string.content_description_proteus_verified) - else null + val membership = uiParticipant.membership.stringResourceId.let { + if (it != -1) stringResource(id = it) else null + } + val mlsVerification = uiParticipant.isMLSVerified.let { + if (it) stringResource(id = R.string.content_description_mls_verified) else null + } + val proteusVerification = uiParticipant.isProteusVerified.let { + if (it) stringResource(id = R.string.content_description_proteus_verified) else null + } val membershipAndVerificationText = listOfNotNull(membership, mlsVerification, proteusVerification).joinToString(", ") return stringResource(id = resId, uiParticipant.name, uiParticipant.handle, membershipAndVerificationText) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt index 5003c306a63..4e62a3ead30 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt @@ -26,7 +26,6 @@ import com.wire.android.model.Clickable import com.wire.android.ui.common.divider.WireDivider import com.wire.android.ui.home.conversations.details.participants.model.UIParticipant import com.wire.android.util.extension.folderWithElements -import com.wire.android.util.ui.UIText fun LazyListScope.participantsFoldersWithElements( context: Context, diff --git a/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt b/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt index 1dc5328a4ea..6ecde1d4add 100644 --- a/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt +++ b/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt @@ -29,9 +29,8 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import com.wire.android.ui.home.conversationslist.common.CollapsingFolderHeader import com.wire.android.ui.home.conversationslist.common.FolderHeader -import com.wire.android.util.ui.UIText -@Suppress("LongParameterList") +@Suppress("LongParameterList", "CyclomaticComplexMethod") inline fun LazyListScope.folderWithElements( header: String? = null, items: Map, diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt index beeae10caa4..0f093b5957d 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt @@ -50,6 +50,7 @@ import com.wire.android.ui.theme.wireTypography @Composable fun WirePrimaryButton( onClick: () -> Unit, + modifier: Modifier = Modifier, loading: Boolean = false, leadingIcon: @Composable (() -> Unit)? = null, leadingIconAlignment: IconAlignment = IconAlignment.Center, @@ -71,8 +72,7 @@ fun WirePrimaryButton( vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - @StringRes contentDescriptionRes: Int? = null, - modifier: Modifier = Modifier, + @StringRes contentDescriptionRes: Int? = null ) = WireButton( onClick = onClick, loading = loading, From 336bc0aaf0cbe5d10a812adbffba4869c78cc609 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Thu, 10 Oct 2024 13:34:01 +0300 Subject: [PATCH 03/16] Fixed code-style one more --- .../conversations/details/options/GroupConversationOptions.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt index 29c750b306a..368318a0a55 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt @@ -126,7 +126,8 @@ fun GroupConversationSettings( R.string.label_system_message_receipt_mode_off } ) - val contentDescription = stringResource(id = R.string.content_description_conversation_details_guests_option, isOnText) + val contentDescription = + stringResource(id = R.string.content_description_conversation_details_guests_option, isOnText) GroupConversationOptionsItem( title = stringResource(id = R.string.conversation_options_guests_label), subtitle = stringResource(id = R.string.conversation_details_guest_description), From f4eadad4dcbc147eec6b43e5cac6d1dc611ed32f Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Thu, 10 Oct 2024 15:06:14 +0300 Subject: [PATCH 04/16] Fixed code-style again --- .../com/wire/android/ui/common/button/WireSecondaryButton.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt index e21a66a2373..fb46d9782ea 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt @@ -49,6 +49,7 @@ import com.wire.android.ui.theme.wireTypography @Composable fun WireSecondaryButton( onClick: () -> Unit, + modifier: Modifier = Modifier, loading: Boolean = false, leadingIcon: @Composable (() -> Unit)? = null, leadingIconAlignment: IconAlignment = IconAlignment.Center, @@ -70,8 +71,7 @@ fun WireSecondaryButton( vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - @StringRes contentDescriptionRes: Int? = null, - modifier: Modifier = Modifier, + @StringRes contentDescriptionRes: Int? = null ) = WireButton( onClick = onClick, loading = loading, From 787bc01a4af6a081ae1819182718ab50441e4059 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Fri, 11 Oct 2024 17:33:15 +0300 Subject: [PATCH 05/16] Fixed, but not everything yet --- .../com/wire/android/ui/common/ArrowIcon.kt | 5 +- .../android/ui/common/UserProfileAvatar.kt | 1 + .../wire/android/ui/common/WireCheckIcon.kt | 5 +- .../com/wire/android/ui/common/WireSwitch.kt | 7 +- .../com/wire/android/ui/common/WireTabRow.kt | 10 ++- .../bottomsheet/RichMenuBottomSheetItem.kt | 11 +-- .../conversation/HomeSheetContent.kt | 26 +++---- .../conversation/MutingOptionsSheetContent.kt | 19 ++--- .../CreateGuestLinkBottomSheet.kt | 4 +- .../editguestaccess/EditGuestAccessScreen.kt | 8 --- .../details/editguestaccess/GuestOption.kt | 4 +- .../EditSelfDeletingMessagesScreen.kt | 12 +--- .../SelfDeletingMessageOption.kt | 4 +- .../options/GroupConversationOptions.kt | 71 ++++--------------- .../options/GroupConversationOptionsItem.kt | 11 ++- .../ConversationParticipantItem.kt | 32 ++------- .../GroupConversationParticipantList.kt | 21 ++---- .../conversations/messages/QuotedMessage.kt | 5 +- .../home/conversations/model/MessageTypes.kt | 2 + .../location/LocationMessageType.kt | 2 + .../home/conversationslist/common/RowItem.kt | 2 + .../android/ui/home/settings/SettingsItem.kt | 2 + .../ui/home/settings/SettingsOptionSwitch.kt | 3 +- .../android/util/extension/LazyListScope.kt | 5 -- app/src/main/res/values/strings.xml | 34 +++------ .../com/wire/android/model/Clickable.kt | 2 + .../com/wire/android/ui/common/Extensions.kt | 39 +++++++--- .../common/bottomsheet/MenuBottomSheetItem.kt | 8 +-- .../android/ui/common/button/WireButton.kt | 11 +-- .../ui/common/button/WirePrimaryButton.kt | 7 +- .../ui/common/button/WireSecondaryButton.kt | 5 +- .../topappbar/WireCenterAlignedTopAppBar.kt | 3 +- 32 files changed, 144 insertions(+), 237 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/ArrowIcon.kt b/app/src/main/kotlin/com/wire/android/ui/common/ArrowIcon.kt index e4aa73c8746..7b0b2ca90ff 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/ArrowIcon.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/ArrowIcon.kt @@ -32,11 +32,12 @@ import com.wire.android.ui.theme.wireDimensions @Composable fun ArrowRightIcon( - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + @StringRes contentDescription: Int = R.string.content_description_right_arrow, ) { ArrowIcon( arrowIcon = R.drawable.ic_arrow_right, - contentDescription = R.string.content_description_right_arrow, + contentDescription = contentDescription, modifier = modifier ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt b/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt index a36ea965fe5..af8e491bbe7 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt @@ -142,6 +142,7 @@ fun UserProfileAvatar( .wrapContentSize() .clip(CircleShape) .clickable(clickable) + .clickableDescriptions(clickable) ) { var userStatusIndicatorParams by remember { mutableStateOf(Size.Zero to Offset.Zero) } Box( diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireCheckIcon.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireCheckIcon.kt index 5bee223162c..f804d37aeb0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireCheckIcon.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireCheckIcon.kt @@ -18,6 +18,7 @@ package com.wire.android.ui.common +import androidx.annotation.StringRes import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -30,10 +31,10 @@ import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions @Composable -fun WireCheckIcon() { +fun WireCheckIcon(@StringRes contentDescription: Int = R.string.content_description_check) { Icon( painter = painterResource(id = R.drawable.ic_check_circle), - contentDescription = stringResource(R.string.content_description_check), + contentDescription = stringResource(contentDescription), modifier = Modifier.size(MaterialTheme.wireDimensions.wireIconButtonSize), tint = MaterialTheme.wireColorScheme.positive ) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt index 63dd0528b9e..f23d6e95aaf 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -46,14 +47,12 @@ fun WireSwitch( enabled: Boolean = true, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, colors: SwitchColors = wireSwitchColors(), - contentDescription: String? = null + toggleActionDescription: String? = null ) { Switch( checked, onCheckedChange, - modifier.semantics { - if (enabled) contentDescription?.let { this.contentDescription = contentDescription } - }, + modifier.semantics { toggleActionDescription?.let { onClick(it) { false } } }, thumbContent, enabled, colors, diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt index a21d2f7d7f5..9d9271d5561 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt @@ -35,8 +35,11 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.unit.dp import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireTypography @@ -73,10 +76,13 @@ fun WireTabRow( if (upperCaseTitles) it.uppercase() else it } val contentDescription = tabItem.contentDescription?.asString() + val selectText = stringResource(id = com.wire.android.R.string.content_description_select_label) Tab( - modifier = Modifier.semantics { - contentDescription?.let { this.contentDescription = contentDescription } + modifier = Modifier.semantics() { + onClick(selectText) { false } + this.contentDescription = "2" + this.stateDescription = "1" }, enabled = true, text = { diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt index 23871816f5b..8b8fee6caaf 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt @@ -32,14 +32,16 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview +import com.wire.android.R import com.wire.android.model.Clickable import com.wire.android.ui.common.WireCheckIcon import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.common.dimensions import com.wire.android.ui.theme.DEFAULT_WEIGHT import com.wire.android.ui.theme.wireColorScheme @@ -55,8 +57,7 @@ fun SelectableMenuBottomSheetItem( subLine: String? = null, icon: @Composable () -> Unit = { }, onItemClick: Clickable = Clickable(enabled = false) {}, - state: RichMenuItemState = RichMenuItemState.DEFAULT, - contentDescription: String? = null + state: RichMenuItemState = RichMenuItemState.DEFAULT ) { Row( verticalAlignment = Alignment.CenterVertically, @@ -66,7 +67,7 @@ fun SelectableMenuBottomSheetItem( .defaultMinSize(minHeight = dimensions().spacing48x) .let { if (isSelectedItem(state)) it.background(MaterialTheme.wireColorScheme.secondaryButtonSelected) else it } .clickable(onItemClick) - .semantics { this.contentDescription = contentDescription ?: title } + .clickableDescriptions(onItemClick) .padding(vertical = dimensions().spacing12x, horizontal = dimensions().spacing16x) ) { icon() @@ -95,7 +96,7 @@ fun SelectableMenuBottomSheetItem( .padding(start = dimensions().spacing8x) .align(Alignment.CenterVertically) ) { - WireCheckIcon() + WireCheckIcon(R.string.label_selected) } } } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt index 88a9c7fee1a..5df59dd1cb0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt @@ -94,21 +94,16 @@ internal fun ConversationMainSheetContent( menuItems = buildList<@Composable () -> Unit> { if (conversationSheetContent.canEditNotifications() && !conversationSheetContent.isArchived) { add { - val contentDescription = stringResource( - id = R.string.content_description_conversation_menu_notification_setting, - conversationSheetContent.mutingConversationState.getMutedStatusTextResource() - ) MenuBottomSheetItem( title = stringResource(R.string.label_notifications), icon = { MenuItemIcon( id = R.drawable.ic_mute, - contentDescription = stringResource(R.string.content_description_muted_conversation), + contentDescription = null, ) }, action = { NotificationsOptionsItemAction(conversationSheetContent.mutingConversationState) }, - onItemClick = navigateToNotification, - contentDescription = contentDescription + onItemClick = navigateToNotification ) } } @@ -144,10 +139,7 @@ internal fun ConversationMainSheetContent( icon = { MenuItemIcon( id = R.drawable.ic_archive, - contentDescription = stringResource( - if (conversationSheetContent.isArchived) R.string.content_description_unarchive - else R.string.content_description_move_to_archive - ), + contentDescription = null, ) }, title = stringResource( @@ -173,7 +165,7 @@ internal fun ConversationMainSheetContent( icon = { MenuItemIcon( id = R.drawable.ic_erase, - contentDescription = stringResource(R.string.content_description_clear_content), + contentDescription = null, ) }, title = stringResource(R.string.label_clear_content), @@ -196,7 +188,7 @@ internal fun ConversationMainSheetContent( icon = { MenuItemIcon( id = R.drawable.ic_block, - contentDescription = stringResource(R.string.content_description_block_the_user), + contentDescription = null, ) }, itemProvidedColor = MaterialTheme.colorScheme.error, @@ -219,7 +211,7 @@ internal fun ConversationMainSheetContent( icon = { MenuItemIcon( id = R.drawable.ic_block, - contentDescription = stringResource(R.string.content_description_unblock_the_user) + contentDescription = null ) }, itemProvidedColor = MaterialTheme.colorScheme.onBackground, @@ -241,7 +233,7 @@ internal fun ConversationMainSheetContent( icon = { MenuItemIcon( id = R.drawable.ic_leave, - contentDescription = stringResource(R.string.content_description_leave_the_group), + contentDescription = null, ) }, itemProvidedColor = MaterialTheme.colorScheme.error, @@ -263,7 +255,7 @@ internal fun ConversationMainSheetContent( icon = { MenuItemIcon( id = R.drawable.ic_remove, - contentDescription = stringResource(R.string.content_description_delete_the_group), + contentDescription = null, ) }, title = stringResource(R.string.label_delete_group), @@ -298,6 +290,6 @@ fun NotificationsOptionsItemAction( modifier = Modifier.weight(weight = 1f, fill = false) ) Spacer(modifier = Modifier.size(dimensions().spacing16x)) - ArrowRightIcon() + ArrowRightIcon(contentDescription = R.string.content_description_empty) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt index ab991f46a1d..bafff78b1b0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/MutingOptionsSheetContent.kt @@ -25,10 +25,10 @@ import androidx.compose.ui.res.stringResource import com.wire.android.R import com.wire.android.model.Clickable import com.wire.android.ui.common.ArrowLeftIcon -import com.wire.android.ui.common.bottomsheet.WireMenuModalSheetContent import com.wire.android.ui.common.bottomsheet.MenuModalSheetHeader -import com.wire.android.ui.common.bottomsheet.SelectableMenuBottomSheetItem import com.wire.android.ui.common.bottomsheet.RichMenuItemState +import com.wire.android.ui.common.bottomsheet.SelectableMenuBottomSheetItem +import com.wire.android.ui.common.bottomsheet.WireMenuModalSheetContent import com.wire.android.ui.common.dimensions import com.wire.kalium.logic.data.conversation.MutedConversationStatus @@ -51,8 +51,9 @@ internal fun MutingOptionsSheetContent( SelectableMenuBottomSheetItem( title = stringResource(id = R.string.muting_option_all_allowed_title), subLine = stringResource(id = R.string.muting_option_all_allowed_text), - onItemClick = Clickable { onMuteConversation(MutedConversationStatus.AllAllowed) }, - contentDescription = stringResource(id = R.string.content_description_muting_menu_everything), + onItemClick = Clickable(onClickDescription = stringResource(id = R.string.content_description_select_label)) { + onMuteConversation(MutedConversationStatus.AllAllowed) + }, state = if (mutingConversationState == MutedConversationStatus.AllAllowed) RichMenuItemState.SELECTED else RichMenuItemState.DEFAULT ) @@ -61,8 +62,9 @@ internal fun MutingOptionsSheetContent( SelectableMenuBottomSheetItem( title = stringResource(id = R.string.muting_option_only_mentions_title), subLine = stringResource(id = R.string.muting_option_only_mentions_text), - onItemClick = Clickable { onMuteConversation(MutedConversationStatus.OnlyMentionsAndRepliesAllowed) }, - contentDescription = stringResource(id = R.string.content_description_muting_menu_calls), + onItemClick = Clickable(onClickDescription = stringResource(id = R.string.content_description_select_label)) { + onMuteConversation(MutedConversationStatus.OnlyMentionsAndRepliesAllowed) + }, state = if (mutingConversationState == MutedConversationStatus.OnlyMentionsAndRepliesAllowed) RichMenuItemState.SELECTED else RichMenuItemState.DEFAULT ) @@ -71,8 +73,9 @@ internal fun MutingOptionsSheetContent( SelectableMenuBottomSheetItem( title = stringResource(id = R.string.muting_option_all_muted_title), subLine = stringResource(id = R.string.muting_option_all_muted_text), - onItemClick = Clickable { onMuteConversation(MutedConversationStatus.AllMuted) }, - contentDescription = stringResource(id = R.string.content_description_muting_menu_nothing), + onItemClick = Clickable(onClickDescription = stringResource(id = R.string.content_description_select_label)) { + onMuteConversation(MutedConversationStatus.AllMuted) + }, state = if (mutingConversationState == MutedConversationStatus.AllMuted) RichMenuItemState.SELECTED else RichMenuItemState.DEFAULT ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt index d53c8df9843..8935747d2a5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt @@ -69,9 +69,7 @@ private fun CreateInviteLinkSheetItem( MenuBottomSheetItem( title = title, onItemClick = onClicked, - action = { - ArrowRightIcon() - }, + action = { ArrowRightIcon(contentDescription = R.string.content_description_empty) }, enabled = enabled ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt index d566d61c6eb..31f7a44653e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/EditGuestAccessScreen.kt @@ -37,8 +37,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import com.ramcosta.composedestinations.annotation.RootNavGraph @@ -133,19 +131,14 @@ fun EditGuestAccessScreen( } } item { - val contentDescription = - stringResource(id = R.string.content_description_edit_guests_option_link_header) FolderHeader( name = stringResource(id = R.string.folder_label_guest_link), modifier = Modifier .fillMaxWidth() .background(MaterialTheme.wireColorScheme.background) - .semantics { this.contentDescription = contentDescription } ) } item { - val contentDestination = - stringResource(id = R.string.content_description_edit_guests_option_link_description) Column( modifier = Modifier .fillMaxSize() @@ -156,7 +149,6 @@ fun EditGuestAccessScreen( bottom = dimensions().spacing8x, top = dimensions().spacing8x, ) - .semantics { this.contentDescription = contentDestination } ) { with(editGuestAccessViewModel) { Text( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt index 0a2417ce385..d27783a3324 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/GuestOption.kt @@ -42,9 +42,7 @@ fun GuestOption( isSwitchEnabled -> R.string.conversation_options_guest_description isSwitchVisible -> R.string.conversation_options_guest_not_editable_description else -> null - }, - contentDescriptionRes = R.string.content_description_edit_guests_option, - switcherContentDescriptionRes = R.string.content_description_switch_btn + } ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt index dbf50806c28..95ec6190fd4 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt @@ -35,8 +35,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel @@ -144,25 +142,17 @@ fun SelectableSelfDeletingItem( isSelected: Boolean, onSelfDeletionDurationSelected: (SelfDeletionDuration) -> Unit ) { - val text = duration.longLabel.asString() - val contentDescriptionId = if (isSelected) { - R.string.content_description_selected_suffix - } else { - R.string.content_description_not_selected_suffix - } - val contentDestinationSuffix = stringResource(id = contentDescriptionId) Row( modifier = Modifier .fillMaxWidth() .selectableBackground(isSelected, onClick = { onSelfDeletionDurationSelected(duration) }) .background(color = MaterialTheme.wireColorScheme.surface) .padding(all = MaterialTheme.wireDimensions.spacing16x) - .semantics { contentDescription = "$text$contentDestinationSuffix" } ) { RadioButton(selected = isSelected, onClick = null) HorizontalSpace.x8() Text( - text = text, + text = duration.longLabel.asString(), style = MaterialTheme.wireTypography.body01, color = MaterialTheme.wireColorScheme.onBackground ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt index f160a968038..65352f8c44e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/SelfDeletingMessageOption.kt @@ -36,9 +36,7 @@ fun SelfDeletingMessageOption( onClick = onCheckedChange, isLoading = isLoading, title = R.string.self_deleting_messages_option, - subTitle = R.string.self_deleting_messages_option_description, - contentDescriptionRes = R.string.content_description_conversation_details_self_deleting_option, - switcherContentDescriptionRes = R.string.content_description_switch_btn + subTitle = R.string.self_deleting_messages_option_description ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt index 368318a0a55..83f450185e3 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt @@ -32,8 +32,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import androidx.hilt.navigation.compose.hiltViewModel import com.wire.android.BuildConfig @@ -110,31 +108,20 @@ fun GroupConversationSettings( } if (state.areAccessOptionsAvailable) { item { - val contentDescription = - stringResource(id = R.string.content_description_conversation_details_accesses_header) - FolderHeader( - name = stringResource(R.string.folder_label_access), - modifier = Modifier.semantics { this.contentDescription = contentDescription } - ) + FolderHeader(name = stringResource(R.string.folder_label_access)) } item { - val isOnText = stringResource( - if (state.isGuestAllowed) { - R.string.label_system_message_receipt_mode_on - } else { - R.string.label_system_message_receipt_mode_off - } - ) - val contentDescription = - stringResource(id = R.string.content_description_conversation_details_guests_option, isOnText) GroupConversationOptionsItem( title = stringResource(id = R.string.conversation_options_guests_label), subtitle = stringResource(id = R.string.conversation_details_guest_description), switchState = SwitchState.TextOnly(value = state.isGuestAllowed), arrowType = if (state.isUpdatingGuestAllowed) ArrowType.TITLE_ALIGNED else ArrowType.NONE, - clickable = Clickable(enabled = state.isUpdatingGuestAllowed, onClick = onGuestItemClicked, onLongClick = {}), - contentDescription = contentDescription + clickable = Clickable( + enabled = state.isUpdatingGuestAllowed, + onClick = onGuestItemClicked, + onClickDescription = stringResource(id = R.string.content_description_conversation_details_guests_action) + ), ) } @@ -150,19 +137,11 @@ fun GroupConversationSettings( } } item { - val contentDescription = - stringResource(id = R.string.content_description_conversation_details_messages_header) - FolderHeader( - name = stringResource(id = R.string.folder_label_messaging), - modifier = Modifier.semantics { this.contentDescription = contentDescription } - ) + FolderHeader(name = stringResource(id = R.string.folder_label_messaging)) } if (!state.selfDeletionTimer.isDisabled) { item { - val isOnText = stringResource(R.string.label_system_message_receipt_mode_on) - val contentDescription = - stringResource(R.string.content_description_conversation_details_self_deleting_option, isOnText) GroupConversationOptionsItem( title = stringResource(id = R.string.conversation_options_self_deleting_messages_label), subtitle = stringResource(id = R.string.conversation_options_self_deleting_messages_description), @@ -180,9 +159,8 @@ fun GroupConversationSettings( clickable = Clickable( enabled = state.isUpdatingSelfDeletingAllowed && !state.selfDeletionTimer.isEnforcedByTeam, onClick = onSelfDeletingClicked, - onLongClick = {} - ), - contentDescription = contentDescription + onClickDescription = stringResource(id = R.string.content_description_conversation_details_self_deleting_action) + ) ) } } @@ -246,17 +224,15 @@ private fun GroupNameItem( canBeChanged: Boolean, onClick: () -> Unit = {}, ) { - val contentDescription = - stringResource(id = R.string.content_description_conversation_details_group_name, groupName) GroupConversationOptionsItem( label = stringResource(id = R.string.conversation_details_options_group_name), title = groupName, clickable = Clickable( enabled = canBeChanged, onClick = onClick, - onLongClick = { /* not handled */ }), + onClickDescription = stringResource(id = R.string.content_description_edit_label) + ), arrowType = if (!canBeChanged) ArrowType.NONE else ArrowType.CENTER_ALIGNED, - contentDescription = contentDescription ) HorizontalDivider(thickness = Dp.Hairline, color = MaterialTheme.wireColorScheme.divider) } @@ -285,9 +261,7 @@ private fun ServicesOption( isLoading = isLoading, onClick = onCheckedChange, title = R.string.conversation_options_services_label, - subTitle = if (isSwitchEnabledAndVisible) R.string.conversation_options_services_description else null, - contentDescriptionRes = R.string.content_description_conversation_details_services_option, - switcherContentDescriptionRes = R.string.content_description_switch_btn + subTitle = if (isSwitchEnabledAndVisible) R.string.conversation_options_services_description else null ) } @@ -305,9 +279,7 @@ private fun ReadReceiptOption( isLoading = isLoading, onClick = onCheckedChange, title = R.string.conversation_options_read_receipt_label, - subTitle = R.string.conversation_options_read_receipt_description, - contentDescriptionRes = R.string.content_description_conversation_details_read_receipts_option, - switcherContentDescriptionRes = R.string.content_description_switch_btn + subTitle = R.string.conversation_options_read_receipt_description ) } @@ -320,29 +292,16 @@ fun GroupOptionWithSwitch( onClick: (Boolean) -> Unit, @StringRes title: Int, @StringRes subTitle: Int?, - @StringRes contentDescriptionRes: Int, - @StringRes switcherContentDescriptionRes: Int ) { - val isOnText = stringResource( - if (switchState) R.string.label_system_message_receipt_mode_on else R.string.label_system_message_receipt_mode_off - ) - val contentDescription = stringResource(id = contentDescriptionRes, isOnText) - val switcherContentDescription = stringResource(id = switcherContentDescriptionRes, isOnText) GroupConversationOptionsItem( title = stringResource(id = title), subtitle = subTitle?.let { stringResource(id = it) }, switchState = when { !switchVisible -> SwitchState.TextOnly(value = switchState) - switchClickable && !isLoading -> SwitchState.Enabled( - value = switchState, - onCheckedChange = onClick, - contentDescription = switcherContentDescription - ) - + switchClickable && !isLoading -> SwitchState.Enabled(value = switchState, onCheckedChange = onClick) else -> SwitchState.Disabled(value = switchState) }, - arrowType = ArrowType.NONE, - contentDescription = contentDescription + arrowType = ArrowType.NONE ) HorizontalDivider(thickness = Dp.Hairline, color = MaterialTheme.wireColorScheme.divider) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt index 91760d5f2e5..084a62a3484 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt @@ -34,15 +34,21 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.CustomAccessibilityAction +import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.customActions +import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.wire.android.R import com.wire.android.model.Clickable import com.wire.android.ui.common.ArrowRightIcon import com.wire.android.ui.common.button.WireSecondaryButton import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.home.settings.SettingsOptionSwitch import com.wire.android.ui.home.settings.SwitchState import com.wire.android.ui.theme.wireColorScheme @@ -52,11 +58,12 @@ import com.wire.android.ui.theme.wireTypography @Composable fun GroupConversationOptionsItem( title: String, - clickable: Clickable = Clickable(enabled = false, onClick = { /* not handled */ }, onLongClick = { /* not handled */ }), + clickable: Clickable = Clickable(enabled = false, onClick = { /* not handled */ }), modifier: Modifier = Modifier .fillMaxWidth() .background(MaterialTheme.wireColorScheme.surface) .clickable(clickable) + .clickableDescriptions(clickable) .defaultMinSize(minHeight = MaterialTheme.wireDimensions.conversationOptionsItemMinHeight), subtitle: String? = null, label: String? = null, @@ -130,7 +137,7 @@ private fun ArrowRight() { start = MaterialTheme.wireDimensions.spacing8x, end = MaterialTheme.wireDimensions.spacing8x ) - ) { ArrowRightIcon() } + ) { ArrowRightIcon(contentDescription = R.string.content_description_empty) } } enum class ArrowType { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt index 728011a51c6..e7e86602648 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt @@ -28,8 +28,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.contentDescription -import androidx.compose.ui.semantics.semantics import com.wire.android.BuildConfig import com.wire.android.R import com.wire.android.model.Clickable @@ -70,9 +68,8 @@ fun ConversationParticipantItem( searchQuery: String = String.EMPTY, showRightArrow: Boolean = true ) { - val contentDescription = participantContentDescription(uiParticipant) RowItemTemplate( - modifier = modifier.semantics { this.contentDescription = contentDescription }, + modifier = modifier, leadingIcon = { UserProfileAvatar( avatarData = uiParticipant.avatarData, @@ -139,7 +136,10 @@ fun ConversationParticipantItem( .wrapContentWidth() .padding(end = MaterialTheme.wireDimensions.spacing8x) ) { - ArrowRightIcon(Modifier.align(Alignment.TopEnd)) + ArrowRightIcon( + modifier = Modifier.align(Alignment.TopEnd), + contentDescription = R.string.content_description_empty + ) } } }, @@ -165,28 +165,6 @@ private fun processUsername(uiParticipant: UIParticipant) = when { else -> uiParticipant.handle } -@Composable -private fun participantContentDescription(uiParticipant: UIParticipant): String { - val resId = if (uiParticipant.isSelf) { - R.string.content_description_conversation_details_member_self - } else { - R.string.content_description_conversation_details_member - } - - val membership = uiParticipant.membership.stringResourceId.let { - if (it != -1) stringResource(id = it) else null - } - val mlsVerification = uiParticipant.isMLSVerified.let { - if (it) stringResource(id = R.string.content_description_mls_verified) else null - } - val proteusVerification = uiParticipant.isProteusVerified.let { - if (it) stringResource(id = R.string.content_description_proteus_verified) else null - } - val membershipAndVerificationText = listOfNotNull(membership, mlsVerification, proteusVerification).joinToString(", ") - - return stringResource(id = resId, uiParticipant.name, uiParticipant.handle, membershipAndVerificationText) -} - @PreviewMultipleThemes @Composable fun PreviewGroupConversationParticipantItem() { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt index 4e62a3ead30..3fb74864fa4 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt @@ -35,20 +35,12 @@ fun LazyListScope.participantsFoldersWithElements( folderWithElements( header = context.getString(R.string.conversation_details_group_admins, state.data.allAdminsCount), items = state.data.admins, - onRowItemClicked = onRowItemClicked, - folderContentDescription = context.getString( - R.string.content_description_conversation_details_admins_header, - state.data.allAdminsCount - ) + onRowItemClicked = onRowItemClicked ) folderWithElements( header = context.getString(R.string.conversation_details_group_members, state.data.allParticipantsCount), items = state.data.participants, - onRowItemClicked = onRowItemClicked, - folderContentDescription = context.getString( - R.string.content_description_conversation_details_members_header, - state.data.allAdminsCount - ) + onRowItemClicked = onRowItemClicked ) } @@ -56,8 +48,7 @@ fun LazyListScope.folderWithElements( header: String, items: List, onRowItemClicked: (UIParticipant) -> Unit, - showRightArrow: Boolean = true, - folderContentDescription: String? = null + showRightArrow: Boolean = true ) = folderWithElements( header = header, items = items.associateBy { it.id.toString() }, @@ -69,8 +60,7 @@ fun LazyListScope.folderWithElements( showRightArrow = showRightArrow ) }, - divider = { WireDivider() }, - folderContentDescription = folderContentDescription + divider = { WireDivider() } ) fun LazyListScope.folderWithElements( @@ -90,6 +80,5 @@ fun LazyListScope.folderWithElements( showRightArrow = showRightArrow ) }, - divider = { WireDivider() }, - folderContentDescription = folderContentDescription + divider = { WireDivider() } ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/QuotedMessage.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/QuotedMessage.kt index 308b57ea5c2..dd6d96f1358 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/QuotedMessage.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messages/QuotedMessage.kt @@ -57,6 +57,7 @@ import com.wire.android.model.Clickable import com.wire.android.model.ImageAsset import com.wire.android.ui.common.StatusBox import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.common.colorsScheme import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.typography @@ -226,7 +227,7 @@ private fun QuotedMessageContent( .fillMaxWidth() .height(IntrinsicSize.Min) .let { - if (clickable != null) it.clickable(clickable) else it + if (clickable != null) it.clickable(clickable).clickableDescriptions(clickable) else it } ) { Box(modifier = Modifier.padding(start = dimensions().spacing4x)) { @@ -449,7 +450,7 @@ private fun AutosizeContainer( .fillMaxWidth() .padding(dimensions().spacing8x) .let { - if (clickable != null) it.clickable(clickable) else it + if (clickable != null) it.clickable(clickable).clickableDescriptions(clickable) else it } ) { val (leftSide, rightSide) = createRefs() diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/MessageTypes.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/MessageTypes.kt index e7ea4861962..4e5baac9e9f 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/MessageTypes.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/MessageTypes.kt @@ -44,6 +44,7 @@ import com.wire.android.model.ImageAsset import com.wire.android.ui.common.button.WireButtonState import com.wire.android.ui.common.button.WireSecondaryButton import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.common.dimensions import com.wire.android.ui.home.conversations.CompositeMessageViewModel import com.wire.android.ui.home.conversations.CompositeMessageViewModelImpl @@ -247,6 +248,7 @@ fun MediaAssetImage( ) .wrapContentSize() .clickable(onImageClick) + .clickableDescriptions(onImageClick) ) { when { // Trying to upload the asset diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/location/LocationMessageType.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/location/LocationMessageType.kt index cc0a672699c..c58738d15c0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/location/LocationMessageType.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/location/LocationMessageType.kt @@ -46,6 +46,7 @@ import androidx.compose.ui.unit.sp import com.wire.android.R import com.wire.android.model.Clickable import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.common.dimensions import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions @@ -61,6 +62,7 @@ fun LocationMessageContent( Column( modifier = Modifier .clickable(onLocationClick) + .clickableDescriptions(onLocationClick) .padding(top = dimensions().spacing4x) .clip(shape = RoundedCornerShape(dimensions().messageAssetBorderRadius)) .border( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/RowItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/RowItem.kt index f5ad8749c5d..626ef5f8ca0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/RowItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/RowItem.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.Modifier import com.wire.android.model.Clickable import com.wire.android.ui.common.SurfaceBackgroundWrapper import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.theme.wireDimensions @Composable @@ -46,6 +47,7 @@ fun RowItem( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .clickable(clickable) + .clickableDescriptions(clickable) .then( modifier .defaultMinSize(minHeight = MaterialTheme.wireDimensions.conversationItemRowHeight) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt index 2aaead37c90..2ba3eb27ca5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt @@ -40,6 +40,7 @@ import com.wire.android.navigation.TermsOfUseScreenDestination import com.wire.android.navigation.WireWebsiteScreenDestination import com.wire.android.ui.common.RowItemTemplate import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.common.dimensions import com.wire.android.ui.destinations.AboutThisAppScreenDestination import com.wire.android.ui.destinations.AppSettingsScreenDestination @@ -95,6 +96,7 @@ fun SettingsItem( .defaultMinSize(dimensions().wireIconButtonSize) .padding(end = dimensions().spacing8x) .clickable(onIconPressed) + .clickableDescriptions(onIconPressed) ) } ?: Icons.Filled.ChevronRight }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt index 3f2d41cffd0..a68341f14ac 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsOptionSwitch.kt @@ -58,7 +58,7 @@ fun SettingsOptionSwitch( checked = switchState.value, enabled = switchState is SwitchState.Enabled, onCheckedChange = (switchState as? SwitchState.Enabled)?.onCheckedChange, - contentDescription = (switchState as? SwitchState.Enabled)?.contentDescription + toggleActionDescription = stringResource(id = R.string.content_description_toggle_setting_label) ) } } @@ -76,7 +76,6 @@ sealed class SwitchState { data class Enabled( override val value: Boolean = false, override val isOnOffVisible: Boolean = true, - val contentDescription: String? = null, val onCheckedChange: ((Boolean) -> Unit)? ) : Visible(value = value, isOnOffVisible = isOnOffVisible, isSwitchVisible = true) diff --git a/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt b/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt index 6ecde1d4add..1131a6b75d6 100644 --- a/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt +++ b/app/src/main/kotlin/com/wire/android/util/extension/LazyListScope.kt @@ -25,8 +25,6 @@ import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import com.wire.android.ui.home.conversationslist.common.CollapsingFolderHeader import com.wire.android.ui.home.conversationslist.common.FolderHeader @@ -36,7 +34,6 @@ inline fun LazyListScope.folderWithElements( items: Map, animateItemPlacement: Boolean = true, folderType: FolderType = FolderType.Regular, - folderContentDescription: String? = null, crossinline divider: @Composable () -> Unit = {}, crossinline factory: @Composable (T) -> Unit ) { @@ -52,7 +49,6 @@ inline fun LazyListScope.folderWithElements( name = header, modifier = Modifier .fillMaxWidth() - .semantics { folderContentDescription?.let { contentDescription = it } } .let { if (animateItemPlacement) it.animateItem() else it } ) @@ -60,7 +56,6 @@ inline fun LazyListScope.folderWithElements( name = header, modifier = Modifier .fillMaxWidth() - .semantics { folderContentDescription?.let { contentDescription = it } } .let { if (animateItemPlacement) it.animateItem() else it } ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ac351cf8d8a..5698257f599 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -181,37 +181,19 @@ Location item Conversation details, heading Open conversation options - Options, tab, 1 of 2, double-tap to select - Participants, selected, tab, 2 of 2 + Options + Participants Close conversation details - Add participants - Group admins %d, in list - Group members %d, in list - %1$s, %2$s, %3$s, double tap to open profile - %1$s, you, %2$s, %3$s, double tap to open profile - %s, double-tap to edit - Access, in list - Messaging, in list - Guests, %s, when this is on, people from outside your team can join this conversation, double-tap to adjust guest access - Services, %s, turn this option on to open this conversation to services - Read receipts, %s, when this is on, people can see when their messages in this conversation are read. - Self-deleting messages, %s, when this is on, all messages in this group will disappear after a certain time, double-tap to adjust service access - Guests, %s, turn this option on to open this conversation to people outside your team, even if they don\'t have Wire + adjust guest access + adjust self-deleting time + edit + select + toggle setting Guests, heading Go back to conversation details - Guest link, in list - Invite others with a link to this conversation. Anyone with the link can join the conversation, even if they don’t have Wire. Self-deleting messages, heading Go back to conversation details - Notifications, %s, double tap to open notification settings - Everything, receive notifications for this conversation about everything,including audio and video calls, selected - Calls, mentions and replies, only receive notifications for this conversation when someone calls, mentions you or replies to you, double tap to select - Nothing, receive no notifications for this conversation at all, double tap to select - , selected - , double tab to select - Verified (MLS) - Verified (Proteus) - switch button, %s, double tap to toggle setting + https://medium.com/wire-news/android-updates/home https://medium.com/feed/wire-news/tagged/android diff --git a/core/ui-common/src/main/kotlin/com/wire/android/model/Clickable.kt b/core/ui-common/src/main/kotlin/com/wire/android/model/Clickable.kt index 7e57c836012..af5a24822f6 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/model/Clickable.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/model/Clickable.kt @@ -22,6 +22,8 @@ data class Clickable( val enabled: Boolean = true, val clickBlockParams: ClickBlockParams = ClickBlockParams(), val onLongClick: (() -> Unit)? = null, + val onClickDescription: String? = null, + val onLongClickDescription: String? = null, val onClick: () -> Unit = {} ) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt index 55b4ba6dd17..ee3e78031c6 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt @@ -17,6 +17,7 @@ */ package com.wire.android.ui.common +import android.annotation.SuppressLint import android.widget.Toast import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.combinedClickable @@ -28,6 +29,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.onLongClick +import androidx.compose.ui.semantics.semantics import com.wire.android.model.ClickBlockParams import com.wire.android.model.Clickable import com.wire.android.util.LocalSyncStateObserver @@ -60,16 +64,35 @@ fun rememberClickBlockAction(clickBlockParams: ClickBlockParams, clickAction: () } } +@SuppressLint("ComposeComposableModifier") @OptIn(ExperimentalFoundationApi::class) @Composable fun Modifier.clickable(clickable: Clickable?) = clickable?.let { - val onClick = rememberClickBlockAction(clickable.clickBlockParams, clickable.onClick) - val onLongClick = clickable.onLongClick?.let { onLongClick -> - rememberClickBlockAction(clickable.clickBlockParams, onLongClick) + if (clickable.enabled) { + val onClick = rememberClickBlockAction(clickable.clickBlockParams, clickable.onClick) + val onLongClick = clickable.onLongClick?.let { onLongClick -> + rememberClickBlockAction(clickable.clickBlockParams, onLongClick) + } + this.combinedClickable( + enabled = clickable.enabled, + onClick = onClick, + onLongClick = onLongClick + ) + } else { + // even though element is disabled we want to merge all inner elements into one for TalkBack + this.semantics(mergeDescendants = true) { } + } +} ?: this + +@SuppressLint("ComposeComposableModifier") +@Composable +fun Modifier.clickableDescriptions(clickable: Clickable?) = clickable?.let { + this.semantics { + clickable.onClickDescription?.let { + this@semantics.onClick(it) { true } + } + if (clickable.onLongClick != null) clickable.onLongClickDescription?.let { + this@semantics.onLongClick(it) { true } + } } - this.combinedClickable( - enabled = clickable.enabled, - onClick = onClick, - onLongClick = onLongClick - ) } ?: this diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt index 02e3de30fd1..32a03c17ea6 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt @@ -44,6 +44,7 @@ import androidx.compose.ui.unit.dp import com.wire.android.model.ClickBlockParams import com.wire.android.model.Clickable import com.wire.android.ui.common.clickable +import com.wire.android.ui.common.clickableDescriptions import com.wire.android.ui.common.divider.WireDivider import com.wire.android.ui.theme.wireDimensions import com.wire.android.ui.theme.wireTypography @@ -57,8 +58,7 @@ fun MenuBottomSheetItem( clickBlockParams: ClickBlockParams = ClickBlockParams(), itemProvidedColor: Color = MaterialTheme.colorScheme.secondary, onItemClick: () -> Unit = {}, - enabled: Boolean = true, - contentDescription: String? = null + enabled: Boolean = true ) { CompositionLocalProvider(LocalContentColor provides itemProvidedColor) { val clickable = remember(onItemClick, clickBlockParams) { @@ -74,8 +74,8 @@ fun MenuBottomSheetItem( .defaultMinSize(minHeight = MaterialTheme.wireDimensions.conversationBottomSheetItemHeight) .fillMaxWidth() .clickable(clickable) + .clickableDescriptions(clickable) .padding(MaterialTheme.wireDimensions.conversationBottomSheetItemPadding) - .semantics { this.contentDescription = contentDescription ?: title } ) { if (icon != null) { icon() @@ -117,7 +117,7 @@ fun MenuItemTitle( @Composable fun MenuItemIcon( @DrawableRes id: Int, - contentDescription: String, + contentDescription: String?, size: Dp = MaterialTheme.wireDimensions.wireIconButtonSize, modifier: Modifier = Modifier ) { diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt index 69e75abf57e..eba73bd9a11 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt @@ -18,7 +18,6 @@ package com.wire.android.ui.common.button -import androidx.annotation.StringRes import androidx.compose.animation.Crossfade import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.interaction.MutableInteractionSource @@ -50,9 +49,6 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.layout import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize @@ -92,8 +88,7 @@ fun WireButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - @StringRes contentDescriptionRes: Int? = null + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) { val border = when { borderWidth > 0.dp -> BorderStroke(width = borderWidth, color = colors.outlineColor(state).value) @@ -107,16 +102,12 @@ fun WireButton( disabledContentColor = colors.rippleColor(state).value, ) val onClickWithSyncObserver = rememberClickBlockAction(clickBlockParams, onClick) - val contentDescription = contentDescriptionRes?.let { stringResource(id = it) } ?: text CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides min(minClickableSize.width, minClickableSize.height)) { Button( onClick = onClickWithSyncObserver, modifier = modifier .let { if (fillMaxWidth) it.fillMaxWidth() else it.wrapContentWidth() } .sizeIn(minHeight = minSize.height, minWidth = minSize.width) - .semantics { - contentDescription?.let { this.contentDescription = it } - } .layout { measurable, constraints -> val placeable = measurable.measure(constraints) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt index 0f093b5957d..cc854a4a5d1 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt @@ -18,7 +18,6 @@ package com.wire.android.ui.common.button -import androidx.annotation.StringRes import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -71,8 +70,7 @@ fun WirePrimaryButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - @StringRes contentDescriptionRes: Int? = null + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) = WireButton( onClick = onClick, loading = loading, @@ -93,8 +91,7 @@ fun WirePrimaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, - modifier = modifier, - contentDescriptionRes = contentDescriptionRes + modifier = modifier ) @Preview(name = "Default WirePrimaryButton") diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt index fb46d9782ea..b62ee3198f3 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt @@ -18,7 +18,6 @@ package com.wire.android.ui.common.button -import androidx.annotation.StringRes import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -70,8 +69,7 @@ fun WireSecondaryButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - @StringRes contentDescriptionRes: Int? = null + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } ) = WireButton( onClick = onClick, loading = loading, @@ -92,7 +90,6 @@ fun WireSecondaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, - contentDescriptionRes = contentDescriptionRes, modifier = modifier ) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt index 91e0cc8f4bd..a0fd6deef5d 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/topappbar/WireCenterAlignedTopAppBar.kt @@ -156,8 +156,7 @@ fun WireTopAppBarTitle( }.toDp() } Text( - modifier = Modifier - .width(width), + modifier = Modifier.width(width), text = title, style = style, maxLines = maxLines, From 8a142c5b93c2f01ff2ee712a399fe68cece4256e Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Tue, 15 Oct 2024 17:08:02 +0300 Subject: [PATCH 06/16] Ready for review --- .../ui/authentication/login/LoginScreen.kt | 1 - .../wire/android/ui/common/AppExtensions.kt | 24 ++++++++++++++----- .../android/ui/common/UserProfileAvatar.kt | 5 +++- .../com/wire/android/ui/common/WireSwitch.kt | 1 - .../com/wire/android/ui/common/WireTabRow.kt | 10 +------- .../conversation/HomeSheetContent.kt | 3 ++- .../details/GroupConversationDetailsScreen.kt | 16 +++---------- .../EditSelfDeletingMessagesScreen.kt | 8 +++++++ .../options/GroupConversationOptionsItem.kt | 4 ---- .../ConversationParticipantItem.kt | 1 + .../GroupConversationParticipantList.kt | 10 ++++---- .../media/ConversationMediaScreen.kt | 1 - .../messagedetails/MessageDetailsScreen.kt | 2 -- .../search/SearchUsersAndServicesScreen.kt | 1 - .../other/OtherUserProfileScreen.kt | 1 - app/src/main/res/values/strings.xml | 3 +++ .../com/wire/android/ui/common/Extensions.kt | 8 ++++--- .../common/bottomsheet/MenuBottomSheetItem.kt | 8 +++---- 18 files changed, 55 insertions(+), 52 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt index 8685794ff99..791a58e8727 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt @@ -344,7 +344,6 @@ enum class LoginTabItem(@StringRes val titleResId: Int) : TabItem { EMAIL(R.string.login_tab_email), SSO(R.string.login_tab_sso); override val title: UIText = UIText.StringResource(titleResId) - override val contentDescription: UIText? = null // TODO set contentDescription if needed } @PreviewMultipleThemes diff --git a/app/src/main/kotlin/com/wire/android/ui/common/AppExtensions.kt b/app/src/main/kotlin/com/wire/android/ui/common/AppExtensions.kt index 25ea3fa6722..a74f1028eaa 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/AppExtensions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/AppExtensions.kt @@ -18,7 +18,7 @@ package com.wire.android.ui.common -import androidx.compose.foundation.selection.selectable +import android.annotation.SuppressLint import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -29,13 +29,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.compose.ui.semantics.Role +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.flowWithLifecycle import com.google.accompanist.placeholder.PlaceholderHighlight import com.google.accompanist.placeholder.placeholder import com.google.accompanist.placeholder.shimmer +import com.wire.android.R +import com.wire.android.model.Clickable import com.wire.android.ui.home.conversations.model.messagetypes.asset.UIAssetMessage import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions @@ -53,13 +57,21 @@ import kotlin.coroutines.EmptyCoroutineContext // todo try to move as much as we can to common +@SuppressLint("ComposeComposableModifier") @Composable -fun Modifier.selectableBackground(isSelected: Boolean, onClick: () -> Unit): Modifier = - this.selectable( - selected = isSelected, +fun Modifier.selectableBackground(isSelected: Boolean, onClick: () -> Unit): Modifier { + val onItemClick = Clickable( + enabled = !isSelected, onClick = onClick, - role = Role.Tab + onClickDescription = stringResource(id = R.string.content_description_select_label) ) + val selectedDescription = stringResource(id = R.string.content_description_selected_label) + + return this + .clickable(onItemClick) + .clickableDescriptions(onItemClick) + .semantics { stateDescription = if (isSelected) selectedDescription else "" } +} @Composable fun Modifier.shimmerPlaceholder( diff --git a/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt b/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt index af8e491bbe7..cd8dcf25d38 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/UserProfileAvatar.kt @@ -134,6 +134,7 @@ fun UserProfileAvatar( clickable: Clickable? = null, showPlaceholderIfNoAsset: Boolean = true, withCrossfadeAnimation: Boolean = false, + contentDescription: String? = null, type: UserProfileAvatarType = UserProfileAvatarType.WithIndicators.RegularUser(legalHoldIndicatorVisible = false), ) { Box( @@ -168,6 +169,7 @@ fun UserProfileAvatar( withCrossfadeAnimation = withCrossfadeAnimation, type = type, size = size, + contentDescription = contentDescription, modifier = Modifier .padding(padding) .clip(CircleShape) @@ -225,6 +227,7 @@ private fun UserAvatar( type: UserProfileAvatarType, size: Dp, modifier: Modifier = Modifier, + contentDescription: String? = stringResource(R.string.content_description_user_avatar) ) { if (avatarData.shouldPreferNameBasedAvatar()) { DefaultInitialsAvatar(nameBasedAvatar = avatarData.nameBasedAvatar!!, type = type, size = size, modifier = modifier) @@ -232,7 +235,7 @@ private fun UserAvatar( val painter = painter(avatarData, showPlaceholderIfNoAsset, withCrossfadeAnimation) Image( painter = painter, - contentDescription = stringResource(R.string.content_description_user_avatar), + contentDescription = contentDescription, contentScale = ContentScale.Crop, modifier = modifier, ) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt index f23d6e95aaf..d7aed59b7b9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireSwitch.kt @@ -29,7 +29,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color -import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt index 9d9271d5561..461be78b772 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireTabRow.kt @@ -36,10 +36,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.unit.dp import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireTypography @@ -75,15 +73,10 @@ fun WireTabRow( val text = tabItem.title.asString().let { if (upperCaseTitles) it.uppercase() else it } - val contentDescription = tabItem.contentDescription?.asString() val selectText = stringResource(id = com.wire.android.R.string.content_description_select_label) Tab( - modifier = Modifier.semantics() { - onClick(selectText) { false } - this.contentDescription = "2" - this.stateDescription = "1" - }, + modifier = Modifier.semantics { onClick(selectText) { false } }, enabled = true, text = { Text( @@ -120,5 +113,4 @@ fun PagerState.calculateCurrentTab() = // change the tab if we go over half the interface TabItem { val title: UIText - val contentDescription: UIText? } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt index 5df59dd1cb0..bbeddb7c510 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt @@ -103,7 +103,8 @@ internal fun ConversationMainSheetContent( ) }, action = { NotificationsOptionsItemAction(conversationSheetContent.mutingConversationState) }, - onItemClick = navigateToNotification + onItemClick = navigateToNotification, + onItemClickDescription = stringResource(id = R.string.content_description_open_notification_settings_label) ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt index 2640f2e559d..cfd883d84c1 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt @@ -564,21 +564,11 @@ private fun VerifiedLabel(text: String, color: Color, icon: @Composable RowScope } } -enum class GroupConversationDetailsTabItem( - @StringRes val titleResId: Int, - @StringRes val contentDescriptionResId: Int -) : TabItem { - OPTIONS( - R.string.conversation_details_options_tab, - R.string.content_description_conversation_details_options_tab_header - ), - PARTICIPANTS( - R.string.conversation_details_participants_tab, - R.string.content_description_conversation_details_participants_tab_header - ); +enum class GroupConversationDetailsTabItem(@StringRes val titleResId: Int) : TabItem { + OPTIONS(R.string.conversation_details_options_tab), + PARTICIPANTS(R.string.conversation_details_participants_tab); override val title: UIText = UIText.StringResource(titleResId) - override val contentDescription: UIText? = UIText.StringResource(contentDescriptionResId) } @PreviewMultipleThemes diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt index 95ec6190fd4..e83ce0ce926 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -152,6 +153,7 @@ fun SelectableSelfDeletingItem( RadioButton(selected = isSelected, onClick = null) HorizontalSpace.x8() Text( + modifier = Modifier.align(Alignment.CenterVertically), text = duration.longLabel.asString(), style = MaterialTheme.wireTypography.body01, color = MaterialTheme.wireColorScheme.onBackground @@ -164,3 +166,9 @@ fun SelectableSelfDeletingItem( fun PreviewEditSelfDeletingMessagesScreen() { EditSelfDeletingMessagesScreen(rememberNavigator {}) } + +@Preview +@Composable +fun PreviewSelectableSelfDeletingItem() { + SelectableSelfDeletingItem(SelfDeletionDuration.FiveMinutes, true) { _ -> } +} diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt index 084a62a3484..a7e7d04bdc9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt @@ -34,11 +34,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.semantics.CustomAccessibilityAction -import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.customActions -import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt index e7e86602648..846eedf887a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/ConversationParticipantItem.kt @@ -76,6 +76,7 @@ fun ConversationParticipantItem( modifier = Modifier.padding( start = dimensions().spacing8x ), + contentDescription = null, type = uiParticipant.expiresAt?.let { WithIndicators.TemporaryUser(it) } ?: WithIndicators.RegularUser() ) }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt index 3fb74864fa4..5670e60929c 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipantList.kt @@ -21,6 +21,7 @@ package com.wire.android.ui.home.conversations.details.participants import android.content.Context import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.runtime.remember +import androidx.compose.ui.res.stringResource import com.wire.android.R import com.wire.android.model.Clickable import com.wire.android.ui.common.divider.WireDivider @@ -54,9 +55,10 @@ fun LazyListScope.folderWithElements( items = items.associateBy { it.id.toString() }, animateItemPlacement = false, factory = { + val onClickDescription = stringResource(id = R.string.content_description_open_user_profile_label) ConversationParticipantItem( uiParticipant = it, - clickable = remember { Clickable(enabled = true) { onRowItemClicked(it) } }, + clickable = remember { Clickable(enabled = true, onClickDescription = onClickDescription) { onRowItemClicked(it) } }, showRightArrow = showRightArrow ) }, @@ -67,16 +69,16 @@ fun LazyListScope.folderWithElements( header: String, items: Map, onRowItemClicked: (UIParticipant) -> Unit, - showRightArrow: Boolean = true, - folderContentDescription: String? = null + showRightArrow: Boolean = true ) = folderWithElements( header = header, items = items, animateItemPlacement = false, factory = { + val onClickDescription = stringResource(id = R.string.content_description_open_user_profile_label) ConversationParticipantItem( uiParticipant = it, - clickable = remember { Clickable(enabled = true) { onRowItemClicked(it) } }, + clickable = remember { Clickable(enabled = true, onClickDescription = onClickDescription) { onRowItemClicked(it) } }, showRightArrow = showRightArrow ) }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt index 9bc4c1ce858..3b1b37b8c1a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaScreen.kt @@ -271,7 +271,6 @@ enum class ConversationMediaScreenTabItem(@StringRes val titleResId: Int) : TabI FILES(R.string.label_conversation_files); override val title: UIText = UIText.StringResource(titleResId) - override val contentDescription: UIText? = null // TODO set contentDescription if needed } data class AssetOptionsData(val messageId: String, val isMyMessage: Boolean) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt index 125034a9c9e..ee1249089b0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/messagedetails/MessageDetailsScreen.kt @@ -184,6 +184,4 @@ sealed class MessageDetailsTabItem(@StringRes val titleResId: Int, argument: Str data class Reactions(val count: Int) : MessageDetailsTabItem(R.string.message_details_reactions_tab, "$count") data class ReadReceipts(val count: Int) : MessageDetailsTabItem(R.string.message_details_read_receipts_tab, "$count") - - override val contentDescription: UIText? = null // TODO set contentDescription if needed } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt index 2aaed55f2f4..e78efd42179 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt @@ -221,7 +221,6 @@ enum class SearchPeopleTabItem(@StringRes val titleResId: Int) : TabItem { PEOPLE(R.string.label_add_member_people), SERVICES(R.string.label_add_member_services); override val title: UIText = UIText.StringResource(titleResId) - override val contentDescription: UIText? = null // TODO set contentDescription if needed } enum class SearchPeopleScreenType { diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index bc2cb2760bf..1c84f02bb15 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -597,7 +597,6 @@ enum class OtherUserProfileTabItem(@StringRes val titleResId: Int) : TabItem { DEVICES(R.string.user_profile_devices_tab); override val title: UIText = UIText.StringResource(titleResId) - override val contentDescription: UIText? = null // TODO set contentDescription if needed } @OptIn(ExperimentalMaterial3Api::class) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 00a2a602658..1922d478e8b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -188,11 +188,14 @@ adjust self-deleting time edit select + selected toggle setting Guests, heading Go back to conversation details Self-deleting messages, heading Go back to conversation details + open profile + open notification settings https://medium.com/wire-news/android-updates/home diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt index ee3e78031c6..5fd000a2e11 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt @@ -80,13 +80,13 @@ fun Modifier.clickable(clickable: Clickable?) = clickable?.let { ) } else { // even though element is disabled we want to merge all inner elements into one for TalkBack - this.semantics(mergeDescendants = true) { } + this.semantics(mergeDescendants = true) { } } } ?: this @SuppressLint("ComposeComposableModifier") @Composable -fun Modifier.clickableDescriptions(clickable: Clickable?) = clickable?.let { +fun Modifier.clickableDescriptions(clickable: Clickable?) = if (clickable?.enabled == true) { this.semantics { clickable.onClickDescription?.let { this@semantics.onClick(it) { true } @@ -95,4 +95,6 @@ fun Modifier.clickableDescriptions(clickable: Clickable?) = clickable?.let { this@semantics.onLongClick(it) { true } } } -} ?: this +} else { + this +} diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt index 32a03c17ea6..cb8964dea84 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt @@ -37,8 +37,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.wire.android.model.ClickBlockParams @@ -58,14 +56,16 @@ fun MenuBottomSheetItem( clickBlockParams: ClickBlockParams = ClickBlockParams(), itemProvidedColor: Color = MaterialTheme.colorScheme.secondary, onItemClick: () -> Unit = {}, - enabled: Boolean = true + enabled: Boolean = true, + onItemClickDescription: String? = null ) { CompositionLocalProvider(LocalContentColor provides itemProvidedColor) { val clickable = remember(onItemClick, clickBlockParams) { Clickable( clickBlockParams = clickBlockParams, onClick = onItemClick, - enabled = enabled + enabled = enabled, + onClickDescription = onItemClickDescription ) } Row( From 9e2d180a4d722d8941e344a50d26f2ca9eabc311 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Tue, 15 Oct 2024 17:58:19 +0300 Subject: [PATCH 07/16] Code style fix --- .../ui/common/bottomsheet/RichMenuBottomSheetItem.kt | 2 -- .../ui/common/bottomsheet/conversation/HomeSheetContent.kt | 3 ++- .../main/kotlin/com/wire/android/ui/common/Extensions.kt | 6 ++++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt index 8b8fee6caaf..9e78f99f669 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/RichMenuBottomSheetItem.kt @@ -33,8 +33,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import com.wire.android.R diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt index bbeddb7c510..12695e96b22 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt @@ -159,7 +159,8 @@ internal fun ConversationMainSheetContent( ) ) } - }) + } + ) } add { MenuBottomSheetItem( diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt index 5fd000a2e11..b7c71205cc8 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt @@ -91,8 +91,10 @@ fun Modifier.clickableDescriptions(clickable: Clickable?) = if (clickable?.enabl clickable.onClickDescription?.let { this@semantics.onClick(it) { true } } - if (clickable.onLongClick != null) clickable.onLongClickDescription?.let { - this@semantics.onLongClick(it) { true } + if (clickable.onLongClick != null) { + clickable.onLongClickDescription?.let { + this@semantics.onLongClick(it) { true } + } } } } else { From abd929cc7bf32758df46397b7f7b1b778d1a274d Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 16 Oct 2024 11:19:06 +0300 Subject: [PATCH 08/16] Lint fixes --- .../src/main/kotlin/com/wire/android/ui/common/Extensions.kt | 2 +- .../wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt index b7c71205cc8..a428e3f9c7a 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/Extensions.kt @@ -84,7 +84,7 @@ fun Modifier.clickable(clickable: Clickable?) = clickable?.let { } } ?: this -@SuppressLint("ComposeComposableModifier") +@SuppressLint("ComposeComposableModifier", "ComposeModifierWithoutDefault") @Composable fun Modifier.clickableDescriptions(clickable: Clickable?) = if (clickable?.enabled == true) { this.semantics { diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt index cb8964dea84..53ad19e1a2b 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/bottomsheet/MenuBottomSheetItem.kt @@ -118,8 +118,8 @@ fun MenuItemTitle( fun MenuItemIcon( @DrawableRes id: Int, contentDescription: String?, - size: Dp = MaterialTheme.wireDimensions.wireIconButtonSize, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + size: Dp = MaterialTheme.wireDimensions.wireIconButtonSize ) { Icon( painter = painterResource(id = id), From 9fb946e5bcfb0844d2b3088d7b4f92361418e8a6 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 16 Oct 2024 12:04:55 +0300 Subject: [PATCH 09/16] Reverted useles changes --- .../details/options/GroupConversationOptions.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt index 83f450185e3..d6364f9bc65 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptions.kt @@ -107,9 +107,7 @@ fun GroupConversationSettings( ) } if (state.areAccessOptionsAvailable) { - item { - FolderHeader(name = stringResource(R.string.folder_label_access)) - } + item { FolderHeader(name = stringResource(R.string.folder_label_access)) } item { GroupConversationOptionsItem( @@ -136,9 +134,7 @@ fun GroupConversationSettings( ) } } - item { - FolderHeader(name = stringResource(id = R.string.folder_label_messaging)) - } + item { FolderHeader(name = stringResource(id = R.string.folder_label_messaging)) } if (!state.selfDeletionTimer.isDisabled) { item { From 907ec522453f54605c95d1e3332eea8157998bbb Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 16 Oct 2024 12:17:17 +0300 Subject: [PATCH 10/16] Fixed lint again --- .../details/options/GroupConversationOptionsItem.kt | 9 ++++----- .../newconversation/groupOptions/GroupOptionsScreen.kt | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt index a7e7d04bdc9..7a39282235a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/options/GroupConversationOptionsItem.kt @@ -54,13 +54,11 @@ import com.wire.android.ui.theme.wireTypography @Composable fun GroupConversationOptionsItem( title: String, - clickable: Clickable = Clickable(enabled = false, onClick = { /* not handled */ }), modifier: Modifier = Modifier .fillMaxWidth() .background(MaterialTheme.wireColorScheme.surface) - .clickable(clickable) - .clickableDescriptions(clickable) .defaultMinSize(minHeight = MaterialTheme.wireDimensions.conversationOptionsItemMinHeight), + clickable: Clickable = Clickable(enabled = false, onClick = { /* not handled */ }), subtitle: String? = null, label: String? = null, trailingOnText: String? = null, @@ -74,6 +72,8 @@ fun GroupConversationOptionsItem( Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier + .clickable(clickable) + .clickableDescriptions(clickable) .semantics { contentDescription?.let { this.contentDescription = contentDescription } } .padding( top = MaterialTheme.wireDimensions.spacing12x, @@ -83,8 +83,7 @@ fun GroupConversationOptionsItem( ) ) { Column( - modifier = Modifier - .weight(1f) + modifier = Modifier.weight(1f) ) { if (label != null) { Text( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/groupOptions/GroupOptionsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/groupOptions/GroupOptionsScreen.kt index 1755ccdfc0e..c15e2200ba0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/groupOptions/GroupOptionsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/groupOptions/GroupOptionsScreen.kt @@ -172,7 +172,7 @@ private fun GroupOptionState.ReadReceiptsOptions(onReadReceiptChanged: (Boolean) isOnOffVisible = false, onCheckedChange = { onReadReceiptChanged.invoke(it) }), arrowType = ArrowType.NONE, - clickable = Clickable(enabled = false, onClick = {}, onLongClick = {}), + clickable = Clickable(enabled = false, onClick = {}), modifier = Modifier .fillMaxWidth() .background(MaterialTheme.colorScheme.surface) @@ -198,7 +198,7 @@ private fun GroupOptionState.AllowServicesOptions(onAllowServicesChanged: (Boole isOnOffVisible = false, onCheckedChange = { onAllowServicesChanged.invoke(it) }), arrowType = ArrowType.NONE, - clickable = Clickable(enabled = false, onClick = {}, onLongClick = {}), + clickable = Clickable(enabled = false, onClick = {}), modifier = Modifier .fillMaxWidth() .background(MaterialTheme.colorScheme.surface) @@ -222,7 +222,7 @@ private fun GroupOptionState.AllowGuestsOptions(onAllowGuestChanged: (Boolean) - isOnOffVisible = false, onCheckedChange = { onAllowGuestChanged.invoke(it) }), arrowType = ArrowType.NONE, - clickable = Clickable(enabled = false, onClick = {}, onLongClick = {}), + clickable = Clickable(enabled = false, onClick = {}), modifier = Modifier.background(MaterialTheme.colorScheme.surface) ) From 22bae6f2b53e755b07566fcae2555532e2996a00 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 16 Oct 2024 12:43:24 +0300 Subject: [PATCH 11/16] Fixed lint again again --- .../main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt b/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt index f925bdeff07..550b3179160 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/MoreOptionIcon.kt @@ -28,9 +28,9 @@ import com.wire.android.ui.common.button.WireSecondaryIconButton @Composable fun MoreOptionIcon( onButtonClicked: () -> Unit, + modifier: Modifier = Modifier, state: WireButtonState = WireButtonState.Default, - @StringRes contentDescription: Int = R.string.content_description_show_more_options, - modifier: Modifier = Modifier + @StringRes contentDescription: Int = R.string.content_description_show_more_options ) { WireSecondaryIconButton( onButtonClicked = onButtonClicked, From b97790441e36c04080747eb2096c5aa08d21fde3 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Thu, 17 Oct 2024 12:20:12 +0300 Subject: [PATCH 12/16] feat: Add Accessability strings to OtherUserProfile --- .../other/OtherUserProfileGroup.kt | 2 +- .../other/OtherUserProfileScreen.kt | 23 +++++++++++-------- app/src/main/res/values/strings.xml | 4 ++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt index ec311425034..99223358fcd 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt @@ -167,7 +167,7 @@ fun EditButton(onEditClicked: () -> Unit, modifier: Modifier = Modifier) { WireSecondaryIconButton( onButtonClicked = onEditClicked, iconResource = R.drawable.ic_edit, - contentDescription = R.string.content_description_edit, + contentDescription = R.string.content_description_user_profile_edit_role_btn, modifier = modifier ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index 1c84f02bb15..cfebe4568ce 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -84,6 +84,7 @@ import com.wire.android.ui.common.snackbar.LocalSnackbarHostState import com.wire.android.ui.common.spacers.VerticalSpace import com.wire.android.ui.common.topappbar.NavigationIconType import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar +import com.wire.android.ui.common.topappbar.WireTopAppBarTitle import com.wire.android.ui.common.visbility.rememberVisibilityState import com.wire.android.ui.connection.ConnectionActionButton import com.wire.android.ui.destinations.ConversationMediaScreenDestination @@ -98,6 +99,7 @@ import com.wire.android.ui.legalhold.banner.LegalHoldSubjectBanner import com.wire.android.ui.legalhold.dialog.subject.LegalHoldSubjectProfileDialog import com.wire.android.ui.theme.WireTheme import com.wire.android.ui.theme.wireColorScheme +import com.wire.android.ui.theme.wireTypography import com.wire.android.ui.userprofile.common.EditableState import com.wire.android.ui.userprofile.common.UserProfileInfo import com.wire.android.ui.userprofile.group.RemoveConversationMemberState @@ -193,7 +195,6 @@ fun OtherUserProfileScreen( }, onSearchConversationMessagesClick = onSearchConversationMessagesClick, navigateBack = navigator::navigateBack, - navigationIconType = NavigationIconType.Close(), onConversationMediaClick = onConversationMediaClick, onLegalHoldLearnMoreClick = remember { { legalHoldSubjectDialogState.show(Unit) } }, ) @@ -222,7 +223,6 @@ fun OtherUserProfileScreen( fun OtherProfileScreenContent( scope: CoroutineScope, state: OtherUserProfileState, - navigationIconType: NavigationIconType, requestInProgress: Boolean, sheetState: WireModalSheetState, openBottomSheet: () -> Unit, @@ -299,7 +299,6 @@ fun OtherProfileScreenContent( topBarHeader = { TopBarHeader( state = state, - navigationIconType = navigationIconType, elevation = dimensions().spacing0x, // CollapsingTopBarScaffold already manages elevation onNavigateBack = navigateBack, openConversationBottomSheet = openConversationBottomSheet @@ -393,19 +392,29 @@ fun OtherProfileScreenContent( @Composable private fun TopBarHeader( state: OtherUserProfileState, - navigationIconType: NavigationIconType, elevation: Dp, onNavigateBack: () -> Unit, openConversationBottomSheet: () -> Unit ) { + val navigationIconType = if (state.groupState == null) NavigationIconType.Close() + else NavigationIconType.Close(R.string.content_description_user_profile_close_btn) + WireCenterAlignedTopAppBar( onNavigationPressed = onNavigateBack, navigationIconType = navigationIconType, - title = stringResource(id = R.string.user_profile_title), + titleContent = { + WireTopAppBarTitle( + title = stringResource(id = R.string.user_profile_title), + style = MaterialTheme.wireTypography.title01, + maxLines = 2, + contentDescription = stringResource(id = R.string.content_description_user_profile_heading) + ) + }, elevation = elevation, actions = { if (state.conversationSheetContent != null) { MoreOptionIcon( + contentDescription = R.string.content_description_user_profile_more_btn, onButtonClicked = openConversationBottomSheet, state = if (state.isMetadataEmpty()) WireButtonState.Disabled else WireButtonState.Default ) @@ -610,7 +619,6 @@ fun PreviewOtherProfileScreenGroupMemberContent() { connectionState = ConnectionState.ACCEPTED, isUnderLegalHold = true, ), - navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, @@ -634,7 +642,6 @@ fun PreviewOtherProfileScreenContent() { isUnderLegalHold = true, groupState = null ), - navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, @@ -657,7 +664,6 @@ fun PreviewOtherProfileScreenContentNotConnected() { connectionState = ConnectionState.CANCELLED, isUnderLegalHold = true, ), - navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, @@ -682,7 +688,6 @@ fun PreviewOtherProfileScreenTempUser() { isUnderLegalHold = true, expiresAt = Instant.DISTANT_FUTURE ), - navigationIconType = NavigationIconType.Back(), requestInProgress = false, sheetState = rememberWireModalSheetState(), openBottomSheet = {}, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1922d478e8b..3a1b9657746 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -186,6 +186,10 @@ Close conversation details adjust guest access adjust self-deleting time + User Profile, heading + Open conversation options + Go back to conversation details + Edit role edit select selected From 80d2c740d1d2b1ca0df1b8dc9cbeec05a6fd785d Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Mon, 21 Oct 2024 12:25:51 +0300 Subject: [PATCH 13/16] feat: Add Accessability strings to OtherUserProfile: ready for review --- .../ui/authentication/devices/DeviceItem.kt | 12 +++++- .../com/wire/android/ui/common/CopyButton.kt | 8 ++-- .../com/wire/android/ui/common/SearchBar.kt | 6 ++- .../ui/common/textfield/WireTextField.kt | 2 + .../common/textfield/WireTextFieldLayout.kt | 10 +++-- .../common/topappbar/search/SearchTopBar.kt | 8 +++- .../media/ConversationMediaButton.kt | 5 ++- .../search/InternalContactSearchResultItem.kt | 39 ++++++++++++------- .../search/SearchAllPeopleScreen.kt | 18 ++++++--- .../search/SearchAllServicesScreen.kt | 4 +- .../search/SearchUsersAndServicesScreen.kt | 9 ++++- .../SearchConversationMessagesButton.kt | 5 ++- .../conversationslist/common/FolderHeader.kt | 13 +++++-- .../ui/settings/devices/SelfDevicesScreen.kt | 2 +- .../other/OtherUserDevicesScreen.kt | 2 +- .../other/OtherUserProfileDetails.kt | 22 ++++++++--- .../wire/android/util/ui/StyledStringUtil.kt | 20 +++++++--- app/src/main/res/values/strings.xml | 13 +++++++ .../android/ui/common/button/WireButton.kt | 8 +++- .../ui/common/button/WirePrimaryButton.kt | 6 ++- .../ui/common/button/WireSecondaryButton.kt | 6 ++- .../ui/common/button/WireTertiaryButton.kt | 6 ++- 22 files changed, 163 insertions(+), 61 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt index 8a23a1b86b7..afccc77eb5a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt @@ -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 @@ -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 @@ -109,6 +113,9 @@ private fun DeviceItemContent( onClickAction?.invoke(device) } } + .semantics { + if (isWholeItemClickable) onClick(openDetailsDescription) { false } + } ) { Row( modifier = Modifier @@ -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, @@ -199,7 +206,8 @@ private fun ColumnScope.DeviceItemTexts( ProteusVerifiedIcon( Modifier .wrapContentWidth() - .align(Alignment.CenterVertically)) + .align(Alignment.CenterVertically) + ) } } } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt b/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt index 4bcb2aa4e87..b284bac942e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt @@ -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 @@ -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? = null, + state: WireButtonState = WireButtonState.Default ) { WireSecondaryIconButton( onButtonClicked = onCopyClicked, iconResource = R.drawable.ic_copy, - contentDescription = R.string.content_description_copy, + contentDescription = contentDescription ?: R.string.content_description_copy, state = state, modifier = modifier ) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt b/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt index 527eb74113e..41ee41453a7 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt @@ -40,6 +40,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.sp import com.wire.android.R @@ -59,7 +61,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( @@ -108,6 +111,7 @@ fun SearchBarInput( placeholderAlignment = placeholderAlignment, placeholderText = placeholderText, lineLimits = TextFieldLineLimits.SingleLine, + semanticDescription = semanticDescription ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt index 1c6234ea6ac..0bf843388d9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt @@ -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, @@ -115,6 +116,7 @@ internal fun WireTextField( labelText = labelText, labelMandatoryIcon = labelMandatoryIcon, descriptionText = descriptionText, + semanticDescription = semanticDescription, leadingIcon = leadingIcon, trailingIcon = trailingIcon, state = state, diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt index 8d5b12612d2..883415bbaee 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt @@ -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 @@ -65,6 +66,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, @@ -101,8 +103,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 { contentDescription = it } } @@ -178,7 +180,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( diff --git a/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt b/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt index d098338d0e0..75dd1934b87 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt @@ -56,6 +56,8 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import com.wire.android.R import com.wire.android.ui.common.SearchBarInput @@ -71,6 +73,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 = {} @@ -107,6 +110,7 @@ fun SearchTopBar( SearchBarInput( placeholderText = searchBarHint, + semanticDescription = searchBarDescription, textState = searchQueryTextState, isLoading = isLoading, leadingIcon = { @@ -118,7 +122,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, ) } @@ -129,7 +133,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, ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaButton.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaButton.kt index 0ba31e94ebc..d04d6a3ee70 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaButton.kt @@ -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) ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/InternalContactSearchResultItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/InternalContactSearchResultItem.kt index d0dad094d0b..1109bb6a272 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/InternalContactSearchResultItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/InternalContactSearchResultItem.kt @@ -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 @@ -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) { @@ -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 + } ) } @@ -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") } @@ -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 { @@ -200,7 +211,7 @@ fun PreviewInternalContactSearchResultItemClickable() = WireTheme { membership = Membership.None, searchQuery = "", connectionState = ConnectionState.ACCEPTED, - onCheckChange = {}, + onCheckClickable = Clickable {}, isSelected = false, clickable = Clickable {}, actionType = ItemActionType.CLICK, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt index d9cff9e3617..87a8427dcd9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt @@ -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 @@ -287,7 +287,14 @@ 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, @@ -296,9 +303,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) } } ) } } @@ -344,6 +351,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), @@ -352,7 +360,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) } } ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt index 50885b115a9..a9d0a1aafec 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt @@ -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 @@ -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 { @@ -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) ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt index e78efd42179..bcfd4e52bdd 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt @@ -114,11 +114,14 @@ fun SearchUsersAndServicesScreen( elevation = dimensions().spacing0x, // CollapsingTopBarScaffold already manages elevation title = searchTitle, navigationIconType = when (screenType) { - SearchPeopleScreenType.CONVERSATION_DETAILS -> NavigationIconType.Close() + SearchPeopleScreenType.CONVERSATION_DETAILS -> + NavigationIconType.Close(R.string.content_description_add_participants_close) + SearchPeopleScreenType.NEW_CONVERSATION -> NavigationIconType.Close() SearchPeopleScreenType.NEW_GROUP_CONVERSATION -> NavigationIconType.Back() }, - onNavigationPressed = onClose + onNavigationPressed = onClose, + titleContentDescription = stringResource(id = R.string.content_description_add_participants_heading) ) } } @@ -127,6 +130,7 @@ fun SearchUsersAndServicesScreen( SearchTopBar( isSearchActive = searchBarState.isSearchActive, searchBarHint = stringResource(R.string.label_search_people), + searchBarDescription = stringResource(R.string.content_description_add_participants_search_field), searchQueryTextState = searchBarState.searchQueryTextState, onActiveChanged = searchBarState::searchActiveChanged, ) @@ -220,6 +224,7 @@ fun SearchUsersAndServicesScreen( enum class SearchPeopleTabItem(@StringRes val titleResId: Int) : TabItem { PEOPLE(R.string.label_add_member_people), SERVICES(R.string.label_add_member_services); + override val title: UIText = UIText.StringResource(titleResId) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/messages/SearchConversationMessagesButton.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/messages/SearchConversationMessagesButton.kt index 4acbd545072..46f970d62be 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/messages/SearchConversationMessagesButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/messages/SearchConversationMessagesButton.kt @@ -58,10 +58,11 @@ private fun SearchConversationMessagesButtonContent( leadingIcon = { Icon( painter = painterResource(id = R.drawable.ic_search), - contentDescription = stringResource(R.string.label_search_messages), + contentDescription = null, tint = MaterialTheme.colorScheme.onBackground, modifier = Modifier.padding(end = dimensions().spacing8x) ) - } + }, + onClickDescription = stringResource(id = R.string.content_description_search_text_in_conversation_btn) ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt index 33d29e86937..8338308afbc 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt @@ -35,6 +35,8 @@ import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.vector.ImageVector 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.R @@ -66,17 +68,20 @@ fun CollapsingFolderHeader( arrowHorizontalPadding: Dp = dimensions().avatarClickablePadding, ) { val arrowRotation: Float by animateFloatAsState(if (expanded) 180f else 90f, label = "CollapsingArrowRotationAnimation") + val expandDescription = stringResource( + id = if (expanded) R.string.content_description_collapse_label + else R.string.content_description_expand_label + ) Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier - .clickable { - onClicked(!expanded) - } + .semantics { onClick(expandDescription) { false } } + .clickable { onClicked(!expanded) } .padding(horizontal = dimensions().spacing8x, vertical = dimensions().spacing16x) ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_collapse), - contentDescription = stringResource(R.string.change), + contentDescription = null, tint = MaterialTheme.wireColorScheme.labelText, modifier = Modifier .padding(horizontal = arrowHorizontalPadding) diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesScreen.kt index f7845dd9102..bda1155ac22 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesScreen.kt @@ -159,7 +159,7 @@ private fun LazyListScope.folderDeviceItems( .background(MaterialTheme.wireColorScheme.surface), placeholder = placeholders, onClickAction = onDeviceClick, - icon = { ArrowRightIcon() }, + icon = { ArrowRightIcon(contentDescription = R.string.content_description_empty) }, isWholeItemClickable = true, shouldShowVerifyLabel = shouldShowVerifyLabel, isCurrentClient = isCurrentClient, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt index 4c1b655bf24..46eb1fda5c5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt @@ -119,7 +119,7 @@ private fun OtherUserDevicesContent( modifier = Modifier.background(MaterialTheme.wireColorScheme.surface), isWholeItemClickable = true, onClickAction = onDeviceClick, - icon = { ArrowRightIcon() }, + icon = { ArrowRightIcon(contentDescription = R.string.content_description_empty) }, shouldShowVerifyLabel = true, shouldShowE2EIInfo = item.mlsClientIdentity != null ) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt index 4adeb4c5c02..7f462f73b5f 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt @@ -18,6 +18,7 @@ package com.wire.android.ui.userprofile.other +import androidx.annotation.StringRes import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn @@ -53,7 +54,8 @@ fun OtherUserProfileDetails( UserDetailInformation( title = stringResource(R.string.settings_myaccount_domain), value = state.userId.domain, - onCopy = null + onCopy = null, + copyBtnContentDescription = null ) } if (state.email.isNotEmpty()) { @@ -61,7 +63,8 @@ fun OtherUserProfileDetails( UserDetailInformation( title = stringResource(R.string.email_label), value = state.email, - onCopy = { otherUserProfileScreenState.copy(it, context) } + onCopy = { otherUserProfileScreenState.copy(it, context) }, + copyBtnContentDescription = R.string.content_description_user_profile_copy_email_btn ) } } @@ -70,7 +73,8 @@ fun OtherUserProfileDetails( UserDetailInformation( title = stringResource(R.string.phone_label), value = state.phone, - onCopy = { otherUserProfileScreenState.copy(it, context) } + onCopy = { otherUserProfileScreenState.copy(it, context) }, + copyBtnContentDescription = R.string.content_description_user_profile_copy_phone_btn ) } } @@ -81,7 +85,8 @@ fun OtherUserProfileDetails( private fun UserDetailInformation( title: String, value: String, - onCopy: ((String) -> Unit)? + onCopy: ((String) -> Unit)?, + @StringRes copyBtnContentDescription: Int? ) { RowItemTemplate( modifier = Modifier.padding(horizontal = dimensions().spacing8x), @@ -99,7 +104,14 @@ private fun UserDetailInformation( text = value ) }, - actions = { onCopy?.let { CopyButton(onCopyClicked = { onCopy(value) }) } }, + actions = { + onCopy?.let { + CopyButton( + onCopyClicked = { onCopy(value) }, + contentDescription = copyBtnContentDescription + ) + } + }, clickable = Clickable(enabled = false) {} ) } diff --git a/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt b/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt index 38bd19d142d..f8f6c0dd7a8 100644 --- a/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt +++ b/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt @@ -27,10 +27,15 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.LinkAnnotation import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.UrlAnnotation import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withAnnotation +import androidx.compose.ui.text.withLink import androidx.compose.ui.text.withStyle import androidx.core.text.bold import androidx.core.text.buildSpannedString @@ -165,11 +170,16 @@ private fun createAnnotatedString(data: List): AnnotatedString { tag = linkTextData.tag, annotation = linkTextData.annotation, ) - withStyle( - style = SpanStyle( - color = MaterialTheme.wireColorScheme.primary, - textDecoration = TextDecoration.Underline, - ), + withLink( + LinkAnnotation.Url( + linkTextData.annotation, + TextLinkStyles( + style = SpanStyle( + color = MaterialTheme.wireColorScheme.primary, + textDecoration = TextDecoration.Underline, + ) + ) + ) ) { append(linkTextData.text) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3a1b9657746..c8e0c25b055 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -190,8 +190,20 @@ Open conversation options Go back to conversation details Edit role + Copy phone + Copy email + open device details + Search text messages + Open overview of pictures and files + Add participant, heading + Close add partipants view + Search people by name or username + Go back to add participants view + collapse + expand edit select + unselect selected toggle setting Guests, heading @@ -199,6 +211,7 @@ Self-deleting messages, heading Go back to conversation details open profile + open service open notification settings diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt index eba73bd9a11..00b8e95b805 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireButton.kt @@ -49,6 +49,8 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.layout import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize @@ -88,7 +90,8 @@ fun WireButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + onClickDescription: String? = null ) { val border = when { borderWidth > 0.dp -> BorderStroke(width = borderWidth, color = colors.outlineColor(state).value) @@ -120,7 +123,8 @@ fun WireButton( val centerY = ((height - placeable.height) / 2f).roundToInt() placeable.place(centerX, centerY) } - }, + } + .semantics { onClickDescription?.let { onClick(it) { false } } }, enabled = state != WireButtonState.Disabled, interactionSource = interactionSource, elevation = elevation, diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt index cc854a4a5d1..48b08791764 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WirePrimaryButton.kt @@ -70,7 +70,8 @@ fun WirePrimaryButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + onClickDescription: String? = null ) = WireButton( onClick = onClick, loading = loading, @@ -91,7 +92,8 @@ fun WirePrimaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, - modifier = modifier + modifier = modifier, + onClickDescription = onClickDescription ) @Preview(name = "Default WirePrimaryButton") diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt index b62ee3198f3..4045fa2d517 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireSecondaryButton.kt @@ -69,7 +69,8 @@ fun WireSecondaryButton( horizontal = MaterialTheme.wireDimensions.buttonHorizontalContentPadding, vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + onClickDescription: String? = null ) = WireButton( onClick = onClick, loading = loading, @@ -90,7 +91,8 @@ fun WireSecondaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, - modifier = modifier + modifier = modifier, + onClickDescription = onClickDescription ) @Preview(name = "Default WireSecondaryButton") diff --git a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireTertiaryButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireTertiaryButton.kt index 9f341a2b4ab..bcd77ea67bb 100644 --- a/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireTertiaryButton.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/WireTertiaryButton.kt @@ -44,6 +44,7 @@ import com.wire.android.ui.theme.wireTypography @Composable fun WireTertiaryButton( onClick: () -> Unit, + modifier: Modifier = Modifier, loading: Boolean = false, leadingIcon: @Composable (() -> Unit)? = null, leadingIconAlignment: IconAlignment = IconAlignment.Center, @@ -65,7 +66,7 @@ fun WireTertiaryButton( vertical = MaterialTheme.wireDimensions.buttonVerticalContentPadding ), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - modifier: Modifier = Modifier, + onClickDescription: String? = null ) = WireButton( onClick = onClick, loading = loading, @@ -86,7 +87,8 @@ fun WireTertiaryButton( borderWidth = borderWidth, contentPadding = contentPadding, interactionSource = interactionSource, - modifier = modifier + modifier = modifier, + onClickDescription = onClickDescription ) @Preview(name = "Default WireSecondaryButton") From a09199a48408fdb671671b63067239de893eadda Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Tue, 22 Oct 2024 11:51:48 +0300 Subject: [PATCH 14/16] Fixed code style --- .../main/kotlin/com/wire/android/ui/common/SearchBar.kt | 2 -- .../android/ui/common/topappbar/search/SearchTopBar.kt | 2 -- .../ui/home/conversations/search/SearchAllPeopleScreen.kt | 3 +-- .../ui/home/conversationslist/common/FolderHeader.kt | 3 +-- .../android/ui/userprofile/other/OtherUserProfileScreen.kt | 7 +++++-- .../kotlin/com/wire/android/util/ui/StyledStringUtil.kt | 2 -- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt b/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt index 41ee41453a7..241cf8b59fe 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt @@ -40,8 +40,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.sp import com.wire.android.R diff --git a/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt b/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt index 75dd1934b87..123a72f9995 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt @@ -56,8 +56,6 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.onClick -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import com.wire.android.R import com.wire.android.ui.common.SearchBarInput diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt index 87a8427dcd9..a1f22068e10 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt @@ -288,8 +288,7 @@ private fun LazyListScope.internalSuccessItem( ) { (contact, isSelected) -> with(contact) { val onCheckDescription = stringResource( - id = if (isSelected) R.string.content_description_unselect_label - else R.string.content_description_select_label + 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) { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt index 8338308afbc..a6e7a51de9a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/common/FolderHeader.kt @@ -69,8 +69,7 @@ fun CollapsingFolderHeader( ) { val arrowRotation: Float by animateFloatAsState(if (expanded) 180f else 90f, label = "CollapsingArrowRotationAnimation") val expandDescription = stringResource( - id = if (expanded) R.string.content_description_collapse_label - else R.string.content_description_expand_label + id = if (expanded) R.string.content_description_collapse_label else R.string.content_description_expand_label ) Row( verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index cfebe4568ce..ce8ea215c78 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -396,8 +396,11 @@ private fun TopBarHeader( onNavigateBack: () -> Unit, openConversationBottomSheet: () -> Unit ) { - val navigationIconType = if (state.groupState == null) NavigationIconType.Close() - else NavigationIconType.Close(R.string.content_description_user_profile_close_btn) + val navigationIconType = if (state.groupState == null) { + NavigationIconType.Close() + } else { + NavigationIconType.Close(R.string.content_description_user_profile_close_btn) + } WireCenterAlignedTopAppBar( onNavigationPressed = onNavigateBack, diff --git a/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt b/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt index f8f6c0dd7a8..a203618c0dc 100644 --- a/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt +++ b/app/src/main/kotlin/com/wire/android/util/ui/StyledStringUtil.kt @@ -31,10 +31,8 @@ import androidx.compose.ui.text.LinkAnnotation import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextLinkStyles import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.UrlAnnotation import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration -import androidx.compose.ui.text.withAnnotation import androidx.compose.ui.text.withLink import androidx.compose.ui.text.withStyle import androidx.core.text.bold From 17887064de982fe81d29f26cc99d54a455296710 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 23 Oct 2024 12:54:20 +0300 Subject: [PATCH 15/16] Added comments to code --- .../wire/android/ui/common/textfield/WireTextFieldLayout.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt index 883415bbaee..a427da998b9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt @@ -56,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( From 2ed3c12278684d2b8ab741f9a7b5f2398e96e216 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Thu, 24 Oct 2024 13:56:43 +0300 Subject: [PATCH 16/16] Review fixes --- app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt | 4 ++-- .../android/ui/userprofile/other/OtherUserProfileDetails.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt b/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt index b284bac942e..f0393a13de3 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt @@ -29,13 +29,13 @@ import com.wire.android.ui.common.button.WireSecondaryIconButton fun CopyButton( onCopyClicked: () -> Unit, modifier: Modifier = Modifier, - @StringRes contentDescription: Int? = null, + @StringRes contentDescription: Int = R.string.content_description_copy, state: WireButtonState = WireButtonState.Default ) { WireSecondaryIconButton( onButtonClicked = onCopyClicked, iconResource = R.drawable.ic_copy, - contentDescription = contentDescription ?: R.string.content_description_copy, + contentDescription = contentDescription, state = state, modifier = modifier ) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt index 7f462f73b5f..d8353245aa5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileDetails.kt @@ -108,7 +108,7 @@ private fun UserDetailInformation( onCopy?.let { CopyButton( onCopyClicked = { onCopy(value) }, - contentDescription = copyBtnContentDescription + contentDescription = copyBtnContentDescription ?: R.string.content_description_copy ) } },