add chapter/stream selection to audio ui
This commit is contained in:
parent
afceb43308
commit
a4f8e490ae
|
@ -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(),
|
||||||
|
|
|
@ -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)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue