From 3e89036f7b34a928f46f00ab720d2c041aea5be6 Mon Sep 17 00:00:00 2001 From: ponzischeme89 Date: Fri, 28 Aug 2026 09:37:05 +1200 Subject: [PATCH] 0.3.38 --- app/build.gradle.kts | 2 +- .../ponzischeme89/memby/ui/MetadataHero.kt | 94 ++++++++++--------- .../memby/ui/home/HomeMetadataPanel.kt | 44 +++++---- 3 files changed, 77 insertions(+), 63 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 51aa9d8..a7feb7a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -38,7 +38,7 @@ val membyGatewayUrl: String = (project.findProperty("memby.gatewayUrl") as Strin val membyDiagnosticLogLevel: String = (project.findProperty("memby.diagnosticLogLevel") as String?) ?.trim()?.uppercase()?.takeIf { it in setOf("INFO", "DEBUG", "TRACE") } ?: "INFO" -val defaultVersionName = "0.3.38" +val defaultVersionName = "0.3.39" val membyVersionName: String = (project.findProperty("memby.versionName") as String?) ?.trim() diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/MetadataHero.kt b/app/src/main/java/com/ponzischeme89/memby/ui/MetadataHero.kt index 32e91c1..6b40563 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/MetadataHero.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/MetadataHero.kt @@ -11,6 +11,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.draw.drawWithCache import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale @@ -52,26 +53,31 @@ internal fun MetadataHero( item = item, modifier = Modifier.fillMaxSize(), ) + // Both scrims in one cached draw pass. Inline Brush.*Gradient in a + // .background() allocates a new brush on every recomposition — and the + // hero recomposes on every focus change while a shelf is browsed. Box( - Modifier.fillMaxSize().background( - Brush.horizontalGradient( - 0f to MembySurface, - 0.30f to MembySurface, - 0.48f to MembySurface.copy(alpha = 0.80f), - 0.62f to MembySurface.copy(alpha = 0.40f), - 0.78f to MembySurface.copy(alpha = 0.10f), - 1f to Color.Transparent, - ), - ), - ) - Box( - Modifier.fillMaxSize().background( - Brush.verticalGradient( - 0f to MembySurface.copy(alpha = 0.18f), - 0.58f to Color.Transparent, - 1f to MembySurface.copy(alpha = 0.20f), - ), - ), + Modifier + .fillMaxSize() + .drawWithCache { + val horizontal = Brush.horizontalGradient( + 0f to MembySurface, + 0.30f to MembySurface, + 0.48f to MembySurface.copy(alpha = 0.80f), + 0.62f to MembySurface.copy(alpha = 0.40f), + 0.78f to MembySurface.copy(alpha = 0.10f), + 1f to Color.Transparent, + ) + val vertical = Brush.verticalGradient( + 0f to MembySurface.copy(alpha = 0.18f), + 0.58f to Color.Transparent, + 1f to MembySurface.copy(alpha = 0.20f), + ) + onDrawBehind { + drawRect(horizontal) + drawRect(vertical) + } + }, ) MediaMetadataPanel( item = item, @@ -127,36 +133,38 @@ private fun MetadataHeroArtwork( modifier = Modifier .align(Alignment.CenterEnd) .fillMaxWidth(MetadataHeroArtworkWidthFraction) - .fillMaxHeight(), + .fillMaxHeight() + // Scrims in one cached pass over the artwork. The slow pull-back that + // used to sit on the image is gone here: on Home the backdrop changes + // on every focus move, so the 10s animation never finished and its + // per-frame graphicsLayer kept the whole launcher redrawing while the + // viewer merely scrolled a shelf. The detail and pause heroes keep it. + .drawWithCache { + val horizontal = Brush.horizontalGradient( + 0f to MembySurface.copy(alpha = 0.92f), + 0.18f to MembySurface.copy(alpha = 0.76f), + 0.42f to MembySurface.copy(alpha = 0.42f), + 0.70f to MembySurface.copy(alpha = 0.12f), + 1f to Color.Transparent, + ) + val vertical = Brush.verticalGradient( + 0f to MembySurface.copy(alpha = 0.16f), + 0.56f to Color.Transparent, + 1f to MembySurface.copy(alpha = 0.28f), + ) + onDrawWithContent { + drawContent() + drawRect(horizontal) + drawRect(vertical) + } + }, ) { AsyncImage( model = request, contentDescription = null, contentScale = ContentScale.Crop, alignment = Alignment.CenterEnd, - modifier = Modifier - .fillMaxSize() - .cinematicBackdropPullBack(artwork), - ) - Box( - Modifier.fillMaxSize().background( - Brush.horizontalGradient( - 0f to MembySurface.copy(alpha = 0.92f), - 0.18f to MembySurface.copy(alpha = 0.76f), - 0.42f to MembySurface.copy(alpha = 0.42f), - 0.70f to MembySurface.copy(alpha = 0.12f), - 1f to Color.Transparent, - ), - ), - ) - Box( - Modifier.fillMaxSize().background( - Brush.verticalGradient( - 0f to MembySurface.copy(alpha = 0.16f), - 0.56f to Color.Transparent, - 1f to MembySurface.copy(alpha = 0.28f), - ), - ), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/home/HomeMetadataPanel.kt b/app/src/main/java/com/ponzischeme89/memby/ui/home/HomeMetadataPanel.kt index ebad6a7..e5a67f5 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/home/HomeMetadataPanel.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/home/HomeMetadataPanel.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.draw.drawWithCache import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale @@ -105,7 +106,30 @@ fun BackdropLayer(item: BaseItem?, modifier: Modifier = Modifier) { .build() } } - Box(modifier.background(MembySurface)) { + Box( + modifier + .background(MembySurface) + // Both scrims over the backdrop in one cached pass. Inline Brush.*Gradient + // in .background() allocates a fresh brush every recomposition, and this + // layer recomposes on every settled focus change while a shelf is browsed. + .drawWithCache { + val horizontal = Brush.horizontalGradient( + 0f to MembySurface, + 0.58f to MembySurface.copy(alpha = 0.89f), + 1f to MembySurface.copy(alpha = 0.65f), + ) + val vertical = Brush.verticalGradient( + 0f to MembySurface.copy(alpha = 0.45f), + 0.66f to MembySurface.copy(alpha = 0.84f), + 1f to MembySurface, + ) + onDrawWithContent { + drawContent() + drawRect(horizontal) + drawRect(vertical) + } + }, + ) { if (request != null) { AsyncImage( model = request, @@ -114,24 +138,6 @@ fun BackdropLayer(item: BaseItem?, modifier: Modifier = Modifier) { modifier = Modifier.fillMaxSize(), ) } - Box( - Modifier.fillMaxSize().background( - Brush.horizontalGradient( - 0f to MembySurface, - 0.58f to MembySurface.copy(alpha = 0.89f), - 1f to MembySurface.copy(alpha = 0.65f), - ), - ), - ) - Box( - Modifier.fillMaxSize().background( - Brush.verticalGradient( - 0f to MembySurface.copy(alpha = 0.45f), - 0.66f to MembySurface.copy(alpha = 0.84f), - 1f to MembySurface, - ), - ), - ) } }