fix(android): stop Home Crossfade firing on every section emission (#1)
android / Build + lint + test (push) Successful in 3m55s

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.
This commit is contained in:
2026-06-01 19:17:11 -04:00
parent 3d52f271a0
commit c23df8d8af
@@ -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",