Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit82d26f8

Browse files
feat: Add accessibility string to OtherUserProfile and search participants [WPB-9784] 🍒 (#3557)
Co-authored-by: boris <safonovboris@gmail.com>
1 parentd9b6b91 commit82d26f8

File tree

24 files changed

+183
-71
lines changed

24 files changed

+183
-71
lines changed

‎app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import androidx.compose.ui.platform.testTag
4242
importandroidx.compose.ui.res.painterResource
4343
importandroidx.compose.ui.res.stringResource
4444
importandroidx.compose.ui.res.vectorResource
45+
importandroidx.compose.ui.semantics.onClick
46+
importandroidx.compose.ui.semantics.semantics
4547
importandroidx.compose.ui.text.style.TextOverflow
4648
importandroidx.compose.ui.unit.dp
4749
importcom.wire.android.BuildConfig
@@ -101,6 +103,8 @@ private fun DeviceItemContent(
101103
shouldShowE2EIInfo:Boolean,
102104
modifier:Modifier =Modifier,
103105
) {
106+
val openDetailsDescription= stringResource(id=R.string.content_description_user_profile_open_device_btn)
107+
104108
Row(
105109
verticalAlignment=Alignment.Top,
106110
modifier= modifier
@@ -109,6 +113,9 @@ private fun DeviceItemContent(
109113
onClickAction?.invoke(device)
110114
}
111115
}
116+
.semantics {
117+
if (isWholeItemClickable) onClick(openDetailsDescription) {false }
118+
}
112119
) {
113120
Row(
114121
modifier=Modifier
@@ -118,7 +125,7 @@ private fun DeviceItemContent(
118125
Icon(
119126
modifier=Modifier.shimmerPlaceholder(visible= placeholder),
120127
imageVector=ImageVector.vectorResource(id=R.drawable.ic_devices),
121-
contentDescription=stringResource(R.string.content_description_remove_devices_screen_device_item_icon)
128+
contentDescription=null
122129
)
123130
Column(
124131
horizontalAlignment=Alignment.Start,
@@ -199,7 +206,8 @@ private fun ColumnScope.DeviceItemTexts(
199206
ProteusVerifiedIcon(
200207
Modifier
201208
.wrapContentWidth()
202-
.align(Alignment.CenterVertically))
209+
.align(Alignment.CenterVertically)
210+
)
203211
}
204212
}
205213
}

‎app/src/main/kotlin/com/wire/android/ui/common/CopyButton.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
packagecom.wire.android.ui.common
2020

21+
importandroidx.annotation.StringRes
2122
importandroidx.compose.runtime.Composable
2223
importandroidx.compose.ui.Modifier
2324
importcom.wire.android.R
@@ -27,13 +28,14 @@ import com.wire.android.ui.common.button.WireSecondaryIconButton
2728
@Composable
2829
funCopyButton(
2930
onCopyClicked: ()->Unit,
30-
state:WireButtonState =WireButtonState.Default,
31-
modifier:Modifier =Modifier
31+
modifier:Modifier =Modifier,
32+
@StringRescontentDescription:Int =R.string.content_description_copy,
33+
state:WireButtonState =WireButtonState.Default
3234
) {
3335
WireSecondaryIconButton(
3436
onButtonClicked= onCopyClicked,
3537
iconResource=R.drawable.ic_copy,
36-
contentDescription=R.string.content_description_copy,
38+
contentDescription=contentDescription,
3739
state= state,
3840
modifier= modifier
3941
)

‎app/src/main/kotlin/com/wire/android/ui/common/SearchBar.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ fun SearchBarInput(
5959
placeholderAlignment:Alignment.Horizontal =Alignment.CenterHorizontally,
6060
interactionSource:MutableInteractionSource = remember {MutableInteractionSource() },
6161
textStyle:TextStyle =LocalTextStyle.current,
62-
isLoading:Boolean = false
62+
isLoading:Boolean = false,
63+
semanticDescription:String? = null
6364
) {
6465

6566
WireTextField(
@@ -108,6 +109,7 @@ fun SearchBarInput(
108109
placeholderAlignment= placeholderAlignment,
109110
placeholderText= placeholderText,
110111
lineLimits=TextFieldLineLimits.SingleLine,
112+
semanticDescription= semanticDescription
111113
)
112114
}
113115

‎app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ internal fun WireTextField(
7171
labelText:String? = null,
7272
labelMandatoryIcon:Boolean = false,
7373
descriptionText:String? = null,
74+
semanticDescription:String? = null,
7475
leadingIcon: @Composable (()->Unit)? = null,
7576
trailingIcon: @Composable (()->Unit)? = null,
7677
state:WireTextFieldState =WireTextFieldState.Default,
@@ -115,6 +116,7 @@ internal fun WireTextField(
115116
labelText= labelText,
116117
labelMandatoryIcon= labelMandatoryIcon,
117118
descriptionText= descriptionText,
119+
semanticDescription= semanticDescription,
118120
leadingIcon= leadingIcon,
119121
trailingIcon= trailingIcon,
120122
state= state,

‎app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import androidx.compose.ui.geometry.Offset
4141
importandroidx.compose.ui.graphics.Shape
4242
importandroidx.compose.ui.input.pointer.pointerInput
4343
importandroidx.compose.ui.platform.testTag
44+
importandroidx.compose.ui.semantics.clearAndSetSemantics
4445
importandroidx.compose.ui.semantics.contentDescription
4546
importandroidx.compose.ui.semantics.semantics
4647
importandroidx.compose.ui.text.TextStyle
@@ -55,6 +56,12 @@ import com.wire.android.ui.theme.wireTypography
5556
importcom.wire.android.util.EMPTY
5657
importio.github.esentsov.PackagePrivate
5758

59+
/**
60+
* Priority in which fields are used for SemanticContentDescription:
61+
* [semanticDescription] -> [labelText] -> [placeholderText] -> [descriptionText].
62+
* If you need to make empty SemanticContentDescription (which is definitely bad idea for TextView)
63+
* set [semanticDescription] = ""
64+
*/
5865
@PackagePrivate
5966
@Composable
6067
internalfunWireTextFieldLayout(
@@ -65,6 +72,7 @@ internal fun WireTextFieldLayout(
6572
labelText:String? = null,
6673
labelMandatoryIcon:Boolean = false,
6774
descriptionText:String? = null,
75+
semanticDescription:String? = null,
6876
leadingIcon: @Composable (()->Unit)? = null,
6977
trailingIcon: @Composable (()->Unit)? = null,
7078
state:WireTextFieldState =WireTextFieldState.Default,
@@ -101,8 +109,8 @@ internal fun WireTextFieldLayout(
101109
.fillMaxWidth()
102110
.background(color= colors.backgroundColor(state).value, shape= shape)
103111
.border(width= dimensions().spacing1x, color= colors.borderColor(state, interactionSource).value, shape= shape)
104-
.semantics {
105-
(labelText?: placeholderText?: descriptionText)?.let {
112+
.semantics(mergeDescendants=true) {
113+
(semanticDescription?:labelText?: placeholderText?: descriptionText)?.let {
106114
contentDescription= it
107115
}
108116
}
@@ -178,7 +186,9 @@ private fun InnerTextLayout(
178186
text= placeholderText,
179187
style= placeholderTextStyle,
180188
color= colors.placeholderColor(style).value,
181-
modifier=Modifier.align(placeholderAlignment.toAlignment())
189+
modifier=Modifier
190+
.align(placeholderAlignment.toAlignment())
191+
.clearAndSetSemantics {}
182192
)
183193
}
184194
Box(

‎app/src/main/kotlin/com/wire/android/ui/common/topappbar/search/SearchTopBar.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ fun SearchTopBar(
7171
searchQueryTextState:TextFieldState,
7272
modifier:Modifier =Modifier,
7373
isLoading:Boolean = false,
74+
searchBarDescription:String? = null,
7475
onCloseSearchClicked: (()->Unit)? = null,
7576
onActiveChanged: (isActive:Boolean)->Unit = {},
7677
bottomContent: @ComposableColumnScope.()->Unit = {}
@@ -107,6 +108,7 @@ fun SearchTopBar(
107108

108109
SearchBarInput(
109110
placeholderText= searchBarHint,
111+
semanticDescription= searchBarDescription,
110112
textState= searchQueryTextState,
111113
isLoading= isLoading,
112114
leadingIcon= {
@@ -118,7 +120,7 @@ fun SearchTopBar(
118120
) {
119121
Icon(
120122
painter= painterResource(R.drawable.ic_search),
121-
contentDescription=stringResource(R.string.content_description_conversation_search_icon),
123+
contentDescription=null,
122124
tint=MaterialTheme.wireColorScheme.onBackground,
123125
)
124126
}
@@ -129,7 +131,7 @@ fun SearchTopBar(
129131
) {
130132
Icon(
131133
painter= rememberVectorPainter(image=Icons.Filled.ArrowBack),
132-
contentDescription= stringResource(R.string.content_description_back_button),
134+
contentDescription= stringResource(id=R.string.content_description_add_participants_back_btn),
133135
tint=MaterialTheme.wireColorScheme.onBackground,
134136
)
135137
}

‎app/src/main/kotlin/com/wire/android/ui/home/conversations/media/ConversationMediaButton.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ fun ConversationMediaButton(
4343
leadingIcon= {
4444
Icon(
4545
painter= painterResource(id=R.drawable.ic_gallery),
46-
contentDescription=stringResource(R.string.label_conversation_media),
46+
contentDescription=null,
4747
tint=MaterialTheme.colorScheme.onBackground,
4848
modifier=Modifier.padding(end= dimensions().spacing8x)
4949
)
50-
}
50+
},
51+
onClickDescription= stringResource(id=R.string.content_description_see_media_in_conversation_btn)
5152
)
5253
}

‎app/src/main/kotlin/com/wire/android/ui/home/conversations/search/InternalContactSearchResultItem.kt

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ import androidx.compose.runtime.Composable
2626
importandroidx.compose.ui.Alignment
2727
importandroidx.compose.ui.Alignment.Companion.CenterVertically
2828
importandroidx.compose.ui.Modifier
29+
importandroidx.compose.ui.res.stringResource
30+
importandroidx.compose.ui.semantics.semantics
31+
importandroidx.compose.ui.semantics.stateDescription
32+
importcom.wire.android.R
2933
importcom.wire.android.appLogger
3034
importcom.wire.android.model.Clickable
3135
importcom.wire.android.model.ItemActionType
@@ -53,16 +57,15 @@ fun InternalContactSearchResultItem(
5357
membership:Membership,
5458
searchQuery:String,
5559
connectionState:ConnectionState,
56-
onCheckChange: (Boolean)->Unit,
60+
onCheckClickable:Clickable,
5761
isSelected:Boolean,
5862
clickable:Clickable,
5963
actionType:ItemActionType,
6064
modifier:Modifier =Modifier
6165
) {
66+
val selectedDescription= stringResource(id=R.string.content_description_selected_label)
6267
RowItemTemplate(
63-
leadingIcon= {
64-
UserProfileAvatar(avatarData)
65-
},
68+
leadingIcon= {UserProfileAvatar(avatarData) },
6669
titleStartPadding= dimensions().spacing0x,
6770
title= {
6871
Row(verticalAlignment=CenterVertically) {
@@ -101,14 +104,16 @@ fun InternalContactSearchResultItem(
101104
}
102105
},
103106
clickable=
104-
if (actionType.clickable) {
105-
clickable
106-
}else {
107-
Clickable {
108-
onCheckChange(!isSelected)
109-
}
110-
},
111-
modifier= modifier.padding(start= dimensions().spacing8x)
107+
if (actionType.clickable) {
108+
clickable
109+
}else {
110+
onCheckClickable
111+
},
112+
modifier= modifier
113+
.padding(start= dimensions().spacing8x)
114+
.semantics {
115+
if (actionType.checkable&& isSelected) stateDescription= selectedDescription
116+
}
112117
)
113118
}
114119

@@ -155,15 +160,20 @@ fun ExternalContactSearchResultItem(
155160
when (connectionState) {
156161
ConnectionState.NOT_CONNECTED,ConnectionState.CANCELLED->
157162
AddContactButton(userId, name)
163+
158164
ConnectionState.PENDING,ConnectionState.IGNORED->
159165
Box(modifier=Modifier.padding(horizontal= dimensions().spacing12x)) {ConnectRequestBadge() }
166+
160167
ConnectionState.SENT->
161168
Box(modifier=Modifier.padding(horizontal= dimensions().spacing12x)) {ConnectPendingRequestBadge() }
169+
162170
ConnectionState.BLOCKED-> {
163171
}
172+
164173
ConnectionState.MISSING_LEGALHOLD_CONSENT-> {
165174
appLogger.e("Unhandled ConnectionState.MISSING_LEGALHOLD_CONSENT in ExternalContactSearchResultItem")
166175
}
176+
167177
ConnectionState.ACCEPTED-> {
168178
appLogger.e("ConnectionState.ACCEPTED should not appear in ExternalContactSearchResultItem")
169179
}
@@ -184,12 +194,13 @@ fun PreviewInternalContactSearchResultItemCheckable() = WireTheme {
184194
membership=Membership.None,
185195
searchQuery="",
186196
connectionState=ConnectionState.ACCEPTED,
187-
onCheckChange= {},
197+
onCheckClickable=Clickable {},
188198
isSelected=false,
189199
clickable=Clickable {},
190200
actionType=ItemActionType.CHECK,
191201
)
192202
}
203+
193204
@PreviewMultipleThemes
194205
@Composable
195206
funPreviewInternalContactSearchResultItemClickable()=WireTheme {
@@ -200,7 +211,7 @@ fun PreviewInternalContactSearchResultItemClickable() = WireTheme {
200211
membership=Membership.None,
201212
searchQuery="",
202213
connectionState=ConnectionState.ACCEPTED,
203-
onCheckChange= {},
214+
onCheckClickable=Clickable {},
204215
isSelected=false,
205216
clickable=Clickable {},
206217
actionType=ItemActionType.CLICK,

‎app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ import com.wire.android.ui.home.newconversation.model.Contact
5252
importcom.wire.android.ui.theme.WireTheme
5353
importcom.wire.android.util.extension.FolderType
5454
importcom.wire.android.util.extension.folderWithElements
55-
importcom.wire.android.util.ui.keepOnTopWhenNotScrolled
5655
importcom.wire.android.util.ui.PreviewMultipleThemes
56+
importcom.wire.android.util.ui.keepOnTopWhenNotScrolled
5757
importcom.wire.kalium.logic.data.user.ConnectionState
5858
importcom.wire.kalium.logic.data.user.UserId
5959
importkotlinx.collections.immutable.ImmutableList
@@ -287,7 +287,13 @@ private fun LazyListScope.internalSuccessItem(
287287
folderType=FolderType.Collapsing(expanded= expanded, onChanged= onExpansionChanged),
288288
) { (contact, isSelected)->
289289
with(contact) {
290-
val onClick= remember { { isChecked:Boolean-> onChecked(isChecked,this) } }
290+
val onCheckDescription= stringResource(
291+
id=if (isSelected)R.string.content_description_unselect_labelelseR.string.content_description_select_label
292+
)
293+
val clickDescription= stringResource(id=R.string.content_description_open_user_profile_label)
294+
val onCheckClickable= remember(isSelected) {
295+
Clickable(onClickDescription= onCheckDescription) { onChecked(!isSelected,this) }
296+
}
291297
InternalContactSearchResultItem(
292298
avatarData= avatarData,
293299
name= name,
@@ -296,9 +302,9 @@ private fun LazyListScope.internalSuccessItem(
296302
searchQuery= searchQuery,
297303
connectionState= connectionState,
298304
isSelected= isSelected,
299-
onCheckChange=onClick,
305+
onCheckClickable=onCheckClickable,
300306
actionType= actionType,
301-
clickable= remember {Clickable(enabled=true) { onOpenUserProfile(contact) } }
307+
clickable= remember {Clickable(onClickDescription=clickDescription) { onOpenUserProfile(contact) } }
302308
)
303309
}
304310
}
@@ -344,6 +350,7 @@ private fun LazyListScope.externalSuccessItem(
344350
folderType=FolderType.Collapsing(expanded= expanded, onChanged= onExpansionChanged),
345351
) { contact->
346352
with(contact) {
353+
val clickDescription= stringResource(id=R.string.content_description_open_user_profile_label)
347354
ExternalContactSearchResultItem(
348355
avatarData= avatarData,
349356
userId=UserId(id, domain),
@@ -352,7 +359,7 @@ private fun LazyListScope.externalSuccessItem(
352359
membership= membership,
353360
connectionState= connectionState,
354361
searchQuery= searchQuery,
355-
clickable= remember {Clickable(enabled=true) { onOpenUserProfile(contact) } }
362+
clickable= remember {Clickable(onClickDescription=clickDescription) { onOpenUserProfile(contact) } }
356363
)
357364
}
358365
}

‎app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import androidx.compose.runtime.LaunchedEffect
2929
importandroidx.compose.runtime.remember
3030
importandroidx.compose.ui.Alignment
3131
importandroidx.compose.ui.Modifier
32+
importandroidx.compose.ui.res.stringResource
3233
importandroidx.hilt.navigation.compose.hiltViewModel
3334
importcom.wire.android.R
3435
importcom.wire.android.model.Clickable
@@ -110,6 +111,7 @@ private fun SuccessServicesList(
110111
folderWithElements(
111112
items= services.associateBy { it.id }
112113
) {
114+
val clickDescription= stringResource(id=R.string.content_description_open_service_label)
113115
RowItemTemplate(
114116
leadingIcon= {
115117
Row {
@@ -132,7 +134,7 @@ private fun SuccessServicesList(
132134
}
133135
},
134136
actions= {},
135-
clickable= remember(it) {Clickable(enabled=true) { onServiceClicked(it) } },
137+
clickable= remember(it) {Clickable(onClickDescription=clickDescription) { onServiceClicked(it) } },
136138
modifier=Modifier.padding(start= dimensions().spacing8x)
137139
)
138140
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp