Create PrimaryButton composable

This commit is contained in:
vfsfitvnm 2022-09-28 16:49:41 +02:00
parent c03a3bcc03
commit 42a4d5b43e
7 changed files with 102 additions and 345 deletions

View file

@ -0,0 +1,50 @@
package it.vfsfitvnm.vimusic.ui.components.themed
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import it.vfsfitvnm.vimusic.LocalPlayerAwarePaddingValues
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
@Composable
fun BoxScope.PrimaryButton(
onClick: () -> Unit,
@DrawableRes iconId: Int,
modifier: Modifier = Modifier,
isEnabled: Boolean = true,
) {
val (colorPalette) = LocalAppearance.current
Box(
modifier = modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.padding(LocalPlayerAwarePaddingValues.current)
.clip(RoundedCornerShape(16.dp))
.clickable(enabled = isEnabled, onClick = onClick)
.background(colorPalette.background2)
.size(62.dp)
) {
Image(
painter = painterResource(iconId),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
}

View file

@ -1,6 +1,7 @@
package it.vfsfitvnm.vimusic.ui.components.themed
import android.annotation.SuppressLint
import androidx.annotation.DrawableRes
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.AnimatedVisibilityScope
@ -13,6 +14,7 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
@ -85,25 +87,10 @@ fun Scaffold(
}
primaryIconButtonId?.let {
Box(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.padding(LocalPlayerAwarePaddingValues.current)
.clip(RoundedCornerShape(16.dp))
.clickable(onClick = onPrimaryIconButtonClick)
.background(colorPalette.background2)
.size(62.dp)
) {
Image(
painter = painterResource(primaryIconButtonId),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
PrimaryButton(
iconId = primaryIconButtonId,
onClick = onPrimaryIconButtonClick
)
}
}
}

View file

@ -48,6 +48,7 @@ import it.vfsfitvnm.vimusic.savers.DetailedSongListSaver
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderPlaceholder
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
@ -266,32 +267,16 @@ fun AlbumOverview(
}
}
Box(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.padding(LocalPlayerAwarePaddingValues.current)
.clip(RoundedCornerShape(16.dp))
.clickable(enabled = songs.isNotEmpty()) {
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(
songs
.shuffled()
.map(DetailedSong::asMediaItem)
)
}
.background(colorPalette.background2)
.size(62.dp)
) {
Image(
painter = painterResource(R.drawable.shuffle),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
PrimaryButton(
iconId = R.drawable.shuffle,
isEnabled = songs.isNotEmpty(),
onClick = {
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(
songs.shuffled().map(DetailedSong::asMediaItem)
)
}
)
} ?: albumResult?.exceptionOrNull()?.let {
Box(
modifier = Modifier

View file

@ -73,226 +73,4 @@ fun ArtistOverview(
val (colorPalette, typography, thumbnailShape) = LocalAppearance.current
val binder = LocalPlayerServiceBinder.current
val context = LocalContext.current
// BoxWithConstraints {
// val thumbnailSizeDp = maxWidth - Dimensions.verticalBarWidth
// val thumbnailSizePx = (thumbnailSizeDp - 32.dp).px
//
// viewModel.result?.getOrNull()?.let { albumWithSongs ->
// LazyColumn(
// contentPadding = LocalPlayerAwarePaddingValues.current,
// modifier = Modifier
// .background(colorPalette.background0)
// .fillMaxSize()
// ) {
// item(
// key = "header",
// contentType = 0
// ) {
// Column {
// Header(title = albumWithSongs.album.title ?: "Unknown") {
// if (albumWithSongs.songs.isNotEmpty()) {
// BasicText(
// text = "Enqueue",
// style = typography.xxs.medium,
// modifier = Modifier
// .clip(RoundedCornerShape(16.dp))
// .clickable {
// binder?.player?.enqueue(
// albumWithSongs.songs.map(DetailedSong::asMediaItem)
// )
// }
// .background(colorPalette.background2)
// .padding(all = 8.dp)
// .padding(horizontal = 8.dp)
// )
// }
//
// Spacer(
// modifier = Modifier
// .weight(1f)
// )
//
// Image(
// painter = painterResource(
// if (albumWithSongs.album.bookmarkedAt == null) {
// R.drawable.bookmark_outline
// } else {
// R.drawable.bookmark
// }
// ),
// contentDescription = null,
// colorFilter = ColorFilter.tint(colorPalette.accent),
// modifier = Modifier
// .clickable {
// query {
// Database.update(
// albumWithSongs.album.copy(
// bookmarkedAt = if (albumWithSongs.album.bookmarkedAt == null) {
// System.currentTimeMillis()
// } else {
// null
// }
// )
// )
// }
// }
// .padding(all = 4.dp)
// .size(18.dp)
// )
//
// Image(
// painter = painterResource(R.drawable.share_social),
// contentDescription = null,
// colorFilter = ColorFilter.tint(colorPalette.text),
// modifier = Modifier
// .clickable {
// albumWithSongs.album.shareUrl?.let { url ->
// val sendIntent = Intent().apply {
// action = Intent.ACTION_SEND
// type = "text/plain"
// putExtra(Intent.EXTRA_TEXT, url)
// }
//
// context.startActivity(
// Intent.createChooser(
// sendIntent,
// null
// )
// )
// }
// }
// .padding(all = 4.dp)
// .size(18.dp)
// )
// }
//
// AsyncImage(
// model = albumWithSongs.album.thumbnailUrl?.thumbnail(thumbnailSizePx),
// contentDescription = null,
// modifier = Modifier
// .align(Alignment.CenterHorizontally)
// .padding(all = 16.dp)
// .clip(thumbnailShape)
// .size(thumbnailSizeDp)
// )
// }
// }
//
// itemsIndexed(
// items = albumWithSongs.songs,
// key = { _, song -> song.id }
// ) { index, song ->
// SongItem(
// title = song.title,
// authors = song.artistsText ?: albumWithSongs.album.authorsText,
// durationText = song.durationText,
// onClick = {
// binder?.stopRadio()
// binder?.player?.forcePlayAtIndex(
// albumWithSongs.songs.map(DetailedSong::asMediaItem),
// index
// )
// },
// startContent = {
// BasicText(
// text = "${index + 1}",
// style = typography.s.semiBold.center.color(colorPalette.textDisabled),
// maxLines = 1,
// overflow = TextOverflow.Ellipsis,
// modifier = Modifier
// .width(Dimensions.thumbnails.song)
// )
// },
// menuContent = {
// NonQueuedMediaItemMenu(mediaItem = song.asMediaItem)
// }
// )
// }
// }
//
// Box(
// modifier = Modifier
// .align(Alignment.BottomEnd)
// .padding(all = 16.dp)
// .padding(LocalPlayerAwarePaddingValues.current)
// .clip(RoundedCornerShape(16.dp))
// .clickable(enabled = albumWithSongs.songs.isNotEmpty()) {
// binder?.stopRadio()
// binder?.player?.forcePlayFromBeginning(
// albumWithSongs.songs
// .shuffled()
// .map(DetailedSong::asMediaItem)
// )
// }
// .background(colorPalette.background2)
// .size(62.dp)
// ) {
// Image(
// painter = painterResource(R.drawable.shuffle),
// contentDescription = null,
// colorFilter = ColorFilter.tint(colorPalette.text),
// modifier = Modifier
// .align(Alignment.Center)
// .size(20.dp)
// )
// }
// } ?: viewModel.result?.exceptionOrNull()?.let {
// Box(
// modifier = Modifier
// .pointerInput(Unit) {
// detectTapGestures {
// viewModel.fetch(browseId)
// }
// }
// .align(Alignment.Center)
// .fillMaxSize()
// ) {
// BasicText(
// text = "An error has occurred.\nTap to retry",
// style = typography.s.medium.secondary.center,
// modifier = Modifier
// .align(Alignment.Center)
// )
// }
// } ?: Column(
// modifier = Modifier
// .padding(LocalPlayerAwarePaddingValues.current)
// .shimmer()
// ) {
// HeaderPlaceholder()
//
// Spacer(
// modifier = Modifier
// .align(Alignment.CenterHorizontally)
// .padding(all = 16.dp)
// .clip(thumbnailShape)
// .size(thumbnailSizeDp)
// .background(colorPalette.shimmer)
// )
//
// repeat(3) { index ->
// Row(
// verticalAlignment = Alignment.CenterVertically,
// horizontalArrangement = Arrangement.spacedBy(12.dp),
// modifier = Modifier
// .alpha(1f - index * 0.25f)
// .fillMaxWidth()
// .padding(horizontal = 16.dp, vertical = Dimensions.itemsVerticalPadding)
// .height(Dimensions.thumbnails.song)
// ) {
// Spacer(
// modifier = Modifier
// .background(color = colorPalette.shimmer, shape = thumbnailShape)
// .size(Dimensions.thumbnails.song)
// )
//
// Column {
// TextPlaceholder()
// TextPlaceholder()
// }
// }
// }
// }
// }
}

View file

@ -1,25 +1,20 @@
package it.vfsfitvnm.vimusic.ui.screens.builtinplaylist
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.LocalPlayerAwarePaddingValues
@ -31,6 +26,7 @@ import it.vfsfitvnm.vimusic.savers.DetailedSongListSaver
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.InFavoritesMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.ui.styling.px
@ -136,27 +132,15 @@ fun BuiltInPlaylistSongList(builtInPlaylist: BuiltInPlaylist) {
}
}
Box(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.padding(LocalPlayerAwarePaddingValues.current)
.clip(RoundedCornerShape(16.dp))
.clickable(enabled = songs.isNotEmpty()) {
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(songs.shuffled().map(DetailedSong::asMediaItem))
}
.background(colorPalette.background2)
.size(62.dp)
) {
Image(
painter = painterResource(R.drawable.shuffle),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
PrimaryButton(
iconId = R.drawable.shuffle,
isEnabled = songs.isNotEmpty(),
onClick = {
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(
songs.shuffled().map(DetailedSong::asMediaItem)
)
}
)
}
}

View file

@ -19,7 +19,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
@ -42,6 +41,7 @@ import it.vfsfitvnm.vimusic.transaction
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.InPlaylistMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
@ -267,32 +267,18 @@ fun LocalPlaylistSongList(
}
}
Box(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.padding(LocalPlayerAwarePaddingValues.current)
.clip(RoundedCornerShape(16.dp))
.clickable(enabled = playlistWithSongs?.songs?.isNotEmpty() == true) {
playlistWithSongs?.songs
?.shuffled()
?.map(DetailedSong::asMediaItem)
?.let { mediaItems ->
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(mediaItems)
}
}
.background(colorPalette.background2)
.size(62.dp)
) {
Image(
painter = painterResource(R.drawable.shuffle),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
PrimaryButton(
iconId = R.drawable.shuffle,
isEnabled = playlistWithSongs?.songs?.isNotEmpty() == true,
onClick = {
playlistWithSongs?.songs
?.shuffled()
?.map(DetailedSong::asMediaItem)
?.let { mediaItems ->
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(mediaItems)
}
}
)
}
}

View file

@ -46,6 +46,7 @@ import it.vfsfitvnm.vimusic.transaction
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderPlaceholder
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
@ -234,30 +235,16 @@ fun PlaylistSongList(
}
}
Box(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.padding(LocalPlayerAwarePaddingValues.current)
.clip(RoundedCornerShape(16.dp))
.clickable(enabled = playlist.songs?.isNotEmpty() == true) {
playlist.songs?.map(YouTube.Item.Song::asMediaItem)?.let { mediaItems ->
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(mediaItems.shuffled())
}
PrimaryButton(
iconId = R.drawable.shuffle,
isEnabled = playlist.songs?.isNotEmpty() == true,
onClick = {
playlist.songs?.map(YouTube.Item.Song::asMediaItem)?.let { mediaItems ->
binder?.stopRadio()
binder?.player?.forcePlayFromBeginning(mediaItems.shuffled())
}
.background(colorPalette.background2)
.size(62.dp)
) {
Image(
painter = painterResource(R.drawable.shuffle),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
}
)
} ?: playlistResult?.exceptionOrNull()?.let {
Box(
modifier = Modifier