player: match the normalised D-pad key when scrolling the description (#23)

Scrolling the info text up still did nothing on the TV while down worked. The
handler only matched the raw nativeKeyEvent keycode; remotes don't all report
the same codes, so match Compose's normalised Key.DirectionUp/Down as well, and
always attempt the scroll (animateScrollBy clamps at the ends itself) instead of
gating it on the current offset.

Not reproducible on the emulator in either the debug or the release build, so
this targets the device difference rather than a confirmed fault.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Jeena 2026-10-15 14:56:00 +00:00
parent 654963436f
commit ddacf48906

View file

@ -47,6 +47,8 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withLink import androidx.compose.ui.text.withLink
import androidx.compose.ui.text.TextLinkStyles import androidx.compose.ui.text.TextLinkStyles
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.KeyEventType import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.type import androidx.compose.ui.input.key.type
import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.onPreviewKeyEvent
@ -244,22 +246,31 @@ private fun DescriptionScroll(
.onPreviewKeyEvent { ke -> .onPreviewKeyEvent { ke ->
if (ke.type != KeyEventType.KeyDown) return@onPreviewKeyEvent false if (ke.type != KeyEventType.KeyDown) return@onPreviewKeyEvent false
val step = (viewportPx * 0.85f).coerceAtLeast(240f) val step = (viewportPx * 0.85f).coerceAtLeast(240f)
when (ke.nativeKeyEvent.keyCode) { val code = ke.nativeKeyEvent.keyCode
// UP/DOWN are always consumed: they scroll while there is room and // Match Compose's normalised key AND the raw keycode: remotes don't all
// otherwise do nothing, so focus stays here and the text can always // report the same native codes, and matching only the raw one left UP
// be scrolled back up (issue #23 review). // unhandled on some devices (issue #23 review).
KeyEvent.KEYCODE_DPAD_DOWN -> { val isUp = ke.key == Key.DirectionUp || code == KeyEvent.KEYCODE_DPAD_UP
if (scroll.value < scroll.maxValue) scope.launch { scroll.animateScrollBy(step) } val isDown = ke.key == Key.DirectionDown || code == KeyEvent.KEYCODE_DPAD_DOWN
val isLeft = ke.key == Key.DirectionLeft || code == KeyEvent.KEYCODE_DPAD_LEFT
val isCenter = ke.key == Key.DirectionCenter || ke.key == Key.Enter ||
code == KeyEvent.KEYCODE_DPAD_CENTER || code == KeyEvent.KEYCODE_ENTER
when {
// UP/DOWN are always consumed and always attempt the scroll (it
// clamps at the ends by itself), so focus stays here and the text
// can always be scrolled back up.
isDown -> {
scope.launch { scroll.animateScrollBy(step) }
true true
} }
KeyEvent.KEYCODE_DPAD_UP -> { isUp -> {
if (scroll.value > 0) scope.launch { scroll.animateScrollBy(-step) } scope.launch { scroll.animateScrollBy(-step) }
true true
} }
KeyEvent.KEYCODE_DPAD_LEFT -> { isLeft -> {
onDismiss(); true onDismiss(); true
} }
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_ENTER -> { isCenter -> {
onActivate(); true onActivate(); true
} }
else -> false else -> false