diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelItem.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelItem.kt
index d1d38cd12ac..e5d760b3203 100644
--- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelItem.kt
+++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/list/ChannelItem.kt
@@ -47,8 +47,6 @@ import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.platform.testTag
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.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -142,7 +140,8 @@ public fun ChannelItem(
},
) {
val channel = channelItem.channel
- val description = stringResource(id = R.string.stream_compose_cd_channel_item)
+ val openLabel = stringResource(R.string.stream_compose_channel_item_open)
+ val optionsLabel = stringResource(R.string.stream_compose_channel_item_options)
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
@@ -154,13 +153,14 @@ public fun ChannelItem(
.testTag("Stream_ChannelItem")
.fillMaxWidth()
.wrapContentHeight()
- .semantics { contentDescription = description }
.applyIf(isFocused) { border(2.dp, ChatTheme.colors.borderUtilityFocused, shape) }
.clip(shape)
.applyIf(channelItem.isSelected) { background(ChatTheme.colors.backgroundUtilitySelected, shape) }
.combinedClickable(
onClick = { onChannelClick(channel) },
+ onClickLabel = openLabel,
onLongClick = { onChannelLongClick(channel) },
+ onLongClickLabel = optionsLabel,
indication = ripple(),
interactionSource = interactionSource,
),
@@ -283,7 +283,7 @@ private fun TitleRow(
.testTag("Stream_ChannelMutedIcon")
.size(16.dp),
painter = painterResource(id = R.drawable.stream_design_ic_mute),
- contentDescription = null,
+ contentDescription = stringResource(R.string.stream_compose_channel_item_muted),
tint = ChatTheme.colors.textTertiary,
)
}
@@ -350,7 +350,7 @@ private fun MessageRow(
.testTag("Stream_ChannelMutedIcon")
.size(16.dp),
painter = painterResource(id = R.drawable.stream_design_ic_mute),
- contentDescription = null,
+ contentDescription = stringResource(R.string.stream_compose_channel_item_muted),
tint = ChatTheme.colors.textTertiary,
)
}
diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/HeaderScaffold.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/HeaderScaffold.kt
index 11701e5eccc..84c464b2db0 100644
--- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/HeaderScaffold.kt
+++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/HeaderScaffold.kt
@@ -36,6 +36,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.heading
+import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.ui.components.avatar.AvatarSize
@@ -140,7 +142,8 @@ internal fun RowScope.DefaultListHeaderCenterContent(
modifier = Modifier
.weight(1f)
.wrapContentWidth()
- .padding(horizontal = StreamTokens.spacingMd),
+ .padding(horizontal = StreamTokens.spacingMd)
+ .semantics { heading() },
text = title,
style = ChatTheme.typography.headingSmall,
maxLines = 1,
@@ -154,7 +157,8 @@ internal fun RowScope.DefaultListHeaderCenterContent(
modifier = Modifier
.weight(1f)
.wrapContentWidth()
- .padding(horizontal = StreamTokens.spacingMd),
+ .padding(horizontal = StreamTokens.spacingMd)
+ .semantics { heading() },
text = stringResource(R.string.stream_compose_disconnected),
style = ChatTheme.typography.headingSmall,
maxLines = 1,
diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/MessagePreviewContent.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/MessagePreviewContent.kt
index ded6fda1744..ca0b3cdfb73 100644
--- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/MessagePreviewContent.kt
+++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/MessagePreviewContent.kt
@@ -25,7 +25,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.text
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
@@ -64,7 +64,7 @@ internal fun MessagePreviewContent(
Row(
modifier = modifier
.testTag("Stream_MessagePreview")
- .semantics { text = AnnotatedString(fullPreview) },
+ .clearAndSetSemantics { text = AnnotatedString(fullPreview) },
horizontalArrangement = Arrangement.spacedBy(StreamTokens.spacing3xs),
) {
if (senderName != null) {
@@ -101,7 +101,7 @@ internal fun DraftPreviewContent(
Row(
modifier = modifier
.testTag("Stream_MessagePreview")
- .semantics { text = AnnotatedString(fullPreview) },
+ .clearAndSetSemantics { text = AnnotatedString(fullPreview) },
horizontalArrangement = Arrangement.spacedBy(StreamTokens.spacing3xs),
) {
Text(
diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/UnreadCountIndicator.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/UnreadCountIndicator.kt
index f74faba21fd..724148cb68e 100644
--- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/UnreadCountIndicator.kt
+++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/UnreadCountIndicator.kt
@@ -27,9 +27,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.res.pluralStringResource
+import androidx.compose.ui.semantics.clearAndSetSemantics
+import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.theme.StreamTokens
@@ -47,12 +51,18 @@ public fun UnreadCountIndicator(
color: Color = ChatTheme.colors.accentPrimary,
) {
val displayText = if (unreadCount > LimitTooManyUnreadCount) UnreadCountMany else unreadCount.toString()
+ val description = pluralStringResource(
+ R.plurals.stream_compose_channel_item_unread,
+ unreadCount,
+ unreadCount,
+ )
Box(
modifier = modifier
.defaultMinSize(minWidth = 20.dp, minHeight = 20.dp)
.background(shape = CircleShape, color = color)
- .padding(horizontal = StreamTokens.spacing2xs), // 4dp horizontal content padding
+ .padding(horizontal = StreamTokens.spacing2xs)
+ .clearAndSetSemantics { contentDescription = description },
contentAlignment = Alignment.Center,
) {
Text(
diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/TextUtils.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/TextUtils.kt
index 0631f35d053..7bf1f90bd21 100644
--- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/TextUtils.kt
+++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/TextUtils.kt
@@ -226,16 +226,21 @@ private fun AnnotatedString.Builder.tagUser(
if (start < 0) return@forEach
+ // Backtrack one position to include the leading `@`. Clamp to 0 when the mention is at the
+ // start of the text and no `@` precedes it — otherwise the resulting -1 span start crashes
+ // TalkBack's spannable conversion with `setSpan (-1 ...) starts before 0`.
+ val styledStart = (start - 1).coerceAtLeast(0)
+
addStyle(
style = SpanStyle(color = mentionsColor),
- start = start - 1, // -1 to include the @ symbol
+ start = styledStart,
end = end,
)
addStringAnnotation(
tag = AnnotationTagMention,
annotation = userName,
- start = start - 1, // -1 to include the @ symbol
+ start = styledStart,
end = end,
)
}
diff --git a/stream-chat-android-compose/src/main/res/values-es/strings.xml b/stream-chat-android-compose/src/main/res/values-es/strings.xml
index 202dcf8b5e5..7481f63b568 100644
--- a/stream-chat-android-compose/src/main/res/values-es/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-es/strings.xml
@@ -56,7 +56,9 @@
"+%1$d"
"Bloquear usuario"
"Cancelar"
- "Elemento de canal"
+ "silenciado"
+ "Abrir conversación"
+ "Abrir opciones de conversación"
"Elemento de mensaje"
"Botón de reproducción"
"Borrador: "
@@ -259,6 +261,10 @@
"Conectado"
"Vídeo"
"Esperando conexión de red"
+
+ - "%d mensaje sin leer"
+ - "%d mensajes sin leer"
+
- "%d persona está escribiendo"
- "%d personas están escribiendo"
diff --git a/stream-chat-android-compose/src/main/res/values-fr/strings.xml b/stream-chat-android-compose/src/main/res/values-fr/strings.xml
index 76a4240e600..5ce3ccca9b5 100644
--- a/stream-chat-android-compose/src/main/res/values-fr/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-fr/strings.xml
@@ -56,7 +56,9 @@
"+%1$d"
"Bloquer l\'utilisateur"
"Annuler"
- "Élément de canal"
+ "en sourdine"
+ "Ouvrir la conversation"
+ "Ouvrir les options de conversation"
"Élément de message"
"Bouton de lecture"
"Brouillon : "
@@ -259,6 +261,10 @@
"En ligne"
"Vidéo"
"En attente de réseau"
+
+ - "%d message non lu"
+ - "%d messages non lus"
+
- "%d personne écrit"
- "%d personnes écrivent"
diff --git a/stream-chat-android-compose/src/main/res/values-hi/strings.xml b/stream-chat-android-compose/src/main/res/values-hi/strings.xml
index 2c511cd628b..eae677cfdcb 100644
--- a/stream-chat-android-compose/src/main/res/values-hi/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-hi/strings.xml
@@ -15,6 +15,10 @@
limitations under the License.
-->
+
+ - "%d अपठित संदेश"
+ - "%d अपठित संदेश"
+
- "%d व्यक्ति टाइप कर रहा है"
- "%d लोग टाइप कर रहे हैं"
@@ -112,7 +116,9 @@
"+%1$d"
"उपयोगकर्ता को ब्लॉक करें"
"रद्द करें"
- "चैनल आइटम"
+ "म्यूट किया गया"
+ "बातचीत खोलें"
+ "बातचीत के विकल्प खोलें"
"मैसेज आइटम"
"चलाएँ बटन"
"ड्राफ़्ट: "
diff --git a/stream-chat-android-compose/src/main/res/values-in/strings.xml b/stream-chat-android-compose/src/main/res/values-in/strings.xml
index d465a0a68d6..9d7a7034dc7 100644
--- a/stream-chat-android-compose/src/main/res/values-in/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-in/strings.xml
@@ -56,7 +56,9 @@
"+%1$d"
"Blokir pengguna"
"Batal"
- "Item saluran"
+ "dibisukan"
+ "Buka percakapan"
+ "Buka opsi percakapan"
"Item pesan"
"Tombol putar"
"Draf: "
@@ -259,6 +261,10 @@
"Online"
"Video"
"Menunggu jaringan"
+
+ - "%d pesan belum dibaca"
+ - "%d pesan belum dibaca"
+
- "%d orang sedang mengetik"
diff --git a/stream-chat-android-compose/src/main/res/values-it/strings.xml b/stream-chat-android-compose/src/main/res/values-it/strings.xml
index f69c0f98282..4fb11462293 100644
--- a/stream-chat-android-compose/src/main/res/values-it/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-it/strings.xml
@@ -15,6 +15,10 @@
limitations under the License.
-->
+
+ - "%d messaggio non letto"
+ - "%d messaggi non letti"
+
- "%d persona sta scrivendo"
- "%d persone stanno scrivendo"
@@ -112,7 +116,9 @@
"+%1$d"
"Blocca utente"
"Annulla"
- "Elemento canale"
+ "silenziato"
+ "Apri conversazione"
+ "Apri opzioni conversazione"
"Elemento messaggio"
"Pulsante riproduci"
"Bozza: "
diff --git a/stream-chat-android-compose/src/main/res/values-ja/strings.xml b/stream-chat-android-compose/src/main/res/values-ja/strings.xml
index d478f091e40..5e6ffcc84a5 100644
--- a/stream-chat-android-compose/src/main/res/values-ja/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-ja/strings.xml
@@ -56,7 +56,9 @@
"+%1$d"
"ユーザーをブロック"
"キャンセル"
- "チャンネル項目"
+ "ミュート中"
+ "会話を開く"
+ "会話のオプションを開く"
"メッセージ項目"
"再生ボタン"
"下書き: "
@@ -64,6 +66,10 @@
"\"%1$s\"の検索結果はありません"
"新しいチャット"
"チャットを始める"
+
+ - "%d件の未読メッセージ"
+ - "%d件の未読メッセージ"
+
- "%d人が入力中"
diff --git a/stream-chat-android-compose/src/main/res/values-ko/strings.xml b/stream-chat-android-compose/src/main/res/values-ko/strings.xml
index b5b4caa2a14..fb28eb654c1 100644
--- a/stream-chat-android-compose/src/main/res/values-ko/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values-ko/strings.xml
@@ -56,7 +56,9 @@
"+%1$d"
"사용자 차단"
"취소"
- "채널 항목"
+ "음소거됨"
+ "대화 열기"
+ "대화 옵션 열기"
"메시지 항목"
"재생 버튼"
"임시 저장: "
@@ -64,6 +66,10 @@
"\"%1$s\"에 대한 검색결과가 없습니다"
"새 채팅"
"채팅 시작하기"
+
+ - "%d개의 안 읽은 메시지"
+ - "%d개의 안 읽은 메시지"
+
- "%d명이 입력 중"
diff --git a/stream-chat-android-compose/src/main/res/values/strings.xml b/stream-chat-android-compose/src/main/res/values/strings.xml
index 4faa3c59bf2..23bbe66965a 100644
--- a/stream-chat-android-compose/src/main/res/values/strings.xml
+++ b/stream-chat-android-compose/src/main/res/values/strings.xml
@@ -288,7 +288,13 @@
%.2f MB needs to be downloaded before sharing.
- Channel item
+ Open conversation
+ Open conversation options
+ muted
+
+ - %d unread message
+ - %d unread messages
+
Message item
Play button