feat: add skip segment functionality to player

This commit is contained in:
2026-04-26 12:21:52 +02:00
parent 9906d473c5
commit 522c8273d5
13 changed files with 263 additions and 56 deletions

View File

@@ -32,12 +32,15 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.common.util.UnstableApi
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
import hu.bbara.purefin.player.viewmodel.PlayerViewModel
import hu.bbara.purefin.ui.common.button.PurefinTextButton
import hu.bbara.purefin.ui.common.visual.EmptyValueTimedVisibility
import hu.bbara.purefin.ui.common.visual.ValueChangeTimedVisibility
import hu.bbara.purefin.ui.screen.player.components.PersistentOverlayContainer
@@ -168,8 +171,9 @@ fun PlayerScreen(
)
}
val playerControlsVisible = controlsVisible || uiState.isEnded || uiState.error != null
AnimatedVisibility(
visible = controlsVisible || uiState.isEnded || uiState.error != null,
visible = playerControlsVisible,
enter = fadeIn(),
exit = fadeOut()
) {
@@ -183,6 +187,7 @@ fun PlayerScreen(
onSeek = { viewModel.seekTo(it) },
onSeekRelative = { delta -> viewModel.seekBy(delta) },
onSeekLiveEdge = { viewModel.seekToLiveEdge() },
onSkipSegment = { viewModel.skipActiveSegment() },
onNext = { viewModel.next() },
onPrevious = { viewModel.previous() },
onSelectTrack = { viewModel.selectTrack(it) },
@@ -191,6 +196,26 @@ fun PlayerScreen(
)
}
AnimatedVisibility(
visible = !playerControlsVisible && uiState.activeSkippableSegmentEndMs != null,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(end = 24.dp, bottom = 24.dp)
) {
PurefinTextButton(
onClick = { viewModel.skipActiveSegment() },
modifier = Modifier.padding(8.dp)
) {
Text(
text = "Skip",
fontSize = 20.sp,
fontWeight = FontWeight.ExtraBold
)
}
}
PlayerLoadingErrorEndCard(
modifier = Modifier.align(Alignment.Center),
uiState = uiState,

View File

@@ -35,10 +35,12 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.PurefinIconButton
import androidx.compose.ui.unit.sp
import hu.bbara.purefin.player.model.PlayerUiState
import hu.bbara.purefin.player.model.TrackOption
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.PurefinIconButton
import hu.bbara.purefin.ui.common.button.PurefinTextButton
@Composable
fun PlayerControlsOverlay(
@@ -50,6 +52,7 @@ fun PlayerControlsOverlay(
onSeek: (Long) -> Unit,
onSeekRelative: (Long) -> Unit,
onSeekLiveEdge: () -> Unit,
onSkipSegment: () -> Unit,
onNext: () -> Unit,
onPrevious: () -> Unit,
onSelectTrack: (TrackOption) -> Unit,
@@ -100,6 +103,7 @@ fun PlayerControlsOverlay(
onSeekForward = { onSeekRelative(30_000) },
onSeekBackward = { onSeekRelative(-10_000) },
onSeekLiveEdge = onSeekLiveEdge,
onSkipSegment = onSkipSegment,
onSelectTrack = onSelectTrack,
onQueueSelected = onQueueSelected,
modifier = Modifier.align(Alignment.BottomCenter)
@@ -163,12 +167,33 @@ private fun BottomSection(
onSeekForward: () -> Unit,
onSeekBackward: () -> Unit,
onSeekLiveEdge: () -> Unit,
onSkipSegment: () -> Unit,
onSelectTrack: (TrackOption) -> Unit,
onQueueSelected: (String) -> Unit,
modifier: Modifier = Modifier
) {
val scheme = MaterialTheme.colorScheme
Column(modifier = modifier) {
if (uiState.activeSkippableSegmentEndMs != null) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
horizontalArrangement = Arrangement.End
) {
PurefinTextButton(
onClick = onSkipSegment,
modifier = Modifier.padding(8.dp)
) {
Text(
text = "Skip",
fontSize = 20.sp,
fontWeight = FontWeight.ExtraBold
)
}
}
Spacer(modifier = Modifier.height(6.dp))
}
Row(
modifier = Modifier
.fillMaxWidth()