Improve codebase

This commit is contained in:
vfsfitvnm 2022-07-16 20:43:00 +02:00
parent 0372d8b406
commit e6b5c68ad1
6 changed files with 993 additions and 1039 deletions

View file

@ -0,0 +1,99 @@
package it.vfsfitvnm.vimusic.ui.components.themed
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.medium
@Composable
fun DropDownSection(content: @Composable ColumnScope.() -> Unit) {
val (colorPalette) = LocalAppearance.current
Column(
modifier = Modifier
.shadow(
elevation = 2.dp,
shape = RoundedCornerShape(16.dp)
)
.background(colorPalette.elevatedBackground)
.width(IntrinsicSize.Max),
content = content
)
}
@Composable
fun DropDownSectionSpacer() {
Spacer(
modifier = Modifier
.height(4.dp)
)
}
@Composable
fun DropDownTextItem(
text: String,
isSelected: Boolean,
onClick: () -> Unit
) {
val (colorPalette) = LocalAppearance.current
DropDownTextItem(
text = text,
textColor = if (isSelected) {
colorPalette.onPrimaryContainer
} else {
colorPalette.textSecondary
},
backgroundColor = if (isSelected) {
colorPalette.primaryContainer
} else {
colorPalette.elevatedBackground
},
onClick = onClick
)
}
@Composable
fun DropDownTextItem(
text: String,
backgroundColor: Color? = null,
textColor: Color? = null,
onClick: () -> Unit
) {
val (colorPalette, typography) = LocalAppearance.current
BasicText(
text = text,
style = typography.xxs.medium.copy(
color = textColor ?: colorPalette.text,
letterSpacing = 1.sp
),
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = onClick
)
.background(backgroundColor ?: colorPalette.elevatedBackground)
.fillMaxWidth()
.widthIn(min = 124.dp, max = 248.dp)
.padding(
horizontal = 16.dp,
vertical = 8.dp
)
)
}

View file

@ -0,0 +1,219 @@
package it.vfsfitvnm.vimusic.ui.views
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.BasicText
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import coil.compose.SubcomposeAsyncImage
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.enums.AlbumSortBy
import it.vfsfitvnm.vimusic.enums.SortOrder
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
import it.vfsfitvnm.vimusic.models.Album
import it.vfsfitvnm.vimusic.ui.components.themed.DropDownSection
import it.vfsfitvnm.vimusic.ui.components.themed.DropDownSectionSpacer
import it.vfsfitvnm.vimusic.ui.components.themed.DropDownTextItem
import it.vfsfitvnm.vimusic.ui.components.themed.DropdownMenu
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.rememberPreference
import it.vfsfitvnm.vimusic.utils.secondary
import it.vfsfitvnm.vimusic.utils.semiBold
import it.vfsfitvnm.vimusic.utils.thumbnail
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged
@ExperimentalFoundationApi
@Composable
fun AlbumsTab(
onAlbumClicked: (Album) -> Unit
) {
val (colorPalette, typography) = LocalAppearance.current
var sortBy by rememberPreference("albumSortBy", AlbumSortBy.DateAdded)
var sortOrder by rememberPreference("albumSortOrder", SortOrder.Descending)
val albums by remember(sortBy, sortOrder) {
Database.albums(sortBy, sortOrder).distinctUntilChanged()
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
val thumbnailSizePx = with(LocalDensity.current) { Dimensions.thumbnails.song.roundToPx() }
Box {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
modifier = Modifier
.background(
Brush.verticalGradient(
listOf(
colorPalette.background,
Color.Transparent
)
)
)
.fillMaxWidth()
.zIndex(1f)
.padding(horizontal = 8.dp)
) {
Box {
var isSortMenuDisplayed by remember {
mutableStateOf(false)
}
Image(
painter = painterResource(R.drawable.sort),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
isSortMenuDisplayed = true
}
.padding(horizontal = 8.dp, vertical = 8.dp)
.size(20.dp)
)
DropdownMenu(
isDisplayed = isSortMenuDisplayed,
onDismissRequest = {
isSortMenuDisplayed = false
}
) {
DropDownSection {
DropDownTextItem(
text = "NAME",
isSelected = sortBy == AlbumSortBy.Title,
onClick = {
isSortMenuDisplayed = false
sortBy = AlbumSortBy.Title
}
)
DropDownTextItem(
text = "YEAR",
isSelected = sortBy == AlbumSortBy.Year,
onClick = {
isSortMenuDisplayed = false
sortBy = AlbumSortBy.Year
}
)
DropDownTextItem(
text = "DATE ADDED",
isSelected = sortBy == AlbumSortBy.DateAdded,
onClick = {
isSortMenuDisplayed = false
sortBy = AlbumSortBy.DateAdded
}
)
}
DropDownSectionSpacer()
DropDownSection {
DropDownTextItem(
text = when (sortOrder) {
SortOrder.Ascending -> "ASCENDING"
SortOrder.Descending -> "DESCENDING"
},
onClick = {
isSortMenuDisplayed = false
sortOrder = !sortOrder
}
)
}
}
}
}
LazyColumn(contentPadding = PaddingValues(top = 36.dp)) {
items(
items = albums,
key = Album::id
) { album ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { onAlbumClicked(album) }
)
.animateItemPlacement()
.fillMaxWidth()
.padding(vertical = 5.dp)
.padding(start = 16.dp, end = 16.dp)
) {
SubcomposeAsyncImage(
model = album.thumbnailUrl?.thumbnail(thumbnailSizePx),
contentDescription = null,
error = {
Box {
Image(
painter = painterResource(R.drawable.disc),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.textSecondary),
modifier = Modifier
.align(Alignment.Center)
.size(36.dp)
)
}
},
modifier = Modifier
.clip(ThumbnailRoundness.shape)
.size(Dimensions.thumbnails.song)
)
Column(
modifier = Modifier
.weight(1f)
) {
BasicText(
text = album.title ?: "Unknown",
style = typography.xs.semiBold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
album.authorsText?.let {
BasicText(
text = album.authorsText,
style = typography.xs.semiBold.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
album.year?.let {
BasicText(
text = album.year,
style = typography.xxs.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}
}
}

View file

@ -0,0 +1,189 @@
package it.vfsfitvnm.vimusic.ui.views
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import coil.compose.SubcomposeAsyncImage
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.enums.ArtistSortBy
import it.vfsfitvnm.vimusic.enums.SortOrder
import it.vfsfitvnm.vimusic.models.Artist
import it.vfsfitvnm.vimusic.ui.components.themed.DropDownSection
import it.vfsfitvnm.vimusic.ui.components.themed.DropDownSectionSpacer
import it.vfsfitvnm.vimusic.ui.components.themed.DropDownTextItem
import it.vfsfitvnm.vimusic.ui.components.themed.DropdownMenu
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.rememberPreference
import it.vfsfitvnm.vimusic.utils.semiBold
import it.vfsfitvnm.vimusic.utils.thumbnail
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged
@ExperimentalFoundationApi
@Composable
fun ArtistsTab(
onArtistClicked: (Artist) -> Unit
) {
val (colorPalette, typography) = LocalAppearance.current
var sortBy by rememberPreference("artistSortBy", ArtistSortBy.Name)
var sortOrder by rememberPreference("artistSortOrder", SortOrder.Ascending)
val artists by remember(sortBy, sortOrder) {
Database.artists(sortBy, sortOrder).distinctUntilChanged()
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
val thumbnailSizePx = with(LocalDensity.current) { Dimensions.thumbnails.song.roundToPx() }
Box {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
modifier = Modifier
.background(
Brush.verticalGradient(
listOf(
colorPalette.background,
Color.Transparent
)
)
)
.fillMaxWidth()
.zIndex(1f)
.padding(horizontal = 8.dp)
) {
Box {
var isSortMenuDisplayed by remember {
mutableStateOf(false)
}
Image(
painter = painterResource(R.drawable.sort),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
isSortMenuDisplayed = true
}
.padding(horizontal = 8.dp, vertical = 8.dp)
.size(20.dp)
)
DropdownMenu(
isDisplayed = isSortMenuDisplayed,
onDismissRequest = {
isSortMenuDisplayed = false
}
) {
DropDownSection {
DropDownTextItem(
text = "NAME",
isSelected = sortBy == ArtistSortBy.Name,
onClick = {
isSortMenuDisplayed = false
sortBy = ArtistSortBy.Name
}
)
DropDownTextItem(
text = "DATE ADDED",
isSelected = sortBy == ArtistSortBy.DateAdded,
onClick = {
isSortMenuDisplayed = false
sortBy = ArtistSortBy.DateAdded
}
)
}
DropDownSectionSpacer()
DropDownSection {
DropDownTextItem(
text = when (sortOrder) {
SortOrder.Ascending -> "ASCENDING"
SortOrder.Descending -> "DESCENDING"
},
onClick = {
isSortMenuDisplayed = false
sortOrder = !sortOrder
}
)
}
}
}
}
LazyColumn(contentPadding = PaddingValues(top = 36.dp)) {
items(
items = artists,
key = Artist::id
) { artist ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { onArtistClicked(artist) }
)
.animateItemPlacement()
.fillMaxWidth()
.padding(vertical = 5.dp)
.padding(start = 16.dp, end = 16.dp)
) {
SubcomposeAsyncImage(
model = artist.thumbnailUrl?.thumbnail(thumbnailSizePx),
contentDescription = null,
error = {
Box {
Image(
painter = painterResource(R.drawable.person),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.textSecondary),
modifier = Modifier
.align(Alignment.Center)
.size(24.dp)
)
}
},
modifier = Modifier
.clip(CircleShape)
.size(Dimensions.thumbnails.song)
)
BasicText(
text = artist.name,
style = typography.xs.semiBold,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.weight(1f)
)
}
}
}
}
}

View file

@ -0,0 +1,216 @@
package it.vfsfitvnm.vimusic.ui.views
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.enums.BuiltInPlaylist
import it.vfsfitvnm.vimusic.enums.PlaylistSortBy
import it.vfsfitvnm.vimusic.enums.SortOrder
import it.vfsfitvnm.vimusic.models.Playlist
import it.vfsfitvnm.vimusic.query
import it.vfsfitvnm.vimusic.ui.components.themed.*
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.isCachedPlaylistShownKey
import it.vfsfitvnm.vimusic.utils.rememberPreference
import kotlinx.coroutines.Dispatchers
@ExperimentalFoundationApi
@Composable
fun PlaylistsTab(
onBuiltInPlaylistClicked: (BuiltInPlaylist) -> Unit,
onPlaylistClicked: (Playlist) -> Unit,
) {
val (colorPalette, typography) = LocalAppearance.current
val isCachedPlaylistShown by rememberPreference(isCachedPlaylistShownKey, false)
var sortBy by rememberPreference("playlistSortBy", PlaylistSortBy.DateAdded)
var sortOrder by rememberPreference("playlistSortOrder", SortOrder.Ascending)
val playlistPreviews by remember(sortBy, sortOrder) {
Database.playlistPreviews(sortBy, sortOrder)
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
var isCreatingANewPlaylist by rememberSaveable {
mutableStateOf(false)
}
if (isCreatingANewPlaylist) {
TextFieldDialog(
hintText = "Enter the playlist name",
onDismiss = {
isCreatingANewPlaylist = false
},
onDone = { text ->
query {
Database.insert(Playlist(name = text))
}
}
)
}
Box {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
modifier = Modifier
.background(
Brush.verticalGradient(
listOf(
colorPalette.background,
Color.Transparent
)
)
)
.fillMaxWidth()
.zIndex(1f)
.padding(horizontal = 8.dp)
) {
Image(
painter = painterResource(R.drawable.add),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
isCreatingANewPlaylist = true
}
.padding(horizontal = 8.dp, vertical = 8.dp)
.size(20.dp)
)
Box {
var isSortMenuDisplayed by remember {
mutableStateOf(false)
}
Image(
painter = painterResource(R.drawable.sort),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
isSortMenuDisplayed = true
}
.padding(horizontal = 8.dp, vertical = 8.dp)
.size(20.dp)
)
DropdownMenu(
isDisplayed = isSortMenuDisplayed,
onDismissRequest = {
isSortMenuDisplayed = false
}
) {
DropDownSection {
DropDownTextItem(
text = "NAME",
isSelected = sortBy == PlaylistSortBy.Name,
onClick = {
isSortMenuDisplayed = false
sortBy = PlaylistSortBy.Name
}
)
DropDownTextItem(
text = "DATE ADDED",
isSelected = sortBy == PlaylistSortBy.DateAdded,
onClick = {
isSortMenuDisplayed = false
sortBy = PlaylistSortBy.DateAdded
}
)
DropDownTextItem(
text = "SONG COUNT",
isSelected = sortBy == PlaylistSortBy.SongCount,
onClick = {
isSortMenuDisplayed = false
sortBy = PlaylistSortBy.SongCount
}
)
}
DropDownSectionSpacer()
DropDownSection {
DropDownTextItem(
text = when (sortOrder) {
SortOrder.Ascending -> "ASCENDING"
SortOrder.Descending -> "DESCENDING"
},
onClick = {
isSortMenuDisplayed = false
sortOrder = !sortOrder
}
)
}
}
}
}
LazyColumn(contentPadding = PaddingValues(top = 36.dp)) {
item(key = "favorites") {
BuiltInPlaylistItem(
icon = R.drawable.heart,
colorTint = colorPalette.red,
name = "Favorites",
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { onBuiltInPlaylistClicked(BuiltInPlaylist.Favorites) }
)
)
}
if (isCachedPlaylistShown) {
item(key = "cached") {
BuiltInPlaylistItem(
icon = R.drawable.download,
colorTint = colorPalette.blue,
name = "Cached",
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { onBuiltInPlaylistClicked(BuiltInPlaylist.Cached) }
)
.animateItemPlacement()
)
}
}
items(
items = playlistPreviews,
key = { it.playlist.id }
) { playlistPreview ->
PlaylistPreviewItem(
playlistPreview = playlistPreview,
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { onPlaylistClicked(playlistPreview.playlist) }
)
.animateItemPlacement()
)
}
}
}
}

View file

@ -0,0 +1,216 @@
package it.vfsfitvnm.vimusic.ui.views
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.enums.SongSortBy
import it.vfsfitvnm.vimusic.enums.SortOrder
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
import it.vfsfitvnm.vimusic.models.DetailedSong
import it.vfsfitvnm.vimusic.ui.components.themed.*
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.ui.styling.px
import it.vfsfitvnm.vimusic.utils.*
import kotlinx.coroutines.Dispatchers
@ExperimentalFoundationApi
@ExperimentalAnimationApi
@Composable
fun SongsTab() {
val (colorPalette, typography) = LocalAppearance.current
var sortBy by rememberPreference("songSortBy", SongSortBy.DateAdded)
var sortOrder by rememberPreference("songSortOrder", SortOrder.Ascending)
val songs by remember(sortBy, sortOrder) {
Database.songs(sortBy, sortOrder)
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
Box {
val binder = LocalPlayerServiceBinder.current
val thumbnailSize = Dimensions.thumbnails.song.px
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
modifier = Modifier
.background(
Brush.verticalGradient(
listOf(
colorPalette.background,
Color.Transparent
)
)
)
.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)
)
Box {
var isSortMenuDisplayed by remember {
mutableStateOf(false)
}
Image(
painter = painterResource(R.drawable.sort),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
isSortMenuDisplayed = true
}
.padding(horizontal = 8.dp, vertical = 8.dp)
.size(20.dp)
)
DropdownMenu(
isDisplayed = isSortMenuDisplayed,
onDismissRequest = {
isSortMenuDisplayed = false
}
) {
DropDownSection {
DropDownTextItem(
text = "PLAY TIME",
isSelected = sortBy == SongSortBy.PlayTime,
onClick = {
isSortMenuDisplayed = false
sortBy = SongSortBy.PlayTime
}
)
DropDownTextItem(
text = "TITLE",
isSelected = sortBy == SongSortBy.Title,
onClick = {
isSortMenuDisplayed = false
sortBy = SongSortBy.Title
}
)
DropDownTextItem(
text = "DATE ADDED",
isSelected = sortBy == SongSortBy.DateAdded,
onClick = {
isSortMenuDisplayed = false
sortBy = SongSortBy.DateAdded
}
)
}
DropDownSectionSpacer()
DropDownSection {
DropDownTextItem(
text = when (sortOrder) {
SortOrder.Ascending -> "ASCENDING"
SortOrder.Descending -> "DESCENDING"
},
onClick = {
isSortMenuDisplayed = false
sortOrder = !sortOrder
}
)
}
}
}
}
LazyColumn(contentPadding = PaddingValues(top = 36.dp)) {
itemsIndexed(
items = songs,
key = { _, song -> song.song.id }
) { index, song ->
SongItem(
song = song,
thumbnailSize = thumbnailSize,
onClick = {
binder?.stopRadio()
binder?.player?.forcePlayAtIndex(
songs.map(DetailedSong::asMediaItem),
index
)
},
menuContent = {
InHistoryMediaItemMenu(song = song)
},
onThumbnailContent = {
AnimatedVisibility(
visible = sortBy == SongSortBy.PlayTime,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.align(Alignment.BottomCenter)
) {
BasicText(
text = song.song.formattedTotalPlayTime,
style = typography.xxs.semiBold.center.color(
Color.White
),
maxLines = 2,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.fillMaxWidth()
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Black.copy(alpha = 0.75f)
)
),
shape = ThumbnailRoundness.shape
)
.padding(
horizontal = 8.dp,
vertical = 4.dp
)
)
}
},
modifier = Modifier
.animateItemPlacement()
)
}
}
}
}