Icon-only transport buttons (play/pause/stop need no labels)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,8 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.input.key.onKeyEvent
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -236,13 +238,13 @@ private fun Overlay(state: AppState) {
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
PillButton(
|
||||
label = if (state.playerState == "paused") "Weiter" else "Pause",
|
||||
IconButton(
|
||||
icon = if (state.playerState == "paused") PillIcon.PLAY else PillIcon.PAUSE,
|
||||
contentDescription = if (state.playerState == "paused") "Weiter" else "Pause",
|
||||
focusRequester = playFocus,
|
||||
) { state.player.toggle() }
|
||||
Spacer(Modifier.width(10.dp))
|
||||
PillButton(label = "Beenden", icon = PillIcon.STOP) { state.stopPlayback() }
|
||||
IconButton(icon = PillIcon.STOP, contentDescription = "Beenden") { state.stopPlayback() }
|
||||
if (state.audioTracks.size > 1) {
|
||||
Spacer(Modifier.width(10.dp))
|
||||
val current = state.audioTracks.firstOrNull { it.selected }
|
||||
@@ -262,10 +264,59 @@ private fun Overlay(state: AppState) {
|
||||
|
||||
private enum class PillIcon { PLAY, PAUSE, STOP }
|
||||
|
||||
/** Round icon-only transport button; the icons are drawn, not typed —
|
||||
* glyphs like U+23F8 render as emoji on Android. */
|
||||
@Composable
|
||||
private fun IconButton(
|
||||
icon: PillIcon,
|
||||
contentDescription: String,
|
||||
focusRequester: FocusRequester? = null,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Surface(
|
||||
onClick = onClick,
|
||||
modifier = (if (focusRequester != null) Modifier.focusRequester(focusRequester) else Modifier)
|
||||
.semantics { this.contentDescription = contentDescription },
|
||||
shape = ClickableSurfaceDefaults.shape(CircleShape),
|
||||
colors = ClickableSurfaceDefaults.colors(
|
||||
containerColor = CastarrColors.surface.copy(alpha = 0.75f),
|
||||
contentColor = CastarrColors.fg,
|
||||
focusedContainerColor = CastarrColors.accent,
|
||||
focusedContentColor = CastarrColors.onAccent,
|
||||
),
|
||||
) {
|
||||
val color = LocalContentColor.current
|
||||
Box(Modifier.size(46.dp), contentAlignment = Alignment.Center) {
|
||||
Canvas(Modifier.size(15.dp)) {
|
||||
when (icon) {
|
||||
PillIcon.PLAY -> drawPath(
|
||||
Path().apply {
|
||||
moveTo(0f, 0f)
|
||||
lineTo(size.width, size.height / 2f)
|
||||
lineTo(0f, size.height)
|
||||
close()
|
||||
},
|
||||
color,
|
||||
)
|
||||
PillIcon.PAUSE -> {
|
||||
val bar = size.width * 0.3f
|
||||
drawRect(color, size = androidx.compose.ui.geometry.Size(bar, size.height))
|
||||
drawRect(
|
||||
color,
|
||||
topLeft = androidx.compose.ui.geometry.Offset(size.width - bar, 0f),
|
||||
size = androidx.compose.ui.geometry.Size(bar, size.height),
|
||||
)
|
||||
}
|
||||
PillIcon.STOP -> drawRect(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PillButton(
|
||||
label: String,
|
||||
icon: PillIcon? = null,
|
||||
focusRequester: FocusRequester? = null,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
@@ -280,45 +331,12 @@ private fun PillButton(
|
||||
focusedContentColor = CastarrColors.onAccent,
|
||||
),
|
||||
) {
|
||||
Row(
|
||||
Text(
|
||||
label,
|
||||
fontFamily = AppFont,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
modifier = Modifier.padding(horizontal = 18.dp, vertical = 9.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (icon != null) {
|
||||
// Drawn, not typed — glyphs like U+23F8 render as emoji on
|
||||
// Android and have no business on this screen.
|
||||
val color = LocalContentColor.current
|
||||
Canvas(Modifier.size(11.dp)) {
|
||||
when (icon) {
|
||||
PillIcon.PLAY -> drawPath(
|
||||
Path().apply {
|
||||
moveTo(0f, 0f)
|
||||
lineTo(size.width, size.height / 2f)
|
||||
lineTo(0f, size.height)
|
||||
close()
|
||||
},
|
||||
color,
|
||||
)
|
||||
PillIcon.PAUSE -> {
|
||||
val bar = size.width * 0.32f
|
||||
drawRect(color, size = androidx.compose.ui.geometry.Size(bar, size.height))
|
||||
drawRect(
|
||||
color,
|
||||
topLeft = androidx.compose.ui.geometry.Offset(size.width - bar, 0f),
|
||||
size = androidx.compose.ui.geometry.Size(bar, size.height),
|
||||
)
|
||||
}
|
||||
PillIcon.STOP -> drawRect(color)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.width(9.dp))
|
||||
}
|
||||
Text(
|
||||
label,
|
||||
fontFamily = AppFont,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user