mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
feat(player): track skippable segment type to gate intro and outro UI
Expose the active skippable segment type from the player state so the UI can show the skip intro button only for intro segments and trigger the next episode overlay when an outro segment is active.
This commit is contained in:
@@ -62,6 +62,7 @@ import androidx.media3.ui.PlayerView
|
|||||||
import androidx.media3.ui.SubtitleView
|
import androidx.media3.ui.SubtitleView
|
||||||
import hu.bbara.purefin.core.player.model.TimedMarker
|
import hu.bbara.purefin.core.player.model.TimedMarker
|
||||||
import hu.bbara.purefin.core.player.viewmodel.PlayerViewModel
|
import hu.bbara.purefin.core.player.viewmodel.PlayerViewModel
|
||||||
|
import hu.bbara.purefin.model.SegmentType
|
||||||
import hu.bbara.purefin.ui.common.visual.ValueChangeTimedVisibility
|
import hu.bbara.purefin.ui.common.visual.ValueChangeTimedVisibility
|
||||||
import hu.bbara.purefin.ui.screen.player.components.PlayerSeekBarTrack
|
import hu.bbara.purefin.ui.screen.player.components.PlayerSeekBarTrack
|
||||||
import hu.bbara.purefin.ui.screen.player.components.TvIconButton
|
import hu.bbara.purefin.ui.screen.player.components.TvIconButton
|
||||||
@@ -179,11 +180,12 @@ fun TvPlayerScreen(
|
|||||||
|
|
||||||
val showSkipIntroButton = !controlsVisible
|
val showSkipIntroButton = !controlsVisible
|
||||||
&& uiState.activeSkippableSegmentEndMs != null
|
&& uiState.activeSkippableSegmentEndMs != null
|
||||||
|
&& uiState.activeSkippableSegmentType == SegmentType.INTRO
|
||||||
&& !uiState.isEnded
|
&& !uiState.isEnded
|
||||||
val showNextEpisodeOverlay = !controlsVisible
|
val showNextEpisodeOverlay = !controlsVisible
|
||||||
&& uiState.nextEpisode != null
|
&& uiState.nextEpisode != null
|
||||||
&& uiState.durationMs > 0L
|
&& uiState.durationMs > 0L
|
||||||
&& (uiState.durationMs - uiState.positionMs) <= 60_000L
|
&& ((uiState.durationMs - uiState.positionMs) <= 30_000L || uiState.activeSkippableSegmentType == SegmentType.OUTRO)
|
||||||
&& !uiState.isEnded
|
&& !uiState.isEnded
|
||||||
LaunchedEffect(showSkipIntroButton, showNextEpisodeOverlay) {
|
LaunchedEffect(showSkipIntroButton, showNextEpisodeOverlay) {
|
||||||
rootFocusRequester = when {
|
rootFocusRequester = when {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import androidx.media3.ui.PlayerView
|
|||||||
import androidx.media3.ui.SubtitleView
|
import androidx.media3.ui.SubtitleView
|
||||||
import hu.bbara.purefin.core.player.model.TimedMarker
|
import hu.bbara.purefin.core.player.model.TimedMarker
|
||||||
import hu.bbara.purefin.core.player.viewmodel.PlayerViewModel
|
import hu.bbara.purefin.core.player.viewmodel.PlayerViewModel
|
||||||
|
import hu.bbara.purefin.model.SegmentType
|
||||||
import hu.bbara.purefin.ui.common.visual.EmptyValueTimedVisibility
|
import hu.bbara.purefin.ui.common.visual.EmptyValueTimedVisibility
|
||||||
import hu.bbara.purefin.ui.common.visual.ValueChangeTimedVisibility
|
import hu.bbara.purefin.ui.common.visual.ValueChangeTimedVisibility
|
||||||
import hu.bbara.purefin.ui.screen.player.components.NextEpisodeOverlay
|
import hu.bbara.purefin.ui.screen.player.components.NextEpisodeOverlay
|
||||||
@@ -100,11 +101,11 @@ fun PlayerScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val showSkipIntroButton = !controlsVisible && uiState.activeSkippableSegmentEndMs != null
|
val showSkipIntroButton = !controlsVisible && uiState.activeSkippableSegmentEndMs != null && uiState.activeSkippableSegmentType == SegmentType.INTRO
|
||||||
val showNextEpisodeOverlay = !controlsVisible
|
val showNextEpisodeOverlay = !controlsVisible
|
||||||
&& uiState.nextEpisode != null
|
&& uiState.nextEpisode != null
|
||||||
&& uiState.durationMs > 0L
|
&& uiState.durationMs > 0L
|
||||||
&& (uiState.durationMs - uiState.positionMs) <= 60_000L
|
&& ((uiState.durationMs - uiState.positionMs) <= 60_000L || uiState.activeSkippableSegmentType == SegmentType.OUTRO)
|
||||||
&& !uiState.isEnded
|
&& !uiState.isEnded
|
||||||
|
|
||||||
|
|
||||||
@@ -301,7 +302,7 @@ fun PlayerScreen(
|
|||||||
.align(Alignment.BottomEnd)
|
.align(Alignment.BottomEnd)
|
||||||
.padding(
|
.padding(
|
||||||
end = 24.dp,
|
end = 24.dp,
|
||||||
bottom = 120.dp
|
bottom = 24.dp
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
uiState.nextEpisode?.let { nextEpisode ->
|
uiState.nextEpisode?.let { nextEpisode ->
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package hu.bbara.purefin.core.player.model
|
package hu.bbara.purefin.core.player.model
|
||||||
|
|
||||||
|
import hu.bbara.purefin.model.SegmentType
|
||||||
|
|
||||||
data class PlayerUiState(
|
data class PlayerUiState(
|
||||||
val isPlaying: Boolean = false,
|
val isPlaying: Boolean = false,
|
||||||
val isBuffering: Boolean = false,
|
val isBuffering: Boolean = false,
|
||||||
@@ -11,6 +13,7 @@ data class PlayerUiState(
|
|||||||
val positionMs: Long = 0L,
|
val positionMs: Long = 0L,
|
||||||
val bufferedMs: Long = 0L,
|
val bufferedMs: Long = 0L,
|
||||||
val activeSkippableSegmentEndMs: Long? = null,
|
val activeSkippableSegmentEndMs: Long? = null,
|
||||||
|
val activeSkippableSegmentType: SegmentType? = null,
|
||||||
val error: String? = null,
|
val error: String? = null,
|
||||||
val playbackSpeed: Float = 1f,
|
val playbackSpeed: Float = 1f,
|
||||||
val chapters: List<TimedMarker> = emptyList(),
|
val chapters: List<TimedMarker> = emptyList(),
|
||||||
|
|||||||
@@ -117,7 +117,10 @@ class PlayerViewModel @Inject constructor(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
playerManager.activeSkippableSegment.collect { mediaSegment ->
|
playerManager.activeSkippableSegment.collect { mediaSegment ->
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
it.copy(activeSkippableSegmentEndMs = mediaSegment?.endMs)
|
it.copy(
|
||||||
|
activeSkippableSegmentEndMs = mediaSegment?.endMs,
|
||||||
|
activeSkippableSegmentType = mediaSegment?.type
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user