feat(upgrade): Merge upgrade screen mascot and preamble into one hero card

Adds UpgradeHeroCard, which pairs the mascot with the preamble copy inside a
single ElevatedCard and stacks them once the copy runs out of room. Used by
the FOSS pitch view and the GPLAY acquisition view; grace episodes and the
FOSS status views keep their standalone header, which has no preamble to
pair with. Screen tests pin the hero's presence and absence per state.
This commit is contained in:
darken
2026-08-03 20:28:01 +02:00
committed by Matthias Urhahn
parent 495f58c23b
commit 2833639892
5 changed files with 186 additions and 17 deletions
@@ -244,10 +244,23 @@ internal fun UpgradeScreen(
// episode ages into the diagnostics stage, the mascot joins the mood: unimpressed
// at Google Play, matching the setup card's "needs your attention" face. The young
// episode keeps the happy face — its message is that nothing is wrong.
UpgradeHeader(
mascotSize = 88.dp,
happy = loaded?.grace?.showDiagnostics != true,
)
if (loaded?.grace != null) {
// Grace users never see the preamble (sales copy contradicts "still active"),
// so there is nothing to pair the mascot with — it stays a standalone header
// above the grace card.
UpgradeHeader(
mascotSize = 88.dp,
happy = loaded.grace.showDiagnostics != true,
)
} else {
UpgradeHeroCard(
text = stringResource(R.string.upgrade_preamble),
colors = CardDefaults.elevatedCardColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
),
)
}
}
if (ownedState != null) {
@@ -296,14 +309,8 @@ private fun UpgradeAcquisitionContent(
// blip) shows calm status only, an aged one (likely really gone) adds restore AND the offers,
// so an expired subscriber can switch without waiting out the full grace window.
if (!inGrace) {
UpgradePreambleCard(
text = stringResource(R.string.upgrade_preamble),
colors = CardDefaults.elevatedCardColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
),
)
// The preamble itself now lives in the hero card at the top of the screen, next to the
// mascot — only the sections below it are conditional here.
if (uiState is GplayUpgradeUiState.Loaded && uiState.wasPreviouslyPro) {
// The targeted returning-buyer nudge: prominent placement and emphasis, and the ONLY
// restore affordance on the screen — a second one below would make the screen feel