feat(nests): use mic icons for talk / stop talking

The text Talk / Stop Talking buttons made it easy to misread the
broadcast state. Swap them for large filled mic-icon buttons so the
mic state is unmistakable: MicOff in primary color when idle (tap to
go live), Mic in error color when broadcasting (mic is open, tap to
stop).
This commit is contained in:
Claude
2026-04-30 03:28:53 +00:00
parent 9bc1e3d3ce
commit 6da9af2a81
@@ -31,14 +31,17 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material3.AssistChip import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.FilledTonalIconToggleButton import androidx.compose.material3.FilledTonalIconToggleButton
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
@@ -263,7 +266,11 @@ private fun OnStageControls(
when (val broadcast = ui.broadcast) { when (val broadcast = ui.broadcast) {
BroadcastUiState.Idle -> { BroadcastUiState.Idle -> {
Button(onClick = { // Mic OFF visual: filled primary button signals "tap to go live".
// Sized larger than the surrounding 40.dp icon buttons so the
// mic state is unmistakable at a glance.
FilledIconButton(
onClick = {
val granted = val granted =
ContextCompat.checkSelfPermission( ContextCompat.checkSelfPermission(
context, context,
@@ -274,8 +281,19 @@ private fun OnStageControls(
} else { } else {
permissionLauncher.launch(Manifest.permission.RECORD_AUDIO) permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
} }
}) { },
Text(stringRes(R.string.nest_talk)) modifier = Modifier.size(56.dp),
colors =
IconButtonDefaults.filledIconButtonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary,
),
) {
Icon(
symbol = MaterialSymbols.MicOff,
contentDescription = stringRes(R.string.nest_talk),
modifier = Modifier.size(28.dp),
)
} }
OutlinedButton(onClick = { viewModel.setOnStage(false) }) { OutlinedButton(onClick = { viewModel.setOnStage(false) }) {
Text(stringRes(R.string.nest_leave_stage)) Text(stringRes(R.string.nest_leave_stage))
@@ -336,8 +354,23 @@ private fun OnStageControls(
), ),
) )
} }
OutlinedButton(onClick = { viewModel.stopBroadcast() }) { // Mic ON visual: filled error-color button screams "MIC IS LIVE,
Text(stringRes(R.string.nest_stop_talking)) // tap to stop transmitting". Same large footprint as the Idle
// mic button so the state swap is impossible to miss.
FilledIconButton(
onClick = { viewModel.stopBroadcast() },
modifier = Modifier.size(56.dp),
colors =
IconButtonDefaults.filledIconButtonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError,
),
) {
Icon(
symbol = MaterialSymbols.Mic,
contentDescription = stringRes(R.string.nest_stop_talking),
modifier = Modifier.size(28.dp),
)
} }
OutlinedButton(onClick = { OutlinedButton(onClick = {
viewModel.stopBroadcast() viewModel.stopBroadcast()
@@ -348,8 +381,20 @@ private fun OnStageControls(
} }
is BroadcastUiState.Failed -> { is BroadcastUiState.Failed -> {
Button(onClick = { viewModel.startBroadcast(speakerPubkeyHex) }) { FilledIconButton(
Text(stringRes(R.string.nest_talk)) onClick = { viewModel.startBroadcast(speakerPubkeyHex) },
modifier = Modifier.size(56.dp),
colors =
IconButtonDefaults.filledIconButtonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary,
),
) {
Icon(
symbol = MaterialSymbols.MicOff,
contentDescription = stringRes(R.string.nest_talk),
modifier = Modifier.size(28.dp),
)
} }
} }
} }