make goto next or prev streem buttons work

This commit is contained in:
Christian Schabesberger 2024-09-06 15:42:19 +02:00
parent 106060625c
commit 58e0ad9f09
5 changed files with 122 additions and 80 deletions

View File

@ -79,6 +79,7 @@ interface NewPlayer {
val playlist: StateFlow<List<PlaylistItem>>
val currentlyPlaying: StateFlow<PlaylistItem?>
var currentlyPlayingPlaylistItem: Int
val currentChapters: StateFlow<List<Chapter>>
@ -96,7 +97,6 @@ interface NewPlayer {
fun removePlaylistItem(index: Int)
fun playStream(item: String, playMode: PlayMode)
fun selectChapter(index: Int)
fun selectPlaylistItem(index: Int)
fun playStream(item: String, streamVariant: String, playMode: PlayMode)
data class Builder(val app: Application, val repository: MediaRepository) {
@ -209,6 +209,15 @@ class NewPlayerImpl(
private val mutableCurrentChapter = MutableStateFlow<List<Chapter>>(emptyList())
override val currentChapters: StateFlow<List<Chapter>> = mutableCurrentChapter.asStateFlow()
override var currentlyPlayingPlaylistItem: Int
get() = internalPlayer.currentMediaItemIndex
set(value) {
assert(value in 0..<playlist.value.size) {
throw NewPlayerException("Playlist item selection out of bound: selected item index: $value, available chapters: ${playlist.value.size}")
}
internalPlayer.seekTo(value, 0)
}
init {
internalPlayer.addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
@ -349,13 +358,6 @@ class NewPlayerImpl(
currentPosition = chapter.chapterStartInMs
}
override fun selectPlaylistItem(index: Int) {
assert(index in 0..<playlist.value.size) {
throw NewPlayerException("Playlist item selection out of bound: selected item index: $index, available chapters: ${playlist.value.size}")
}
internalPlayer.seekTo(index, 0)
}
private fun internalPlayStream(mediaItem: MediaItem, playMode: PlayMode) {
if (internalPlayer.playbackState == Player.STATE_IDLE) {
internalPlayer.prepare()

View File

@ -46,7 +46,8 @@ data class VideoPlayerUIState(
val shuffleEnabled: Boolean,
val repeatMode: RepeatMode,
val playListDurationInS: Int,
val currentlyPlaying: PlaylistItem
val currentlyPlaying: PlaylistItem,
val currentPlaylistItemIndex: Int
) {
companion object {
val DEFAULT = VideoPlayerUIState(
@ -70,7 +71,8 @@ data class VideoPlayerUIState(
shuffleEnabled = false,
repeatMode = RepeatMode.DONT_REPEAT,
playListDurationInS = 0,
currentlyPlaying = PlaylistItem.DEFAULT
currentlyPlaying = PlaylistItem.DEFAULT,
currentPlaylistItemIndex = 0
)
val DUMMY = DEFAULT.copy(
@ -87,7 +89,51 @@ data class VideoPlayerUIState(
brightness = 0.2f,
shuffleEnabled = true,
playListDurationInS = 5493,
currentlyPlaying = PlaylistItem.DUMMY
currentlyPlaying = PlaylistItem.DUMMY,
currentPlaylistItemIndex = 1,
chapters = arrayListOf(
Chapter(
chapterStartInMs = 5000,
chapterTitle = "First Chapter",
thumbnail = null
),
Chapter(
chapterStartInMs = 10000,
chapterTitle = "Second Chapter",
thumbnail = null
),
Chapter(
chapterStartInMs = 20000,
chapterTitle = "Third Chapter",
thumbnail = null
)
),
playList = arrayListOf(
PlaylistItem(
id = "6502",
title = "Stream 1",
creator = "The Creator",
lengthInS = 6 * 60 + 5,
thumbnail = null,
uniqueId = 0
),
PlaylistItem(
id = "6502",
title = "Stream 2",
creator = "The Creator 2",
lengthInS = 2 * 60 + 5,
thumbnail = null,
uniqueId = 1
),
PlaylistItem(
id = "6502",
title = "Stream 3",
creator = "The Creator 3",
lengthInS = 29 * 60 + 5,
thumbnail = null,
uniqueId = 2
)
)
)
}
}

View File

@ -30,6 +30,7 @@ import androidx.core.content.ContextCompat.getSystemService
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
@ -42,7 +43,6 @@ import javax.inject.Inject
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import net.newpipe.newplayer.Chapter
import net.newpipe.newplayer.utils.VideoSize
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.RepeatMode
@ -194,13 +194,20 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
viewModelScope.launch {
newPlayer.playlist.collect { playlist ->
mutableUiState.update { it.copy(playList = playlist) }
mutableUiState.update {
it.copy(
playList = playlist,
)
}
}
}
viewModelScope.launch {
newPlayer.currentlyPlaying.collect { playlistItem ->
mutableUiState.update {
it.copy(currentlyPlaying = playlistItem ?: PlaylistItem.DEFAULT)
it.copy(
currentlyPlaying = playlistItem ?: PlaylistItem.DEFAULT,
currentPlaylistItemIndex = newPlayer.currentlyPlayingPlaylistItem
)
}
}
}
@ -261,12 +268,20 @@ class VideoPlayerViewModelImpl @Inject constructor(
override fun prevStream() {
resetHideUiDelayedJob()
Log.e(TAG, "imeplement prev stream")
newPlayer?.let { newPlayer ->
if (0 <= newPlayer.currentlyPlayingPlaylistItem - 1) {
newPlayer.currentlyPlayingPlaylistItem -= 1
}
}
}
override fun nextStream() {
resetHideUiDelayedJob()
Log.e(TAG, "implement next stream")
newPlayer?.let { newPlayer ->
if (newPlayer.currentlyPlayingPlaylistItem + 1 < newPlayer.internalPlayer.mediaItemCount) {
newPlayer.currentlyPlayingPlaylistItem += 1
}
}
}
override fun showUi() {
@ -427,7 +442,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
if (selectChapter) uiState.value.uiMode.getChapterSelectUiState()
else uiState.value.uiMode.getStreamSelectUiState()
)
if(selectChapter) {
if (selectChapter) {
resetProgressUpdatePeriodicallyJob()
} else {
resetPlaylistProgressUpdaterJob()
@ -468,8 +483,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
override fun streamSelected(streamId: Int) {
println("gurken stream selected: $streamId")
newPlayer?.selectPlaylistItem(streamId)
newPlayer?.currentlyPlayingPlaylistItem = streamId
}
override fun cycleRepeatMode() {

View File

@ -21,9 +21,15 @@
package net.newpipe.newplayer.ui.videoplayer
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Pause
@ -33,6 +39,7 @@ import androidx.compose.material.icons.filled.SkipPrevious
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@ -60,13 +67,22 @@ fun CenterUI(
modifier = modifier,
) {
Box(modifier = Modifier.size(80.dp)) {
androidx.compose.animation.AnimatedVisibility(
uiState.currentPlaylistItemIndex != 0,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(400))
) {
CenterControllButton(
buttonModifier = Modifier.size(80.dp),
buttonModifier = Modifier.fillMaxSize(),
iconModifier = Modifier.size(40.dp),
icon = Icons.Filled.SkipPrevious,
contentDescription = stringResource(R.string.widget_description_previous_stream),
onClick = viewModel::prevStream
)
}
}
CenterControllButton(
buttonModifier = Modifier.size(80.dp),
@ -78,15 +94,22 @@ fun CenterUI(
),
onClick = if (uiState.playing) viewModel::pause else viewModel::play
)
Box(modifier = Modifier.size(80.dp)) {
androidx.compose.animation.AnimatedVisibility(
uiState.currentPlaylistItemIndex < uiState.playList.size - 1,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(400))
) {
CenterControllButton(
buttonModifier = Modifier.size(80.dp),
buttonModifier = Modifier.fillMaxSize(),
iconModifier = Modifier.size(40.dp),
icon = Icons.Filled.SkipNext,
contentDescription = stringResource(R.string.widget_description_next_stream),
onClick = viewModel::nextStream
)
}
}
}
}
@Composable
@ -124,7 +147,8 @@ fun VideoPlayerControllerUICenterUIPreview() {
viewModel = VideoPlayerViewModelDummy(),
uiState = VideoPlayerUIState.DUMMY.copy(
isLoading = false,
playing = true
playing = true,
currentPlaylistItemIndex = 1
)
)
}

View File

@ -172,25 +172,7 @@ fun VideoPlayerChannelSelectUIPreview() {
StreamSelectUI(
isChapterSelect = true,
viewModel = VideoPlayerViewModelDummy(),
uiState = VideoPlayerUIState.DEFAULT.copy(
chapters = arrayListOf(
Chapter(
chapterStartInMs = 5000,
chapterTitle = "First Chapter",
thumbnail = null
),
Chapter(
chapterStartInMs = 10000,
chapterTitle = "Second Chapter",
thumbnail = null
),
Chapter(
chapterStartInMs = 20000,
chapterTitle = "Third Chapter",
thumbnail = null
),
)
)
uiState = VideoPlayerUIState.DUMMY
)
}
}
@ -205,32 +187,6 @@ fun VideoPlayerStreamSelectUIPreview() {
isChapterSelect = false,
viewModel = VideoPlayerViewModelDummy(),
uiState = VideoPlayerUIState.DUMMY.copy(
playList = arrayListOf(
PlaylistItem(
id = "6502",
title = "Stream 1",
creator = "The Creator",
lengthInS = 6 * 60 + 5,
thumbnail = null,
uniqueId = 0
),
PlaylistItem(
id = "6502",
title = "Stream 2",
creator = "The Creator 2",
lengthInS = 2 * 60 + 5,
thumbnail = null,
uniqueId = 1
),
PlaylistItem(
id = "6502",
title = "Stream 3",
creator = "The Creator 3",
lengthInS = 29 * 60 + 5,
thumbnail = null,
uniqueId = 2
)
),
currentlyPlaying = PlaylistItem.DUMMY.copy(uniqueId = 1)
)
)