add chapter/stream selection to audio ui

This commit is contained in:
Christian Schabesberger 2024-09-23 15:07:37 +02:00
parent afceb43308
commit a4f8e490ae
5 changed files with 170 additions and 130 deletions

View File

@ -96,7 +96,7 @@ fun AudioPlaybackController(viewModel: NewPlayerViewModel, uiState: NewPlayerUIS
.fillMaxWidth() .fillMaxWidth()
.aspectRatio(1f), .aspectRatio(1f),
onClick = { onClick = {
viewModel.fastSeek(1) viewModel.fastSeek(-1)
viewModel.finishFastSeek() viewModel.finishFastSeek()
}, },
colors = lightAudioControlButtonColorScheme(), colors = lightAudioControlButtonColorScheme(),

View File

@ -22,6 +22,10 @@
package net.newpipe.newplayer.ui.audioplayer package net.newpipe.newplayer.ui.audioplayer
import androidx.annotation.OptIn import androidx.annotation.OptIn
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.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -49,11 +53,17 @@ import net.newpipe.newplayer.R
import net.newpipe.newplayer.model.NewPlayerUIState import net.newpipe.newplayer.model.NewPlayerUIState
import net.newpipe.newplayer.model.NewPlayerViewModel import net.newpipe.newplayer.model.NewPlayerViewModel
import net.newpipe.newplayer.model.NewPlayerViewModelDummy import net.newpipe.newplayer.model.NewPlayerViewModelDummy
import net.newpipe.newplayer.model.UIModeState
import net.newpipe.newplayer.ui.common.NewPlayerSeeker import net.newpipe.newplayer.ui.common.NewPlayerSeeker
import net.newpipe.newplayer.ui.streamselect.StreamSelectUI
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
import net.newpipe.newplayer.utils.Thumbnail import net.newpipe.newplayer.utils.Thumbnail
import net.newpipe.newplayer.utils.getInsets import net.newpipe.newplayer.utils.getInsets
private val UI_ENTER_ANIMATION = fadeIn(tween(200))
private val UI_EXIT_ANIMATION = fadeOut(tween(200))
@Composable @Composable
fun lightAudioControlButtonColorScheme() = ButtonDefaults.buttonColors().copy( fun lightAudioControlButtonColorScheme() = ButtonDefaults.buttonColors().copy(
containerColor = MaterialTheme.colorScheme.background, containerColor = MaterialTheme.colorScheme.background,
@ -70,88 +80,110 @@ fun AudioPlayerUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
.fillMaxSize() .fillMaxSize()
.background(color = MaterialTheme.colorScheme.background) .background(color = MaterialTheme.colorScheme.background)
) { ) {
Scaffold(modifier = Modifier AnimatedVisibility(
.fillMaxSize() visible = uiState.uiMode == UIModeState.AUDIO_CHAPTER_SELECT,
.windowInsetsPadding(insets), enter = UI_ENTER_ANIMATION,
topBar = { exit = UI_EXIT_ANIMATION
) {
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true)
}
}) { innerPadding -> AnimatedVisibility(
Box( visible = uiState.uiMode == UIModeState.AUDIO_STREAM_SELECT,
modifier = Modifier enter = UI_ENTER_ANIMATION,
.fillMaxSize() exit = UI_EXIT_ANIMATION
.padding(innerPadding) ) {
) { StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = false)
Column( }
AnimatedVisibility(
uiState.uiMode == UIModeState.FULLSCREEN_AUDIO,
enter = UI_ENTER_ANIMATION,
exit = UI_EXIT_ANIMATION
) {
Scaffold(modifier = Modifier
.fillMaxSize()
.windowInsetsPadding(insets),
topBar = {
}) { innerPadding ->
Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(innerPadding)
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(20.dp)
.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Box( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.weight(1f) .padding(20.dp)
) .weight(1f),
Box { horizontalAlignment = Alignment.CenterHorizontally,
Card( ) {
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), Box(
) { modifier = Modifier
Thumbnail( .fillMaxSize()
modifier = Modifier.fillMaxWidth(), .weight(1f)
thumbnail = uiState.currentlyPlaying?.mediaMetadata?.artworkUri, )
contentDescription = stringResource( Box {
id = R.string.stream_thumbnail Card(
), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
) ) {
Thumbnail(
modifier = Modifier.fillMaxWidth(),
thumbnail = uiState.currentlyPlaying?.mediaMetadata?.artworkUri,
contentDescription = stringResource(
id = R.string.stream_thumbnail
),
)
}
} }
} Box(
Box( modifier = Modifier
modifier = Modifier .fillMaxSize()
.fillMaxSize() .weight(1f)
.weight(1f) )
) Text(
Text( text = uiState.currentlyPlaying?.mediaMetadata?.title.toString(),
text = uiState.currentlyPlaying?.mediaMetadata?.title.toString(), overflow = TextOverflow.Ellipsis,
overflow = TextOverflow.Ellipsis, maxLines = 1,
maxLines = 1, fontSize = 6.em
fontSize = 6.em )
) Text(
Text( text = uiState.currentlyPlaying?.mediaMetadata?.artist.toString(),
text = uiState.currentlyPlaying?.mediaMetadata?.artist.toString(), overflow = TextOverflow.Ellipsis,
overflow = TextOverflow.Ellipsis, maxLines = 1,
maxLines = 1, fontSize = 4.em
fontSize = 4.em )
)
Box(
modifier = Modifier
.fillMaxSize()
.weight(0.2f)
)
NewPlayerSeeker(viewModel = viewModel, uiState = uiState)
Box(
modifier = Modifier
.fillMaxSize()
.weight(0.2f)
)
AudioPlaybackController(viewModel = viewModel, uiState = uiState)
Box(
modifier = Modifier
.fillMaxSize()
.weight(0.2f)
)
}
AudioBottomUI(viewModel, uiState)
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.weight(0.2f) .weight(0.025f)
)
NewPlayerSeeker(viewModel = viewModel, uiState = uiState)
Box(
modifier = Modifier
.fillMaxSize()
.weight(0.2f)
)
AudioPlaybackController(viewModel = viewModel, uiState = uiState)
Box(
modifier = Modifier
.fillMaxSize()
.weight(0.2f)
) )
} }
AudioBottomUI(viewModel, uiState)
Box(
modifier = Modifier
.fillMaxSize()
.weight(0.025f)
)
} }
} }
} }

View File

@ -102,7 +102,10 @@ fun StreamSelectTopBar(
IconButton( IconButton(
onClick = { onClick = {
viewModel.changeUiMode(uiState.uiMode.getUiHiddenState(), embeddedUiConfig) viewModel.changeUiMode(
uiState.uiMode.getNextModeWhenBackPressed() ?: uiState.uiMode,
embeddedUiConfig
)
} }
) { ) {
Icon( Icon(

View File

@ -70,67 +70,63 @@ fun StreamSelectUI(
else else
EmbeddedUiConfig.DUMMY EmbeddedUiConfig.DUMMY
Surface( Scaffold(
modifier = Modifier.fillMaxSize(), modifier = Modifier
color = STREAMSELECT_UI_BACKGROUND_COLOR .fillMaxSize()
) { .windowInsetsPadding(insets),
Scaffold( containerColor = Color.Transparent,
modifier = Modifier topBar = {
.fillMaxSize() if (isChapterSelect) {
.windowInsetsPadding(insets), ChapterSelectTopBar(
containerColor = Color.Transparent, onClose = {
topBar = { viewModel.changeUiMode(
if (isChapterSelect) { uiState.uiMode.getNextModeWhenBackPressed() ?: uiState.uiMode,
ChapterSelectTopBar( embeddedUiConfig
onClose = { )
viewModel.changeUiMode(
uiState.uiMode.getUiHiddenState(),
embeddedUiConfig
)
}
)
} else {
StreamSelectTopBar(viewModel = viewModel, uiState = uiState)
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
if (isChapterSelect) {
LazyColumn(
modifier = Modifier
.padding(start = 5.dp, end = 5.dp)
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(5.dp),
) {
items(uiState.chapters.size) { chapterIndex ->
val chapter = uiState.chapters[chapterIndex]
ChapterItem(
id = chapterIndex,
chapterTitle = chapter.chapterTitle ?: "",
chapterStartInMs = chapter.chapterStartInMs,
thumbnail = chapter.thumbnail,
onClicked = {
viewModel.chapterSelected(chapterIndex)
},
isCurrentChapter = isActiveChapter(
chapterIndex,
uiState.chapters,
uiState.playbackPositionInMs
)
)
}
} }
} else { )
ReorderableStreamItemsList( } else {
padding = PaddingValues(start = 5.dp, end = 5.dp), StreamSelectTopBar(viewModel = viewModel, uiState = uiState)
viewModel = viewModel, }
uiState = uiState }
) ) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
if (isChapterSelect) {
LazyColumn(
modifier = Modifier
.padding(start = 5.dp, end = 5.dp)
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(5.dp),
) {
items(uiState.chapters.size) { chapterIndex ->
val chapter = uiState.chapters[chapterIndex]
ChapterItem(
id = chapterIndex,
chapterTitle = chapter.chapterTitle ?: "",
chapterStartInMs = chapter.chapterStartInMs,
thumbnail = chapter.thumbnail,
onClicked = {
viewModel.chapterSelected(chapterIndex)
},
isCurrentChapter = isActiveChapter(
chapterIndex,
uiState.chapters,
uiState.playbackPositionInMs
)
)
}
} }
} else {
ReorderableStreamItemsList(
padding = PaddingValues(start = 5.dp, end = 5.dp),
viewModel = viewModel,
uiState = uiState
)
} }
} }
} }
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)

View File

@ -109,15 +109,24 @@ fun VideoPlayerUi(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
) )
AnimatedVisibility(visible = uiState.uiMode.isStreamSelect) { AnimatedVisibility(visible = uiState.uiMode.isStreamSelect) {
StreamSelectUI( Surface(
viewModel = viewModel, modifier = Modifier.fillMaxSize(),
uiState = uiState, color = STREAMSELECT_UI_BACKGROUND_COLOR
isChapterSelect = false ) {
) StreamSelectUI(
viewModel = viewModel,
uiState = uiState,
isChapterSelect = false
)
}
} }
AnimatedVisibility(visible = uiState.uiMode.isChapterSelect) { AnimatedVisibility(visible = uiState.uiMode.isChapterSelect) {
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true) Surface(
modifier = Modifier.fillMaxSize(),
color = STREAMSELECT_UI_BACKGROUND_COLOR
) {
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true)
}
} }
} }
} }