Tweak PlaylistScreen, LocalPlaylistScreen and BuiltInPlaylistScreen UI
This commit is contained in:
@@ -192,7 +192,6 @@ fun AlbumScreen(browseId: String) {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.zIndex(1f)
|
.zIndex(1f)
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 8.dp)
|
||||||
// .padding(top = 8.dp)
|
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.shuffle),
|
painter = painterResource(R.drawable.shuffle),
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.foundation.text.BasicText
|
import androidx.compose.foundation.text.BasicText
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -23,10 +23,10 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
@@ -102,6 +102,55 @@ fun BuiltInPlaylistScreen(builtInPlaylist: BuiltInPlaylist) {
|
|||||||
.padding(vertical = 8.dp, horizontal = 16.dp)
|
.padding(vertical = 8.dp, horizontal = 16.dp)
|
||||||
.size(24.dp)
|
.size(24.dp)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 16.dp, bottom = 8.dp)
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
BasicText(
|
||||||
|
text = when (builtInPlaylist) {
|
||||||
|
BuiltInPlaylist.Favorites -> "Favorites"
|
||||||
|
BuiltInPlaylist.Cached -> "Offline"
|
||||||
|
},
|
||||||
|
style = typography.m.semiBold
|
||||||
|
)
|
||||||
|
|
||||||
|
BasicText(
|
||||||
|
text = "${songs.size} songs",
|
||||||
|
style = typography.xxs.semiBold.secondary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.End,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.zIndex(1f)
|
||||||
|
.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.shuffle),
|
||||||
|
contentDescription = null,
|
||||||
|
colorFilter = ColorFilter.tint(colorPalette.text),
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable(enabled = songs.isNotEmpty()) {
|
||||||
|
binder?.stopRadio()
|
||||||
|
binder?.player?.forcePlayFromBeginning(
|
||||||
|
songs
|
||||||
|
.shuffled()
|
||||||
|
.map(DetailedSong::asMediaItem)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||||
|
.size(20.dp)
|
||||||
|
)
|
||||||
|
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.ellipsis_horizontal),
|
painter = painterResource(R.drawable.ellipsis_horizontal),
|
||||||
@@ -123,87 +172,9 @@ fun BuiltInPlaylistScreen(builtInPlaylist: BuiltInPlaylist) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||||
.size(24.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(top = 16.dp, bottom = 32.dp)
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
) {
|
|
||||||
BasicText(
|
|
||||||
text = when (builtInPlaylist) {
|
|
||||||
BuiltInPlaylist.Favorites -> "Favorites"
|
|
||||||
BuiltInPlaylist.Cached -> "Offline"
|
|
||||||
},
|
|
||||||
style = typography.m.semiBold
|
|
||||||
)
|
|
||||||
|
|
||||||
BasicText(
|
|
||||||
text = "${songs.size} songs",
|
|
||||||
style = typography.xxs.semiBold.secondary
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.shuffle),
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
binder?.stopRadio()
|
|
||||||
binder?.player?.forcePlayFromBeginning(
|
|
||||||
songs
|
|
||||||
.map(DetailedSong::asMediaItem)
|
|
||||||
.shuffled()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.shadow(elevation = 2.dp, shape = CircleShape)
|
|
||||||
.background(
|
|
||||||
color = colorPalette.elevatedBackground,
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
|
||||||
.size(20.dp)
|
.size(20.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.play),
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
binder?.stopRadio()
|
|
||||||
binder?.player?.forcePlayFromBeginning(
|
|
||||||
songs.map(
|
|
||||||
DetailedSong::asMediaItem
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.shadow(elevation = 2.dp, shape = CircleShape)
|
|
||||||
.background(
|
|
||||||
color = colorPalette.elevatedBackground,
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
|
||||||
.size(20.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.foundation.text.BasicText
|
import androidx.compose.foundation.text.BasicText
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -26,12 +26,12 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
import it.vfsfitvnm.reordering.rememberReorderingState
|
import it.vfsfitvnm.reordering.rememberReorderingState
|
||||||
import it.vfsfitvnm.reordering.verticalDragAfterLongPressToReorder
|
import it.vfsfitvnm.reordering.verticalDragAfterLongPressToReorder
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
@@ -145,6 +145,52 @@ fun LocalPlaylistScreen(playlistId: Long) {
|
|||||||
.padding(vertical = 8.dp, horizontal = 16.dp)
|
.padding(vertical = 8.dp, horizontal = 16.dp)
|
||||||
.size(24.dp)
|
.size(24.dp)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 16.dp, bottom = 8.dp)
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
BasicText(
|
||||||
|
text = playlistWithSongs.playlist.name,
|
||||||
|
style = typography.m.semiBold
|
||||||
|
)
|
||||||
|
|
||||||
|
BasicText(
|
||||||
|
text = "${playlistWithSongs.songs.size} songs",
|
||||||
|
style = typography.xxs.semiBold.secondary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.End,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.zIndex(1f)
|
||||||
|
.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.shuffle),
|
||||||
|
contentDescription = null,
|
||||||
|
colorFilter = ColorFilter.tint(colorPalette.text),
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable(enabled = playlistWithSongs.songs.isNotEmpty()) {
|
||||||
|
binder?.stopRadio()
|
||||||
|
binder?.player?.forcePlayFromBeginning(
|
||||||
|
playlistWithSongs.songs
|
||||||
|
.shuffled()
|
||||||
|
.map(DetailedSong::asMediaItem)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||||
|
.size(20.dp)
|
||||||
|
)
|
||||||
|
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.ellipsis_horizontal),
|
painter = painterResource(R.drawable.ellipsis_horizontal),
|
||||||
@@ -188,86 +234,9 @@ fun LocalPlaylistScreen(playlistId: Long) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||||
.size(24.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(top = 16.dp, bottom = 32.dp)
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
) {
|
|
||||||
BasicText(
|
|
||||||
text = playlistWithSongs.playlist.name,
|
|
||||||
style = typography.m.semiBold
|
|
||||||
)
|
|
||||||
|
|
||||||
BasicText(
|
|
||||||
text = "${playlistWithSongs.songs.size} songs",
|
|
||||||
style = typography.xxs.semiBold.secondary
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.shuffle),
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
binder?.stopRadio()
|
|
||||||
binder?.player?.forcePlayFromBeginning(
|
|
||||||
playlistWithSongs.songs
|
|
||||||
.map(
|
|
||||||
DetailedSong::asMediaItem
|
|
||||||
)
|
|
||||||
.shuffled()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.shadow(elevation = 2.dp, shape = CircleShape)
|
|
||||||
.background(
|
|
||||||
color = colorPalette.elevatedBackground,
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
|
||||||
.size(20.dp)
|
.size(20.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.play),
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
binder?.stopRadio()
|
|
||||||
binder?.player?.forcePlayFromBeginning(
|
|
||||||
playlistWithSongs.songs.map(
|
|
||||||
DetailedSong::asMediaItem
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.shadow(elevation = 2.dp, shape = CircleShape)
|
|
||||||
.background(
|
|
||||||
color = colorPalette.elevatedBackground,
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
|
||||||
.size(20.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
@@ -125,6 +125,90 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.size(24.dp)
|
.size(24.dp)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
playlist?.getOrNull()?.let { playlist ->
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(IntrinsicSize.Max)
|
||||||
|
.padding(vertical = 8.dp, horizontal = 16.dp)
|
||||||
|
.padding(bottom = 8.dp)
|
||||||
|
) {
|
||||||
|
AsyncImage(
|
||||||
|
model = playlist.thumbnail?.size(thumbnailSizePx),
|
||||||
|
contentDescription = null,
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(ThumbnailRoundness.shape)
|
||||||
|
.size(Dimensions.thumbnails.playlist)
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
BasicText(
|
||||||
|
text = playlist.title ?: "Unknown",
|
||||||
|
style = typography.m.semiBold
|
||||||
|
)
|
||||||
|
|
||||||
|
BasicText(
|
||||||
|
text = playlist.authors?.joinToString("") { it.name }
|
||||||
|
?: "",
|
||||||
|
style = typography.xs.secondary.semiBold,
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
playlist.year?.let { year ->
|
||||||
|
BasicText(
|
||||||
|
text = year,
|
||||||
|
style = typography.xs.secondary,
|
||||||
|
maxLines = 1,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.End,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.zIndex(1f)
|
||||||
|
.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.shuffle),
|
||||||
|
contentDescription = null,
|
||||||
|
colorFilter = ColorFilter.tint(colorPalette.text),
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable {
|
||||||
|
binder?.stopRadio()
|
||||||
|
playlist.items
|
||||||
|
?.shuffled()
|
||||||
|
?.mapNotNull { song ->
|
||||||
|
song.toMediaItem(browseId, playlist)
|
||||||
|
}
|
||||||
|
?.let { mediaItems ->
|
||||||
|
binder?.player?.forcePlayFromBeginning(
|
||||||
|
mediaItems
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||||
|
.size(20.dp)
|
||||||
|
)
|
||||||
|
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.ellipsis_horizontal),
|
painter = painterResource(R.drawable.ellipsis_horizontal),
|
||||||
@@ -139,14 +223,11 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
text = "Enqueue",
|
text = "Enqueue",
|
||||||
onClick = {
|
onClick = {
|
||||||
menuState.hide()
|
menuState.hide()
|
||||||
playlist
|
playlist.items
|
||||||
?.getOrNull()
|
|
||||||
?.let { album ->
|
|
||||||
album.items
|
|
||||||
?.mapNotNull { song ->
|
?.mapNotNull { song ->
|
||||||
song.toMediaItem(
|
song.toMediaItem(
|
||||||
browseId,
|
browseId,
|
||||||
album
|
playlist
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
?.let { mediaItems ->
|
?.let { mediaItems ->
|
||||||
@@ -155,7 +236,6 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
MenuEntry(
|
MenuEntry(
|
||||||
@@ -163,24 +243,20 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
text = "Import",
|
text = "Import",
|
||||||
onClick = {
|
onClick = {
|
||||||
menuState.hide()
|
menuState.hide()
|
||||||
|
|
||||||
playlist
|
|
||||||
?.getOrNull()
|
|
||||||
?.let { album ->
|
|
||||||
transaction {
|
transaction {
|
||||||
val playlistId =
|
val playlistId =
|
||||||
Database.insert(
|
Database.insert(
|
||||||
Playlist(
|
Playlist(
|
||||||
name = album.title
|
name = playlist.title
|
||||||
?: "Unknown"
|
?: "Unknown"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
album.items?.forEachIndexed { index, song ->
|
playlist.items?.forEachIndexed { index, song ->
|
||||||
song
|
song
|
||||||
.toMediaItem(
|
.toMediaItem(
|
||||||
browseId,
|
browseId,
|
||||||
album
|
playlist
|
||||||
)
|
)
|
||||||
?.let { mediaItem ->
|
?.let { mediaItem ->
|
||||||
Database.insert(
|
Database.insert(
|
||||||
@@ -198,7 +274,6 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
MenuEntry(
|
MenuEntry(
|
||||||
@@ -207,7 +282,7 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
onClick = {
|
onClick = {
|
||||||
menuState.hide()
|
menuState.hide()
|
||||||
|
|
||||||
(playlist?.getOrNull()?.url
|
(playlist.url
|
||||||
?: "https://music.youtube.com/playlist?list=${
|
?: "https://music.youtube.com/playlist?list=${
|
||||||
browseId.removePrefix(
|
browseId.removePrefix(
|
||||||
"VL"
|
"VL"
|
||||||
@@ -231,117 +306,9 @@ fun PlaylistScreen(browseId: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||||
.size(24.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
|
||||||
playlist?.getOrNull()?.let { playlist ->
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(IntrinsicSize.Max)
|
|
||||||
.padding(vertical = 8.dp, horizontal = 16.dp)
|
|
||||||
.padding(bottom = 16.dp)
|
|
||||||
) {
|
|
||||||
AsyncImage(
|
|
||||||
model = playlist.thumbnail?.size(thumbnailSizePx),
|
|
||||||
contentDescription = null,
|
|
||||||
contentScale = ContentScale.Crop,
|
|
||||||
modifier = Modifier
|
|
||||||
.clip(ThumbnailRoundness.shape)
|
|
||||||
.size(Dimensions.thumbnails.playlist)
|
|
||||||
)
|
|
||||||
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.SpaceEvenly,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
|
||||||
Column {
|
|
||||||
BasicText(
|
|
||||||
text = playlist.title ?: "Unknown",
|
|
||||||
style = typography.m.semiBold
|
|
||||||
)
|
|
||||||
|
|
||||||
BasicText(
|
|
||||||
text = buildString {
|
|
||||||
val authors =
|
|
||||||
playlist.authors?.joinToString("") { it.name }
|
|
||||||
append(authors)
|
|
||||||
if (authors?.isNotEmpty() == true && playlist.year != null) {
|
|
||||||
append(" • ")
|
|
||||||
}
|
|
||||||
append(playlist.year)
|
|
||||||
},
|
|
||||||
style = typography.xs.secondary.semiBold,
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.End)
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.shuffle),
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
binder?.stopRadio()
|
|
||||||
playlist.items
|
|
||||||
?.shuffled()
|
|
||||||
?.mapNotNull { song ->
|
|
||||||
song.toMediaItem(browseId, playlist)
|
|
||||||
}
|
|
||||||
?.let { mediaItems ->
|
|
||||||
binder?.player?.forcePlayFromBeginning(
|
|
||||||
mediaItems
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.shadow(elevation = 2.dp, shape = CircleShape)
|
|
||||||
.background(
|
|
||||||
color = colorPalette.elevatedBackground,
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
|
||||||
.size(20.dp)
|
.size(20.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.play),
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
binder?.stopRadio()
|
|
||||||
playlist.items
|
|
||||||
?.mapNotNull { song ->
|
|
||||||
song.toMediaItem(browseId, playlist)
|
|
||||||
}
|
|
||||||
?.let { mediaItems ->
|
|
||||||
binder?.player?.forcePlayFromBeginning(
|
|
||||||
mediaItems
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.shadow(elevation = 2.dp, shape = CircleShape)
|
|
||||||
.background(
|
|
||||||
color = colorPalette.elevatedBackground,
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
|
||||||
.size(20.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} ?: playlist?.exceptionOrNull()?.let { throwable ->
|
} ?: playlist?.exceptionOrNull()?.let { throwable ->
|
||||||
|
|||||||
Reference in New Issue
Block a user