From 6081a5c009f8cf1f5a79dedfa406fb0573d2b2b8 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Fri, 25 Sep 2026 12:23:14 +0000 Subject: [PATCH] keep the theme wrapper stable so the layout doesn't remount when artwork arrives ArtworkTheme swapped between a bare content() and a MaterialTheme wrapper depending on whether a scheme existed. When the first track's artwork (or a screen's) resolved, that branch change remounted the whole subtree, reloading images, resetting scroll and restarting the mini player. Always provide a MaterialTheme, falling back to the ambient scheme when there is no artwork, and cover it with a test. --- .../com/subtracks/ui/theme/ArtworkTheme.kt | 11 ++++----- .../ui/theme/ArtworkExtractionTest.kt | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt b/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt index d2daa890..4ca8c6bf 100644 --- a/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt +++ b/app/src/main/kotlin/com/subtracks/ui/theme/ArtworkTheme.kt @@ -204,12 +204,11 @@ fun ArtworkTheme( colors: ArtworkColors?, content: @Composable () -> Unit, ) { - val scheme = colors?.scheme - if (scheme == null) { - content() - } else { - MaterialTheme(colorScheme = scheme, typography = SubtracksTypography, content = content) - } + MaterialTheme( + colorScheme = colors?.scheme ?: MaterialTheme.colorScheme, + typography = SubtracksTypography, + content = content, + ) } fun playerSurfaceColor(artwork: ArtworkColors): Color { diff --git a/app/src/test/kotlin/com/subtracks/ui/theme/ArtworkExtractionTest.kt b/app/src/test/kotlin/com/subtracks/ui/theme/ArtworkExtractionTest.kt index 8897e56d..068192f6 100644 --- a/app/src/test/kotlin/com/subtracks/ui/theme/ArtworkExtractionTest.kt +++ b/app/src/test/kotlin/com/subtracks/ui/theme/ArtworkExtractionTest.kt @@ -4,6 +4,10 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.Color import androidx.activity.ComponentActivity +import androidx.compose.material3.Text +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.graphics.luminance import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule import androidx.test.core.app.ApplicationProvider @@ -15,6 +19,7 @@ import coil3.asImage import coil3.test.FakeImageLoaderEngine import com.subtracks.data.model.CoverArtRef import org.junit.After +import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before @@ -64,4 +69,22 @@ class ArtworkExtractionTest { assertNotNull(colors) assertTrue(colors!!.scheme.background.luminance() < 0.1f) } + + @Test + fun keepsContentStateWhenArtworkArrives() { + val artwork = mutableStateOf(null) + lateinit var state: MutableState + composeRule.setContent { + SubtracksTheme { + ArtworkTheme(artwork.value) { + state = remember { mutableStateOf(0) } + Text(state.value.toString()) + } + } + } + composeRule.runOnIdle { state.value = 42 } + composeRule.runOnIdle { artwork.value = artworkColorsFromSeed(0xFF3A7BD5.toInt()) } + composeRule.waitForIdle() + assertEquals(42, state.value) + } }