diff --git a/app/src/main/java/bruhcollective/itaysonlab/jetispot/ui/dac/components_home/SectionComponentBinder.kt b/app/src/main/java/bruhcollective/itaysonlab/jetispot/ui/dac/components_home/SectionComponentBinder.kt index 95856d9..8e7fb8c 100644 --- a/app/src/main/java/bruhcollective/itaysonlab/jetispot/ui/dac/components_home/SectionComponentBinder.kt +++ b/app/src/main/java/bruhcollective/itaysonlab/jetispot/ui/dac/components_home/SectionComponentBinder.kt @@ -14,12 +14,9 @@ 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.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -27,110 +24,74 @@ import androidx.compose.ui.unit.sp import bruhcollective.itaysonlab.jetispot.ui.ext.dynamicUnpack import bruhcollective.itaysonlab.jetispot.ui.navigation.LocalNavigationController import bruhcollective.itaysonlab.jetispot.ui.shared.PreviewableAsyncImage +import bruhcollective.itaysonlab.jetispot.ui.theme.CustomShapes import com.spotify.home.dac.component.v1.proto.* import dev.chrisbanes.snapper.ExperimentalSnapperApi import dev.chrisbanes.snapper.SnapOffsets import dev.chrisbanes.snapper.rememberSnapperFlingBehavior -@OptIn(ExperimentalMaterial3Api::class, ExperimentalSnapperApi::class) +@OptIn(ExperimentalSnapperApi::class) @Composable fun SectionComponentBinder( item: SectionComponent ) { - val navController = LocalNavigationController.current - val list = item.componentsList.map { it.dynamicUnpack() } val lazyListState = rememberLazyListState() - Box(Modifier.padding(bottom = 4.dp).wrapContentSize().clip(shape = RoundedCornerShape(34.dp))) { - Card( - shape = RoundedCornerShape(34.dp) - ){ - LazyRow( - horizontalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(16.dp), - state = lazyListState, - flingBehavior = rememberSnapperFlingBehavior( - lazyListState, - snapOffsetForItem = SnapOffsets.Start, - decayAnimationSpec = rememberSplineBasedDecay(), - springAnimationSpec = spring(dampingRatio = 0.001f, stiffness = 10f) + LazyRow( + modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + state = lazyListState, + flingBehavior = rememberSnapperFlingBehavior( + lazyListState, + snapOffsetForItem = SnapOffsets.Start, + decayAnimationSpec = rememberSplineBasedDecay(), + springAnimationSpec = spring(0.1f, 20f) + ) + ) { + items(list) { listItem -> + when (listItem) { + is AlbumCardMediumComponent -> MediumCard( + title = listItem.title, + subtitle = listItem.subtitle, + navigateUri = listItem.navigateUri, + imageUri = listItem.imageUri, + imagePlaceholder = "album" ) - ) { - items(list) { listItem -> - when (listItem) { - is AlbumCardMediumComponent -> MediumCard( - title = listItem.title, - subtitle = listItem.subtitle, - navigateUri = listItem.navigateUri, - imageUri = listItem.imageUri, - imagePlaceholder = "album" - ) - - is PlaylistCardMediumComponent -> MediumCard( - title = listItem.title, - subtitle = listItem.subtitle, - navigateUri = listItem.navigateUri, - imageUri = listItem.imageUri, - imagePlaceholder = "playlist" - ) - - is ArtistCardMediumComponent -> MediumCard( - title = listItem.title, - subtitle = listItem.subtitle, - navigateUri = listItem.navigateUri, - imageUri = listItem.imageUri, - imagePlaceholder = "artist" - ) - is EpisodeCardMediumComponent -> MediumCard( - title = listItem.title, - subtitle = listItem.subtitle, - navigateUri = listItem.navigateUri, - imageUri = listItem.imageUri, - imagePlaceholder = "podcasts" - ) + is PlaylistCardMediumComponent -> MediumCard( + title = listItem.title, + subtitle = listItem.subtitle, + navigateUri = listItem.navigateUri, + imageUri = listItem.imageUri, + imagePlaceholder = "playlist" + ) - is ShowCardMediumComponent -> MediumCard( - title = listItem.title, - subtitle = listItem.subtitle, - navigateUri = listItem.navigateUri, - imageUri = listItem.imageUri, - imagePlaceholder = "podcasts" - ) - } - } - } - } + is ArtistCardMediumComponent -> MediumArtistCard( + title = listItem.title, + subtitle = listItem.subtitle, + navigateUri = listItem.navigateUri, + imageUri = listItem.imageUri, + imagePlaceholder = "artist" + ) - Spacer( - Modifier - .fillMaxWidth(0.04f) - .height(274.dp) - .background( - brush = Brush.horizontalGradient( - colors = listOf( - Color.Transparent, - MaterialTheme.colorScheme.surfaceVariant - ) - ) + is EpisodeCardMediumComponent -> MediumCard( + title = listItem.title, + subtitle = listItem.subtitle, + navigateUri = listItem.navigateUri, + imageUri = listItem.imageUri, + imagePlaceholder = "podcasts" ) - .align(Alignment.BottomEnd) - ) - Spacer( - Modifier - .fillMaxWidth(0.04f) - .height(274.dp) - .background( - brush = Brush.horizontalGradient( - colors = listOf( - MaterialTheme.colorScheme.surfaceVariant, - Color.Transparent - ) - ) + is ShowCardMediumComponent -> MediumCard( + title = listItem.title, + subtitle = listItem.subtitle, + navigateUri = listItem.navigateUri, + imageUri = listItem.imageUri, + imagePlaceholder = "podcasts" ) - ) + } + } } } @@ -144,60 +105,59 @@ fun MediumCard( imagePlaceholder: String ) { val navController = LocalNavigationController.current - Surface( - color = MaterialTheme.colorScheme.background, - shape = RoundedCornerShape(20.dp) + Box( + Modifier + .clip(RoundedCornerShape(28.dp)) + .background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp)) + .clickable { navController.navigate(navigateUri) } ) { Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .width(172.dp) - .clickable { navController.navigate(navigateUri) } - .padding(bottom = 12.dp) + modifier = Modifier.width(172.dp).padding(bottom = 4.dp) ) { var drawnTitle = false // Had to wrap the image in another composable due to weird padding when // image couldn't be retrieved - Surface(Modifier.padding(top = 6.dp)) { + Box(Modifier.padding(top = 14.dp, start = 14.dp, end = 14.dp)) { PreviewableAsyncImage( imageUrl = imageUri, placeholderType = imagePlaceholder, modifier = Modifier - .size(160.dp) - .padding(8.dp) - .clip(RoundedCornerShape(8.dp)) + .fillMaxSize() + .aspectRatio(1f) + .clip(RoundedCornerShape(14.dp)) ) } - // Title of the card. TODO: Scrolling text Column( - Modifier - .height(64.dp) - .padding(horizontal = 14.dp), + Modifier.height(96.dp).padding(horizontal = 14.dp, vertical = 8.dp), verticalArrangement = Arrangement.Center ) { if (title.isNotEmpty()) { drawnTitle = true + Text( title, - fontSize = 16.sp, maxLines = 2, overflow = TextOverflow.Ellipsis, - style = TextStyle(platformStyle = PlatformTextStyle(false)), - textAlign = if (imagePlaceholder == "artist") TextAlign.Center else TextAlign.Start + lineHeight = 20.sp, + style = TextStyle( + platformStyle = PlatformTextStyle(false) + ).plus(MaterialTheme.typography.titleMedium), + textAlign = TextAlign.Start ) } if (subtitle.isNotEmpty()) { Text( subtitle, - fontSize = 12.sp, - fontWeight = FontWeight.Medium, modifier = Modifier - .padding(top = if (drawnTitle) 4.dp else 0.dp) + .padding(top = if (drawnTitle) 6.dp else 0.dp) .fillMaxWidth(), - style = TextStyle(platformStyle = PlatformTextStyle(false)), + style = TextStyle( + platformStyle = PlatformTextStyle(false) + ).plus(MaterialTheme.typography.bodySmall), overflow = TextOverflow.Ellipsis, color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f), ) @@ -205,4 +165,60 @@ fun MediumCard( } } } +} + +@Composable +fun MediumArtistCard( + title: String, + subtitle: String, + navigateUri: String, + imageUri: String, + imagePlaceholder: String +) { + val navController = LocalNavigationController.current + + Box( + Modifier + .clip(RoundedCornerShape(28.dp)) + .clickable { navController.navigate(navigateUri) } + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceAround, + modifier = Modifier.width(172.dp).height(258.dp).padding(bottom = 4.dp) + ) { + // Had to wrap the image in another composable due to weird padding when + // image couldn't be retrieved + Box(Modifier.weight(1f).aspectRatio(1f)) { + PreviewableAsyncImage( + imageUrl = imageUri, + placeholderType = imagePlaceholder, + modifier = Modifier.clip(CustomShapes().BlobShape).fillMaxSize() + ) + } + + Column( + Modifier + .height(56.dp) + .fillMaxWidth() + .clip(RoundedCornerShape(24.dp)) + .background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp)), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (title.isNotEmpty()) { + Text( + title, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + lineHeight = 20.sp, + style = TextStyle( + platformStyle = PlatformTextStyle(false) + ).plus(MaterialTheme.typography.labelLarge), + textAlign = TextAlign.Center + ) + } + } + } + } } \ No newline at end of file