0cf07b8d1c5c
compose vault health's category list trailing space instead of leaving a dead void below the 5 headers, matching vault list's end-of-content treatment
- time
- 2026-07-24 02:55 UTC · 3 months ago
- machine
- koh2
- agent
- claude-sonnet-5
- session
- gate1-gate2-verification-pass
- parent
- cb86e678be5c
↓ peach-android-0cf07b8d.tar.gzatlas at this save
files changed1 file
app/src/main/java/com/peachpasswords/ui/vault/VaultHealthScreen.kt+30 −6app/src/main/java/com/peachpasswords/ui/vault/VaultHealthScreen.kt+30 −6
@@ -3,12 +3,15 @@33 import androidx.compose.foundation.Canvas44 import androidx.compose.foundation.border55 import androidx.compose.foundation.clickable6+import androidx.compose.foundation.layout.Arrangement67 import androidx.compose.foundation.layout.Box8+import androidx.compose.foundation.layout.BoxWithConstraints79 import androidx.compose.foundation.layout.Column810 import androidx.compose.foundation.layout.Row911 import androidx.compose.foundation.layout.Spacer1012 import androidx.compose.foundation.layout.fillMaxSize1113 import androidx.compose.foundation.layout.fillMaxWidth14+import androidx.compose.foundation.layout.heightIn1215 import androidx.compose.foundation.layout.padding1316 import androidx.compose.foundation.layout.size1417 import androidx.compose.foundation.layout.systemBarsPadding@@ -66,6 +69,10 @@6669 /** Local password-age threshold for the "Old" bucket: 365 days. */6770 private const val OLD_PASSWORD_MS = 365L * 24 * 60 * 60 * 10006871 72+/** Approximate on-screen heights used to size the health list's trailing footer. */73+private val HEALTH_HEADER_HEIGHT = 52.dp74+private val HEALTH_ENTRY_ROW_HEIGHT = 64.dp75+6976 @HiltViewModel7077 class VaultHealthViewModel @Inject constructor(7178 private val vault: VaultRepository,@@ -151,12 +158,29 @@151158 } else {152159 val breachColor = peachColors.Breach153160 val dimColor = peachColors.T2154- LazyColumn(modifier = Modifier.weight(1f)) {155- healthSection("Breached", breached, breachColor, expanded, onEditEntry)156- healthSection("Reused", reused, Amber, expanded, onEditEntry)157- healthSection("Weak", weak, Amber, expanded, onEditEntry)158- healthSection("Old", old, dimColor, expanded, onEditEntry)159- healthSection("No passkey", noPasskey, dimColor, expanded, onEditEntry)161+ val buckets = listOf("Breached" to breached, "Reused" to reused, "Weak" to weak, "Old" to old, "No passkey" to noPasskey)162+ val expandedRowCount = buckets.sumOf { (title, bucket) -> if (expanded[title] == true) bucket.size else 0 }163+ BoxWithConstraints(Modifier.weight(1f).fillMaxWidth()) {164+ // Five short category headers rarely fill the viewport on their165+ // own — center a defined end treatment in whatever's left over166+ // instead of trailing into dead space below the last header.167+ val footerMinHeight = (maxHeight - HEALTH_HEADER_HEIGHT * buckets.size - HEALTH_ENTRY_ROW_HEIGHT * expandedRowCount)168+ .coerceAtLeast(0.dp)169+ LazyColumn(Modifier.fillMaxSize()) {170+ healthSection("Breached", breached, breachColor, expanded, onEditEntry)171+ healthSection("Reused", reused, Amber, expanded, onEditEntry)172+ healthSection("Weak", weak, Amber, expanded, onEditEntry)173+ healthSection("Old", old, dimColor, expanded, onEditEntry)174+ healthSection("No passkey", noPasskey, dimColor, expanded, onEditEntry)175+ item {176+ Column(177+ modifier = Modifier.fillMaxWidth().heightIn(min = footerMinHeight),178+ verticalArrangement = Arrangement.Center,179+ ) {180+ PeachEmptyOrEndState(message = "That's every category.")181+ }182+ }183+ }160184 }161185 }162186 }