fix(player): opening key-up no longer clicks the freshly focused pause button

The key-down that opens the overlay is consumed by the activity, but its
key-up arrived after the play button grabbed focus and clicked it —
instant pause right after the overlay appeared. The overlay now swallows
select-releases whose press it never saw.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 00:32:22 +02:00
parent b59c3deee4
commit 22bda1644f
2 changed files with 24 additions and 4 deletions

View File

@@ -12,8 +12,8 @@ android {
applicationId = "dev.castarr.tv" applicationId = "dev.castarr.tv"
minSdk = 26 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 11 versionCode = 12
versionName = "0.6.0" versionName = "0.6.1"
} }
// Release signing from environment (see ~/.keys/castarr-release.env on the // Release signing from environment (see ~/.keys/castarr-release.env on the

View File

@@ -17,7 +17,10 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@@ -26,8 +29,12 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.Path
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -97,14 +104,27 @@ private fun formatClock(millis: Long): String =
private fun Overlay(state: AppState) { private fun Overlay(state: AppState) {
val playFocus = remember { FocusRequester() } val playFocus = remember { FocusRequester() }
LaunchedEffect(Unit) { playFocus.requestFocus() } LaunchedEffect(Unit) { playFocus.requestFocus() }
// The key-UP of the very press that opened this overlay arrives after
// the play button grabbed focus and would click it (instant pause).
// Swallow select-releases whose press the overlay never saw.
var sawSelectDown by remember { mutableStateOf(false) }
Box( Box(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
// Any key while the overlay is open keeps it open a while longer. // Any key while the overlay is open keeps it open a while longer.
.onPreviewKeyEvent { .onPreviewKeyEvent { event ->
state.pingOverlay() state.pingOverlay()
false val select = event.key == Key.DirectionCenter ||
event.key == Key.Enter || event.key == Key.NumPadEnter
when {
select && event.type == KeyEventType.KeyDown -> {
sawSelectDown = true
false
}
select && event.type == KeyEventType.KeyUp && !sawSelectDown -> true
else -> false
}
}, },
) { ) {
Box( Box(