fix(player): let focused overlay handle D-pad center instead of pausing

The root Box's onPreviewKeyEvent consumed KeyDown for D-pad
center/Enter in handleTvPlayerRootKeyEvent, pausing or resuming
playback and returning true before the event reached the focused
next-episode overlay. Pressing center on the overlay therefore
paused playback instead of starting the next episode.

Add a popupVisible flag so the root handler returns false for
center/Enter when a focusable overlay (skip intro / next episode) is
shown, letting the event propagate to the overlay's clickable. The
skip-intro action is preserved because the visible skip button now
handles activation through its own clickable.

Drop the now-unused onSkipSegment/hasSkippableSegment parameters and
the redundant focusable modifier on TvNextEpisodeOverlay (clickable
already makes it focusable).
This commit is contained in:
2026-06-19 11:04:18 +00:00
parent 1bd51d8a9f
commit 50bbf5b81f
2 changed files with 7 additions and 11 deletions

View File

@@ -262,6 +262,7 @@ fun TvPlayerScreen(
event = event, event = event,
isPlaying = uiState.isPlaying, isPlaying = uiState.isPlaying,
controlsVisible = controlsVisible, controlsVisible = controlsVisible,
popupVisible = showSkipIntroButton || showNextEpisodeOverlay,
onShowControls = ::showControls, onShowControls = ::showControls,
isPlaylistExpanded = isPlaylistExpanded, isPlaylistExpanded = isPlaylistExpanded,
trackPanelType = trackPanelType, trackPanelType = trackPanelType,
@@ -271,10 +272,6 @@ fun TvPlayerScreen(
onPausePlayback = { viewModel.pausePlayback() }, onPausePlayback = { viewModel.pausePlayback() },
onResumePlayback = { viewModel.resumePlayback() }, onResumePlayback = { viewModel.resumePlayback() },
onSeekRelative = { viewModel.seekBy(it) }, onSeekRelative = { viewModel.seekBy(it) },
onSkipSegment = {
viewModel.skipActiveSegment()
},
hasSkippableSegment = uiState.activeSkippableSegmentEndMs != null
) )
if (event.type == KeyEventType.KeyDown) { if (event.type == KeyEventType.KeyDown) {
hideControlsWithTimeout() hideControlsWithTimeout()
@@ -481,6 +478,7 @@ internal fun handleTvPlayerRootKeyEvent(
event: KeyEvent, event: KeyEvent,
isPlaying: Boolean, isPlaying: Boolean,
controlsVisible: Boolean, controlsVisible: Boolean,
popupVisible: Boolean,
isPlaylistExpanded: Boolean, isPlaylistExpanded: Boolean,
trackPanelType: TvTrackPanelType?, trackPanelType: TvTrackPanelType?,
onCloseTrackPanel: () -> Unit, onCloseTrackPanel: () -> Unit,
@@ -490,8 +488,6 @@ internal fun handleTvPlayerRootKeyEvent(
onResumePlayback: () -> Unit, onResumePlayback: () -> Unit,
onSeekRelative: (Long) -> Unit, onSeekRelative: (Long) -> Unit,
onShowControls: () -> Unit, onShowControls: () -> Unit,
onSkipSegment: () -> Unit = {},
hasSkippableSegment: Boolean = false
): Boolean { ): Boolean {
if (event.type != KeyEventType.KeyDown) return false if (event.type != KeyEventType.KeyDown) return false
@@ -534,14 +530,16 @@ internal fun handleTvPlayerRootKeyEvent(
} }
Key.DirectionCenter, Key.Enter -> { Key.DirectionCenter, Key.Enter -> {
if (hasSkippableSegment) { if (popupVisible) {
onSkipSegment() // Do nothing because the focused component is not he root, but an overlay
false
} else if (isPlaying) { } else if (isPlaying) {
onPausePlayback() onPausePlayback()
true
} else { } else {
onResumePlayback() onResumePlayback()
true
} }
true
} }
else -> false else -> false

View File

@@ -5,7 +5,6 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -80,7 +79,6 @@ fun TvNextEpisodeOverlay(
) )
.clip(RoundedCornerShape(20.dp)) .clip(RoundedCornerShape(20.dp))
.background(backgroundColor) .background(backgroundColor)
.focusable()
.onFocusChanged { isFocused = it.isFocused } .onFocusChanged { isFocused = it.isFocused }
.clickable { onClick() }, .clickable { onClick() },
verticalArrangement = Arrangement.spacedBy(0.dp) verticalArrangement = Arrangement.spacedBy(0.dp)