Skip to content
This repository has been archived by the owner on Jun 27, 2023. It is now read-only.

Commit

Permalink
ImageTopAppBar: rewritten.
Browse files Browse the repository at this point in the history
Regular playlist header: rewritten, redesigned from scratch.
Playlist screen: fab removed.
  • Loading branch information
DotsTeaLab committed Nov 25, 2022
1 parent ee3f3ff commit 4ba1c4b
Show file tree
Hide file tree
Showing 6 changed files with 528 additions and 347 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
package bruhcollective.itaysonlab.jetispot.ui.hub.components

import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.spring
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.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Favorite
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalConfiguration
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.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.*
import bruhcollective.itaysonlab.jetispot.core.objs.hub.HubItem
import bruhcollective.itaysonlab.jetispot.ui.hub.LocalHubScreenDelegate
import bruhcollective.itaysonlab.jetispot.ui.hub.components.essentials.PlaylistEntityActionStrip
import bruhcollective.itaysonlab.jetispot.ui.navigation.LocalNavigationController
import bruhcollective.itaysonlab.jetispot.ui.shared.MarqueeText
import bruhcollective.itaysonlab.jetispot.ui.shared.PreviewableAsyncImage
Expand All @@ -35,12 +42,55 @@ import coil.compose.AsyncImage

@OptIn(ExperimentalTextApi::class, ExperimentalMaterial3Api::class)
@Composable
fun PlaylistHeader(
item: HubItem,
scrollBehaviour: TopAppBarScrollBehavior
) {
fun PlaylistHeader(item: HubItem, scrollBehaviour: TopAppBarScrollBehavior) {
val navController = LocalNavigationController.current
val delegate = LocalHubScreenDelegate.current

val screenWidth = LocalConfiguration.current.screenWidthDp.dp
val padding = 16
val actionStripHeight = 64.dp

val collapsedFraction = run { scrollBehaviour.state.collapsedFraction }
val inverseCollapsedFraction = run { 1f - collapsedFraction }

val fraction = if (collapsedFraction > 0.98f) 0f else 1f

val damping = remember { derivedStateOf { 0.85f } }.value
val stiffness = remember { derivedStateOf { 800f } }.value

val imageAlpha = run { inverseCollapsedFraction * 1.3f }
val imageBlur = run { 32.dp * collapsedFraction }

val buttonBackground by animateColorAsState(
MaterialTheme.colorScheme.background.copy(fraction),
animationSpec = spring(stiffness = 400f)
)
val buttonPadding by animateDpAsState(
((padding * 1.6) * inverseCollapsedFraction + (4 * collapsedFraction)).dp,
spring(damping, stiffness)
)
val imageHeight by animateDpAsState(
(min(412.dp, screenWidth) * inverseCollapsedFraction),
spring(damping, stiffness)
)
val imagePadding by animateDpAsState(
(padding * inverseCollapsedFraction).dp,
spring(damping, stiffness)
)
val animatedActionStripHeight by animateDpAsState(
actionStripHeight * inverseCollapsedFraction,
spring(damping, stiffness)
)

val imageSize = DpSize(
min(
(412.dp * inverseCollapsedFraction + (screenWidth * collapsedFraction)),
screenWidth
),
imageHeight
)


// val darkTheme = isSystemInDarkTheme()
// val dominantColor = remember { mutableStateOf(Color.Transparent) }
// val dominantColorAsBg = animateColorAsState(dominantColor.value)
Expand All @@ -60,87 +110,135 @@ fun PlaylistHeader(
overflow = TextOverflow.Ellipsis,
)
},
smallTitle = {
Text(
text = item.text?.title!!,
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
},
artwork = {
PreviewableAsyncImage(
item.images?.main?.uri,
"playlist",
modifier = Modifier.fillMaxSize()
)
},
description = {
item.text?.subtitle?.let {
Column(Modifier.height(96.dp), verticalArrangement = Arrangement.Bottom) {
Row(
Modifier
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) { navController.navigate(item.custom?.get("owner_username") as String) }
image = {
Column() {
Box(contentAlignment = Alignment.Center) {
Box() {
Column() {
Box(
Modifier
.clip(RoundedCornerShape(24.dp))
.blur(imageBlur)
) {
PreviewableAsyncImage(
item.images?.main?.uri,
"playlist",
modifier = Modifier
.size(imageSize)
.alpha(imageAlpha)
.padding(max(imagePadding, 0.dp))
.clip(RoundedCornerShape(24.dp)),
when (imageHeight > screenWidth) {
true -> ContentScale.FillBounds
false -> ContentScale.Crop
}
)
}

Box(Modifier.height(animatedActionStripHeight).alpha(inverseCollapsedFraction)) {
PlaylistEntityActionStrip(delegate, item, scrollBehaviour)
}
}
}

if (screenWidth < 476.dp) IconButton(
onClick = { navController.popBackStack() },
colors = IconButtonDefaults.outlinedIconButtonColors(containerColor = buttonBackground),
modifier = Modifier
.align(Alignment.TopStart)
.padding(buttonPadding)
) {
PreviewableAsyncImage(
imageUrl = item.custom?.get("owner_pic") as String,
placeholderType = "user",
modifier = Modifier
.size(32.dp)
.clip(CircleShape)
)
Icon(Icons.Rounded.ArrowBack, contentDescription = "Back")
}

Text(
text = item.custom["owner_name"] as String,
fontSize = 14.sp,
modifier = Modifier
.align(Alignment.CenterVertically)
.padding(start = 12.dp)
if (screenWidth < 476.dp) IconButton(
onClick = { /*TODO*/ },
colors = IconButtonDefaults.outlinedIconButtonColors(containerColor = buttonBackground),
modifier = Modifier
.align(Alignment.TopEnd)
.padding(buttonPadding)
) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Options for ${item.text!!.title!!} by ${item.text!!.subtitle!!}"
)
}
// Text(
// text = "${item.custom?.get("likes_count") as Long} likes • ${item.custom["total_duration"] as String}",
// fontSize = 12.sp,
// maxLines = 1
// )

Text(
text = it,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f),
fontSize = 12.sp,
overflow = TextOverflow.Ellipsis,
style = TextStyle(platformStyle = PlatformTextStyle(false)),
modifier = Modifier.padding(top = if (it != "") 8.dp else 0.dp)
)
}
}
},
// description = {
// item.text?.subtitle?.let {
// Column(Modifier.height(96.dp), verticalArrangement = Arrangement.Bottom) {
// Row(
// Modifier
// .clickable(
// interactionSource = remember { MutableInteractionSource() },
// indication = null
// ) { navController.navigate(item.custom?.get("owner_username") as String) }
// ) {
// PreviewableAsyncImage(
// imageUrl = item.custom?.get("owner_pic") as String,
// placeholderType = "user",
// modifier = Modifier
// .size(32.dp)
// .clip(CircleShape)
// )
//
// Text(
// text = item.custom["owner_name"] as String,
// fontSize = 14.sp,
// modifier = Modifier
// .align(Alignment.CenterVertically)
// .padding(start = 12.dp)
// )
// }
//// Text(
//// text = "${item.custom?.get("likes_count") as Long} likes • ${item.custom["total_duration"] as String}",
//// fontSize = 12.sp,
//// maxLines = 1
//// )
//
// Text(
// text = it,
// color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f),
// fontSize = 12.sp,
// overflow = TextOverflow.Ellipsis,
// style = TextStyle(platformStyle = PlatformTextStyle(false)),
// modifier = Modifier.padding(top = if (it != "") 8.dp else 0.dp)
// )
// }
// }
// },
actions = {
Icon(Icons.Rounded.Favorite, contentDescription = null)
IconButton(onClick = { /*TODO*/ }) {
Icon(
if (screenWidth >= 476.dp) Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Options for ${item.text!!.title!!} by ${item.text!!.subtitle!!}"
)
else Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Options for ${item.text!!.title!!} by ${item.text!!.subtitle!!}",
tint = Color.Transparent
)
}
},
scrollBehavior = scrollBehaviour,
appBarHeight = imageSize.width + actionStripHeight,
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
Icon(Icons.Rounded.ArrowBack, contentDescription = "Back")
if (screenWidth >= 476.dp) Icon(
Icons.Rounded.ArrowBack,
contentDescription = "Back"
)
else Icon(
Icons.Rounded.ArrowBack,
contentDescription = "Back",
tint = Color.Transparent
)
}
},
contentPadding = PaddingValues(
top = with(LocalDensity.current) {
WindowInsets.statusBars.getTop(LocalDensity.current).toDp()
}
)
windowInsets = WindowInsets.statusBars
)
// PlaylistHeaderAdditionalInfo(navController, delegate, item.custom)
// EntityActionStrip(navController, delegate, item)
// }
}


Expand Down Expand Up @@ -199,7 +297,11 @@ fun LargePlaylistHeader(
modifier = Modifier
.clip(CircleShape)
.size(38.dp)
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp).copy(0.5f))
.background(
MaterialTheme.colorScheme
.surfaceColorAtElevation(3.dp)
.copy(0.5f)
)
) {
Icon(Icons.Rounded.Favorite, contentDescription = null)
}
Expand All @@ -211,7 +313,11 @@ fun LargePlaylistHeader(
modifier = Modifier
.clip(CircleShape)
.size(38.dp)
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp).copy(0.5f))
.background(
MaterialTheme.colorScheme
.surfaceColorAtElevation(3.dp)
.copy(0.5f)
)
) {
Icon(
imageVector = Icons.Default.MoreVert,
Expand Down
Loading

0 comments on commit 4ba1c4b

Please sign in to comment.