diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt index ae4d2693..e7360ec2 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackControls.kt @@ -65,6 +65,8 @@ import com.github.damontecres.dolphin.util.ExceptionHandler import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import org.jellyfin.sdk.model.api.MediaSegmentDto +import org.jellyfin.sdk.model.extensions.ticks import timber.log.Timber import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -120,6 +122,7 @@ fun PlaybackControls( seekBack: Duration, skipBackOnResume: Duration?, seekForward: Duration, + currentSegment: MediaSegmentDto?, modifier: Modifier = Modifier, initialFocusRequester: FocusRequester = remember { FocusRequester() }, seekBarInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }, @@ -189,18 +192,37 @@ fun PlaybackControls( skipBackOnResume = skipBackOnResume, modifier = Modifier.align(Alignment.Center), ) - RightPlaybackButtons( - subtitleStreams = subtitleStreams, - onControllerInteraction = onControllerInteraction, - onControllerInteractionForDialog = onControllerInteractionForDialog, - onPlaybackActionClick = onPlaybackActionClick, - subtitleIndex = subtitleIndex, - audioStreams = audioStreams, - audioIndex = audioIndex, - playbackSpeed = playbackSpeed, - scale = scale, + Row( modifier = Modifier.align(Alignment.CenterEnd), - ) + ) { + currentSegment?.let { segment -> + Button( + onClick = { + playerControls.seekTo(segment.endTicks.ticks.inWholeMilliseconds) + }, + modifier = + Modifier + .align(Alignment.CenterVertically) + .padding(end = 32.dp), + ) { + Text( + text = "Skip ${segment.type.serialName}", + ) + } + } + RightPlaybackButtons( + subtitleStreams = subtitleStreams, + onControllerInteraction = onControllerInteraction, + onControllerInteractionForDialog = onControllerInteractionForDialog, + onPlaybackActionClick = onPlaybackActionClick, + subtitleIndex = subtitleIndex, + audioStreams = audioStreams, + audioIndex = audioIndex, + playbackSpeed = playbackSpeed, + scale = scale, + modifier = Modifier, + ) + } } } } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt index e689bd72..97715dfc 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackOverlay.kt @@ -53,6 +53,7 @@ import com.github.damontecres.dolphin.ui.ifElse import com.github.damontecres.dolphin.ui.isNotNullOrBlank import com.github.damontecres.dolphin.ui.letNotEmpty import com.github.damontecres.dolphin.ui.tryRequestFocus +import org.jellyfin.sdk.model.api.MediaSegmentDto import org.jellyfin.sdk.model.api.TrickplayInfo import kotlin.time.Duration @@ -84,6 +85,7 @@ fun PlaybackOverlay( moreButtonOptions: MoreButtonOptions, currentPlayback: CurrentPlayback?, audioStreams: List, + currentSegment: MediaSegmentDto?, modifier: Modifier = Modifier, subtitle: String? = null, trickplayInfo: TrickplayInfo? = null, @@ -161,6 +163,7 @@ fun PlaybackOverlay( onNextStateFocus = { nextState?.let { state = it } }, + currentSegment = currentSegment, modifier = Modifier // Don't use key events because this control has vertical items so up/down is tough to manage @@ -413,6 +416,7 @@ fun Controller( currentPlayback: CurrentPlayback?, audioStreams: List, nextState: OverlayViewState?, + currentSegment: MediaSegmentDto?, modifier: Modifier = Modifier, subtitle: String? = null, seekBarInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }, @@ -466,6 +470,7 @@ fun Controller( seekBack = seekBack, seekForward = seekForward, skipBackOnResume = skipBackOnResume, + currentSegment = currentSegment, ) when (nextState) { OverlayViewState.CHAPTERS -> diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackPage.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackPage.kt index 3487d96a..3cc45df2 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackPage.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackPage.kt @@ -100,6 +100,7 @@ fun PlaybackPage( val chapters by viewModel.chapters.observeAsState(listOf()) val currentPlayback by viewModel.currentPlayback.observeAsState(null) val currentSegment by viewModel.currentSegment.observeAsState(null) + var segmentCancelled by remember(currentSegment?.id) { mutableStateOf(false) } var cues by remember { mutableStateOf>(listOf()) } var showDebugInfo by remember { mutableStateOf(prefs.showDebugInfo) } @@ -179,6 +180,13 @@ fun PlaybackPage( skipBackOnResume = preferences.appPreferences.playbackPreferences.skipBackOnResume, ) + val showSegment = + !segmentCancelled && currentSegment != null && + !controllerViewState.controlsVisible && skipIndicatorDuration == 0L + BackHandler(showSegment) { + segmentCancelled = true + } + Box( modifier .background(Color.Black), @@ -318,6 +326,7 @@ fun PlaybackPage( onClickPlaylist = { viewModel.playItemInPlaylist(it) }, + currentSegment = currentSegment, ) } @@ -345,7 +354,7 @@ fun PlaybackPage( // Ask to skip intros, etc button AnimatedVisibility( - currentSegment != null && !controllerViewState.controlsVisible && skipIndicatorDuration == 0L, + showSegment, modifier = Modifier .padding(40.dp) @@ -353,7 +362,11 @@ fun PlaybackPage( ) { currentSegment?.let { segment -> val focusRequester = remember { FocusRequester() } - LaunchedEffect(Unit) { focusRequester.tryRequestFocus() } + LaunchedEffect(Unit) { + focusRequester.tryRequestFocus() + delay(10.seconds) + segmentCancelled = false + } Button( onClick = { player.seekTo(segment.endTicks.ticks.inWholeMilliseconds)