From c23df8d8af577ecfbfe05bb958c50d1c54d931f2 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 1 Jun 2026 19:17:11 -0400 Subject: [PATCH] fix(android): stop Home Crossfade firing on every section emission (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User-visible: Home flickered continuously after first sign-in until all sections settled. The top-level Crossfade keyed on the state INSTANCE — and because each section's flow emission produces a new UiState.Success(data), Crossfade ran its 300ms fade animation on every per-section hydration tick. Six sections cascading in over ~1s read as continuous flicker. Fix: key the Crossfade on state::class. Loading -> Success -> Empty -> Error class transitions still animate; Success -> Success(with more sections) recompositions just update the LazyColumn normally through Compose's standard diff path. --- .../com/fabledsword/minstrel/home/ui/HomeScreen.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/fabledsword/minstrel/home/ui/HomeScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/home/ui/HomeScreen.kt index e9048195..c2b03bc4 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/home/ui/HomeScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/home/ui/HomeScreen.kt @@ -367,8 +367,17 @@ fun HomeScreen( onRefresh = { viewModel.refresh().join() }, modifier = Modifier.fillMaxSize().padding(inner), ) { - Crossfade(targetState = state, label = "home-state") { s -> - when (s) { + // Key Crossfade on the state CLASS, not the instance. Each + // section emission produces a new UiState.Success(data); if + // we keyed on `state` directly, every per-section + // hydration tick would re-run the 300ms crossfade, and + // first-sign-in (six sections cascading in) reads as + // continuous flicker. Keying on the class restricts the + // animation to Loading↔Success↔Empty↔Error transitions and + // lets normal Success→Success recompositions update the + // LazyColumn without a fade. + Crossfade(targetState = state::class, label = "home-state") { _ -> + when (val s = state) { UiState.Loading -> HomeSkeletonContent() UiState.Empty -> EmptyState( title = "Welcome to Minstrel",