refactor(home): extract StreakMilestoneDialog + drop dead MomentCueCard

Step 9/9 of the UI split. StreakMilestoneDialog -> components/ (kept internal;
ArtPreviewScreen call updated to the new package). MomentCueCard was dead (no
callers) — removed. Orphaned imports cleaned. compileDebugKotlin green.
HomeScreen.kt now ~620 lines (from 1921).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
null 2026-07-11 20:34:37 -05:00
parent 5e266a95fa
commit 415f8d6866
3 changed files with 87 additions and 100 deletions

View File

@ -45,7 +45,7 @@ fun ArtPreviewScreen(onNavigate: (String) -> Unit = {}) {
var showStreak by remember { mutableStateOf(false) } var showStreak by remember { mutableStateOf(false) }
if (showStreak) { if (showStreak) {
app.closer.ui.home.StreakMilestoneDialog( app.closer.ui.home.components.StreakMilestoneDialog(
milestone = 7, milestone = 7,
partnerName = "Sofia", partnerName = "Sofia",
onDismiss = { showStreak = false } onDismiss = { showStreak = false }

View File

@ -5,14 +5,11 @@ import app.closer.crypto.FieldEncryptor
import app.closer.domain.model.Question import app.closer.domain.model.Question
import app.closer.domain.model.QuestionCategory import app.closer.domain.model.QuestionCategory
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.Spacer
import androidx.compose.ui.window.Dialog
import coil.compose.SubcomposeAsyncImage import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest import coil.request.ImageRequest
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import app.closer.ui.components.CelebrationOverlay
import app.closer.ui.components.CategoryGlyph import app.closer.ui.components.CategoryGlyph
import app.closer.ui.components.CloserActionButton import app.closer.ui.components.CloserActionButton
import app.closer.ui.components.CloserButtonStyle import app.closer.ui.components.CloserButtonStyle
@ -24,14 +21,10 @@ import app.closer.ui.components.CloserRadii
import app.closer.ui.components.ErrorState import app.closer.ui.components.ErrorState
import app.closer.ui.components.LoadingState import app.closer.ui.components.LoadingState
import app.closer.ui.questions.displayCategoryName import app.closer.ui.questions.displayCategoryName
import app.closer.ui.settings.SettingsInk
import app.closer.ui.settings.SettingsMuted
import app.closer.ui.settings.SettingsSoft
import app.closer.ui.theme.CloserPalette import app.closer.ui.theme.CloserPalette
import app.closer.ui.theme.closerBackgroundBrush import app.closer.ui.theme.closerBackgroundBrush
import app.closer.ui.theme.closerCardColor import app.closer.ui.theme.closerCardColor
import app.closer.ui.theme.isCloserDarkTheme import app.closer.ui.theme.isCloserDarkTheme
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -75,7 +68,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
import app.closer.ui.components.BrandIllustration import app.closer.ui.components.BrandIllustration
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@ -100,6 +92,7 @@ import app.closer.ui.home.components.LoadingHomeCard
import app.closer.ui.home.components.PartnerQuickActionsSheet import app.closer.ui.home.components.PartnerQuickActionsSheet
import app.closer.ui.home.components.PartnerActivationCard import app.closer.ui.home.components.PartnerActivationCard
import app.closer.ui.home.components.PrimaryHomeActionCard import app.closer.ui.home.components.PrimaryHomeActionCard
import app.closer.ui.home.components.StreakMilestoneDialog
import app.closer.ui.home.components.WaitingForYouSection import app.closer.ui.home.components.WaitingForYouSection
import app.closer.ui.home.components.actionColors import app.closer.ui.home.components.actionColors
import app.closer.ui.home.components.homeActionGlyph import app.closer.ui.home.components.homeActionGlyph
@ -431,43 +424,6 @@ private fun HomeContent(
@Composable
private fun MomentCueCard() {
val isDark = isCloserDarkTheme()
CloserCard(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(CloserRadii.Card),
containerColor = if (isDark) {
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.58f)
} else {
CloserPalette.PinkMist.copy(alpha = 0.7f)
},
elevation = CloserElevations.Flat
) {
Column(
modifier = Modifier.padding(17.dp),
verticalArrangement = Arrangement.spacedBy(7.dp)
) {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
HomePill("Special dates")
HomePill("Quiet reminder")
}
Text(
text = "Keep important days close without turning them into chores.",
style = MaterialTheme.typography.titleSmall.copy(fontWeight = FontWeight.SemiBold),
color = MaterialTheme.colorScheme.onSurface
)
Text(
text = "Birthdays, anniversaries, and planned moments will sit here as gentle cues once they are saved.",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
}
}
@Preview @Preview
@Composable @Composable
fun HomeScreenPreview() { fun HomeScreenPreview() {
@ -656,57 +612,3 @@ private fun previewDailyQuestionAction(state: DailyQuestionState): HomeAction =
) )
} }
@Composable
internal fun StreakMilestoneDialog(
milestone: Int,
partnerName: String?,
onDismiss: () -> Unit
) {
Dialog(onDismissRequest = onDismiss) {
Box(contentAlignment = Alignment.Center) {
Surface(
shape = RoundedCornerShape(28.dp),
color = SettingsSoft,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
) {
Column(
modifier = Modifier.padding(horizontal = 28.dp, vertical = 30.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(R.drawable.illustration_streak_milestone),
contentDescription = null,
modifier = Modifier.size(156.dp)
)
Spacer(Modifier.height(18.dp))
Text(
text = if (milestone == 1) "Your first night together" else "$milestone nights together",
style = MaterialTheme.typography.headlineSmall,
fontWeight = FontWeight.SemiBold,
color = SettingsInk,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(8.dp))
val nights = if (milestone == 1) "your first night" else "$milestone nights running"
Text(
text = partnerName?.takeIf { it.isNotBlank() }
?.let { "You and $it keep showing up for each other — $nights. The small moments are adding up to something." }
?: "You keep showing up — $nights. The small moments are adding up to something.",
style = MaterialTheme.typography.bodyMedium,
color = SettingsMuted,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(24.dp))
CloserActionButton(
label = "Keep going together",
onClick = onDismiss,
modifier = Modifier.fillMaxWidth()
)
}
}
CelebrationOverlay(visible = true, intensity = 1.4f)
}
}
}

View File

@ -0,0 +1,85 @@
package app.closer.ui.home.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import app.closer.R
import app.closer.ui.components.CelebrationOverlay
import app.closer.ui.components.CloserActionButton
import app.closer.ui.settings.SettingsInk
import app.closer.ui.settings.SettingsMuted
import app.closer.ui.settings.SettingsSoft
/** One-time streak-milestone celebration dialog. Extracted from HomeScreen.kt; kept `internal`
* because ui/debug/ArtPreviewScreen also renders it. */
@Composable
internal fun StreakMilestoneDialog(
milestone: Int,
partnerName: String?,
onDismiss: () -> Unit
) {
Dialog(onDismissRequest = onDismiss) {
Box(contentAlignment = Alignment.Center) {
Surface(
shape = RoundedCornerShape(28.dp),
color = SettingsSoft,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
) {
Column(
modifier = Modifier.padding(horizontal = 28.dp, vertical = 30.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(R.drawable.illustration_streak_milestone),
contentDescription = null,
modifier = Modifier.size(156.dp)
)
Spacer(Modifier.height(18.dp))
Text(
text = if (milestone == 1) "Your first night together" else "$milestone nights together",
style = MaterialTheme.typography.headlineSmall,
fontWeight = FontWeight.SemiBold,
color = SettingsInk,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(8.dp))
val nights = if (milestone == 1) "your first night" else "$milestone nights running"
Text(
text = partnerName?.takeIf { it.isNotBlank() }
?.let { "You and $it keep showing up for each other — $nights. The small moments are adding up to something." }
?: "You keep showing up — $nights. The small moments are adding up to something.",
style = MaterialTheme.typography.bodyMedium,
color = SettingsMuted,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(24.dp))
CloserActionButton(
label = "Keep going together",
onClick = onDismiss,
modifier = Modifier.fillMaxWidth()
)
}
}
CelebrationOverlay(visible = true, intensity = 1.4f)
}
}
}