diff --git a/core/resources/src/commonMain/composeResources/values/strings.xml b/core/resources/src/commonMain/composeResources/values/strings.xml index 87268ecda..2c29ae3aa 100644 --- a/core/resources/src/commonMain/composeResources/values/strings.xml +++ b/core/resources/src/commonMain/composeResources/values/strings.xml @@ -1276,4 +1276,12 @@ Filter Remove filter Show air quality legend + Show message status + Send reply + Copy message + Select message + Delete message + React with emoji + Select device + Select network diff --git a/feature/connections/src/commonMain/kotlin/org/meshtastic/feature/connections/ui/components/DeviceListItem.kt b/feature/connections/src/commonMain/kotlin/org/meshtastic/feature/connections/ui/components/DeviceListItem.kt index a4d8ecdd8..14f4dc42b 100644 --- a/feature/connections/src/commonMain/kotlin/org/meshtastic/feature/connections/ui/components/DeviceListItem.kt +++ b/feature/connections/src/commonMain/kotlin/org/meshtastic/feature/connections/ui/components/DeviceListItem.kt @@ -17,13 +17,13 @@ package org.meshtastic.feature.connections.ui.components import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.selection.selectable import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.ListItem @@ -41,11 +41,15 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.selected +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import kotlinx.coroutines.delay import org.jetbrains.compose.resources.stringResource import org.meshtastic.core.model.ConnectionState import org.meshtastic.core.resources.Res +import org.meshtastic.core.resources.action_select_device import org.meshtastic.core.resources.add import org.meshtastic.core.resources.bluetooth import org.meshtastic.core.resources.network @@ -108,11 +112,19 @@ fun DeviceListItem( is DeviceListEntry.Mock -> stringResource(Res.string.add) } + val selectLabel = stringResource(Res.string.action_select_device) + val isSelected = connectionState is ConnectionState.Connected val clickableModifier = if (onDelete != null) { - Modifier.combinedClickable(onClick = onSelect, onLongClick = onDelete) + Modifier.semantics { selected = isSelected } + .combinedClickable( + onClickLabel = selectLabel, + role = Role.RadioButton, + onClick = onSelect, + onLongClick = onDelete, + ) } else { - Modifier.clickable(onClick = onSelect) + Modifier.selectable(selected = isSelected, role = Role.RadioButton, onClick = onSelect) } ListItem( diff --git a/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/component/MessageActionsBottomSheet.kt b/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/component/MessageActionsBottomSheet.kt index c4c99720c..5ffb5ea1d 100644 --- a/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/component/MessageActionsBottomSheet.kt +++ b/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/component/MessageActionsBottomSheet.kt @@ -36,11 +36,18 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource import org.meshtastic.core.model.MessageStatus import org.meshtastic.core.resources.Res +import org.meshtastic.core.resources.action_copy_message +import org.meshtastic.core.resources.action_delete_message +import org.meshtastic.core.resources.action_react_with_emoji +import org.meshtastic.core.resources.action_select_message +import org.meshtastic.core.resources.action_send_reply +import org.meshtastic.core.resources.action_show_message_status import org.meshtastic.core.resources.copy import org.meshtastic.core.resources.delete import org.meshtastic.core.resources.device_metrics_label_value @@ -55,6 +62,7 @@ import org.meshtastic.core.ui.icon.MeshtasticIcons import org.meshtastic.core.ui.icon.Reply import org.meshtastic.core.ui.icon.SelectAll +@Suppress("LongMethod") @Composable fun MessageActionsContent( quickEmojis: List, @@ -83,20 +91,35 @@ fun MessageActionsContent( Text(stringResource(Res.string.device_metrics_label_value, title, statusText.orEmpty())) }, leadingContent = { MessageStatusIcon(status = status) }, - modifier = Modifier.clickable(onClick = onStatus), + modifier = + Modifier.clickable( + onClickLabel = stringResource(Res.string.action_show_message_status), + role = Role.Button, + onClick = onStatus, + ), ) } ListItem( headlineContent = { Text(stringResource(Res.string.reply)) }, leadingContent = { Icon(MeshtasticIcons.Reply, contentDescription = stringResource(Res.string.reply)) }, - modifier = Modifier.clickable(onClick = onReply), + modifier = + Modifier.clickable( + onClickLabel = stringResource(Res.string.action_send_reply), + role = Role.Button, + onClick = onReply, + ), ) ListItem( headlineContent = { Text(stringResource(Res.string.copy)) }, leadingContent = { Icon(MeshtasticIcons.Copy, contentDescription = stringResource(Res.string.copy)) }, - modifier = Modifier.clickable(onClick = onCopy), + modifier = + Modifier.clickable( + onClickLabel = stringResource(Res.string.action_copy_message), + role = Role.Button, + onClick = onCopy, + ), ) ListItem( @@ -104,13 +127,23 @@ fun MessageActionsContent( leadingContent = { Icon(MeshtasticIcons.SelectAll, contentDescription = stringResource(Res.string.select)) }, - modifier = Modifier.clickable(onClick = onSelect), + modifier = + Modifier.clickable( + onClickLabel = stringResource(Res.string.action_select_message), + role = Role.Button, + onClick = onSelect, + ), ) ListItem( headlineContent = { Text(stringResource(Res.string.delete)) }, leadingContent = { Icon(MeshtasticIcons.Delete, contentDescription = stringResource(Res.string.delete)) }, - modifier = Modifier.clickable(onClick = onDelete), + modifier = + Modifier.clickable( + onClickLabel = stringResource(Res.string.action_delete_message), + role = Role.Button, + onClick = onDelete, + ), ) } } @@ -130,7 +163,12 @@ private fun QuickEmojiRow(quickEmojis: List, onReact: (String) -> Unit, Modifier.size(40.dp) .clip(CircleShape) .background(MaterialTheme.colorScheme.surfaceVariant) - .clickable { onReact(emoji) }, + .clickable( + onClickLabel = stringResource(Res.string.action_react_with_emoji), + role = Role.Button, + ) { + onReact(emoji) + }, contentAlignment = Alignment.Center, ) { Text(text = emoji, style = MaterialTheme.typography.titleMedium) diff --git a/feature/wifi-provision/src/commonMain/kotlin/org/meshtastic/feature/wifiprovision/ui/WifiProvisionScreen.kt b/feature/wifi-provision/src/commonMain/kotlin/org/meshtastic/feature/wifiprovision/ui/WifiProvisionScreen.kt index 015a4e08b..397710fea 100644 --- a/feature/wifi-provision/src/commonMain/kotlin/org/meshtastic/feature/wifiprovision/ui/WifiProvisionScreen.kt +++ b/feature/wifi-provision/src/commonMain/kotlin/org/meshtastic/feature/wifiprovision/ui/WifiProvisionScreen.kt @@ -76,6 +76,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation @@ -87,6 +88,7 @@ import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel import org.meshtastic.core.resources.Res +import org.meshtastic.core.resources.action_select_network import org.meshtastic.core.resources.apply import org.meshtastic.core.resources.back import org.meshtastic.core.resources.cancel @@ -489,7 +491,12 @@ internal fun NetworkRow(network: WifiNetwork, isSelected: Boolean, onClick: () - } }, colors = ListItemDefaults.colors(containerColor = containerColor), - modifier = Modifier.clickable(onClick = onClick), + modifier = + Modifier.clickable( + onClickLabel = stringResource(Res.string.action_select_network), + role = Role.Button, + onClick = onClick, + ), ) }