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

View File

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