mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 15:29:15 +01:00
sample the bar colour from the gradient, saturate the accents
This commit is contained in:
@@ -78,6 +78,7 @@ import com.subtracks.ui.components.rememberViewportFill
|
|||||||
import com.subtracks.ui.theme.ArtworkColors
|
import com.subtracks.ui.theme.ArtworkColors
|
||||||
import com.subtracks.ui.theme.ArtworkTheme
|
import com.subtracks.ui.theme.ArtworkTheme
|
||||||
import com.subtracks.ui.theme.HeroGradient
|
import com.subtracks.ui.theme.HeroGradient
|
||||||
|
import com.subtracks.ui.theme.gradientColorAt
|
||||||
import com.subtracks.ui.theme.rememberArtworkColors
|
import com.subtracks.ui.theme.rememberArtworkColors
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
@@ -130,8 +131,9 @@ fun AlbumDetailScreen(
|
|||||||
BoxWithConstraints(modifier.fillMaxSize().background(Color.Black)) {
|
BoxWithConstraints(modifier.fillMaxSize().background(Color.Black)) {
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
val fill = rememberViewportFill(listState)
|
val fill = rememberViewportFill(listState)
|
||||||
val gradientHeight = maxHeight * GRADIENT_SCREENS
|
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
|
val gradientHeight = maxHeight * GRADIENT_SCREENS
|
||||||
|
val gradientHeightPx = with(density) { gradientHeight.toPx() }
|
||||||
val statusBarTop = WindowInsets.statusBars.getTop(density)
|
val statusBarTop = WindowInsets.statusBars.getTop(density)
|
||||||
val navBarBottom = WindowInsets.navigationBars.getBottom(density)
|
val navBarBottom = WindowInsets.navigationBars.getBottom(density)
|
||||||
val statusBarDp = with(density) { statusBarTop.toDp() }
|
val statusBarDp = with(density) { statusBarTop.toDp() }
|
||||||
@@ -162,6 +164,9 @@ fun AlbumDetailScreen(
|
|||||||
animationSpec = tween(durationMillis = 600),
|
animationSpec = tween(durationMillis = 600),
|
||||||
label = "gradientAlpha",
|
label = "gradientAlpha",
|
||||||
)
|
)
|
||||||
|
val barColor =
|
||||||
|
artwork?.gradientColorAt(((scrollPx + barHeightPx / 2f) / gradientHeightPx).coerceIn(0f, 1f))
|
||||||
|
?: Color.Black
|
||||||
|
|
||||||
HeroGradient(
|
HeroGradient(
|
||||||
colors = artwork,
|
colors = artwork,
|
||||||
@@ -223,24 +228,6 @@ fun AlbumDetailScreen(
|
|||||||
).alpha(1f - barFraction),
|
).alpha(1f - barFraction),
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.align(Alignment.TopStart)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(with(density) { barHeightPx.toDp() })
|
|
||||||
.clipToBounds()
|
|
||||||
.alpha(barFraction),
|
|
||||||
) {
|
|
||||||
HeroGradient(
|
|
||||||
colors = artwork,
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.requiredHeight(gradientHeight)
|
|
||||||
.offset { IntOffset(0, -scrollPx.roundToInt()) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
@@ -260,6 +247,7 @@ fun AlbumDetailScreen(
|
|||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.align(Alignment.TopStart)
|
.align(Alignment.TopStart)
|
||||||
|
.background(barColor.copy(alpha = barFraction))
|
||||||
.clickable(
|
.clickable(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
indication = null,
|
indication = null,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.lerp
|
||||||
import androidx.compose.ui.graphics.luminance
|
import androidx.compose.ui.graphics.luminance
|
||||||
import androidx.palette.graphics.Palette
|
import androidx.palette.graphics.Palette
|
||||||
import coil3.SingletonImageLoader
|
import coil3.SingletonImageLoader
|
||||||
@@ -92,20 +93,39 @@ fun artworkColorsFromSeeds(
|
|||||||
|
|
||||||
val secondary =
|
val secondary =
|
||||||
secondarySeed?.let { seed ->
|
secondarySeed?.let { seed ->
|
||||||
val color = Color(seed or 0xFF000000.toInt())
|
val (sh, ss, sl) = Color(seed or 0xFF000000.toInt()).toHsl()
|
||||||
val (sh, ss, sl) = color.toHsl()
|
Color.hsl(
|
||||||
if (sl > 0.55f) Color.hsl(sh, ss, 0.30f) else color
|
blendHue(sh, hue, 0.5f),
|
||||||
} ?: tone(hue, s, 0.08f)
|
ss.coerceAtLeast(s * 0.7f).coerceAtMost(0.9f),
|
||||||
|
sl.coerceIn(0.34f, 0.56f),
|
||||||
|
)
|
||||||
|
} ?: tone(hue, s, 0.40f)
|
||||||
|
|
||||||
return ArtworkColors(
|
return ArtworkColors(
|
||||||
scheme = scheme,
|
scheme = scheme,
|
||||||
gradientHigh = tone(hue, (s * 0.6f).coerceAtMost(0.50f), 0.22f),
|
gradientHigh = tone(hue, (s * 0.85f).coerceAtMost(0.65f), 0.30f),
|
||||||
gradientLow = tone(hue, s * 0.30f, 0.03f),
|
gradientLow = tone(hue, s * 0.45f, 0.04f),
|
||||||
accents = listOf(tone(hue, s * 0.8f, 0.90f), secondary),
|
accents = listOf(tone(hue, s, 0.72f), secondary),
|
||||||
blobSeed = primarySeed,
|
blobSeed = primarySeed,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ArtworkColors.gradientColorAt(fraction: Float): Color {
|
||||||
|
val t = fraction.coerceIn(0f, 1f)
|
||||||
|
val base = lerp(gradientHigh, gradientLow, t)
|
||||||
|
val fade = ((t - GRADIENT_FADE_START) / (1f - GRADIENT_FADE_START)).coerceIn(0f, 1f)
|
||||||
|
return lerp(base, Color.Black, fade)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun blendHue(
|
||||||
|
from: Float,
|
||||||
|
to: Float,
|
||||||
|
fraction: Float,
|
||||||
|
): Float {
|
||||||
|
val delta = ((to - from + 540f) % 360f) - 180f
|
||||||
|
return (from + delta * fraction + 360f) % 360f
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun rememberArtworkColors(ref: CoverArtRef?): ArtworkColors? {
|
fun rememberArtworkColors(ref: CoverArtRef?): ArtworkColors? {
|
||||||
val seeds by rememberArtworkSeed(ref)
|
val seeds by rememberArtworkSeed(ref)
|
||||||
|
|||||||
Reference in New Issue
Block a user