mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
fix(ui): finish accessibility roles and action labels for clickable surfaces (#5170)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
56cbc3670d
commit
dd74e501f3
4 changed files with 75 additions and 10 deletions
|
|
@ -1276,4 +1276,12 @@
|
|||
<string name="filter_icon">Filter</string>
|
||||
<string name="remove_filter">Remove filter</string>
|
||||
<string name="show_iaq_legend">Show air quality legend</string>
|
||||
<string name="action_show_message_status">Show message status</string>
|
||||
<string name="action_send_reply">Send reply</string>
|
||||
<string name="action_copy_message">Copy message</string>
|
||||
<string name="action_select_message">Select message</string>
|
||||
<string name="action_delete_message">Delete message</string>
|
||||
<string name="action_react_with_emoji">React with emoji</string>
|
||||
<string name="action_select_device">Select device</string>
|
||||
<string name="action_select_network">Select network</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<String>,
|
||||
|
|
@ -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<String>, 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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue