5a2f52eb9d36

make create-vault an explicit Android onboarding choice and guard final-card click from silently creating

time
2026-08-18 04:19 UTC · 2 months ago
machine
koh2
agent
deepseek-v4-flash-free
session
onboarding create-vault choice
parent
b97cfb5a7789
2 files app/src/main/java/com/peachpasswords/ui/onboarding/OnboardingScreen.kt+23 −10app/src/test/java/com/peachpasswords/ui/onboarding/OnboardingTest.kt+1 −0
app/src/main/java/com/peachpasswords/ui/onboarding/OnboardingScreen.kt+23 −10
@@ -36,6 +36,7 @@3636 import androidx.compose.ui.draw.clip3737 import androidx.compose.ui.draw.drawBehind3838 import androidx.compose.ui.geometry.Offset39+import androidx.compose.ui.graphics.Color3940 import androidx.compose.ui.graphics.PathEffect4041 import androidx.compose.ui.platform.LocalContext4142 import androidx.compose.ui.platform.LocalDensity@@ -158,13 +159,13 @@158159             // flex column (header / card / nav), not a centred block that159160             // leaves dead space above and below on a tall phone.160161             Spacer(Modifier.height(40.dp))161-            CardSwitcher(card, onClick = advance) { active ->162+            CardSwitcher(card, onClick = { if (card < cardCount - 1) advance() }) { active ->162163                 GlassCardPanel {163164                     CardContent(ONBOARDING_CARDS[active])164165                     // The restore/adopt choice row only appears on the final165166                     // card (Onboarding.tsx's `card() === CARDS.length - 1`).166167                     if (active == cardCount - 1) {167-                        ChoiceRow(onRestore = onRestore, onAdopt = onAdopt)168+                        ChoiceRow(onRestore = onRestore, onAdopt = onAdopt, onCreate = advance)168169                     }169170                 }170171             }@@ -313,14 +314,24 @@313314 }314315 315316 /**316- * Card 3's two existing-vault entry points.317+ * Card 3's existing-vault entry points, plus the primary create-new-vault318+ * action (mirrors the browser's explicit choice — a final-card tap does not319+ * silently start creation).317320  */321+internal const val ONBOARD_CREATE_LABEL = "Create a new vault"318322 internal const val ONBOARD_PAIR_LABEL = "Pair with another device"319323 internal const val ONBOARD_RESTORE_LABEL = "Restore a backup"320324 321325 @Composable322-private fun ChoiceRow(onRestore: () -> Unit, onAdopt: () -> Unit) {326+private fun ChoiceRow(onRestore: () -> Unit, onAdopt: () -> Unit, onCreate: () -> Unit) {323327     Spacer(Modifier.height(18.dp))328+    ChoiceButton(329+        ONBOARD_CREATE_LABEL,330+        "Set your master password and start saving.",331+        onCreate,332+        primary = true,333+    )334+    Spacer(Modifier.height(8.dp))324335     Text(325336         "Already using Peach?",326337         color = peachColors.T1,@@ -342,13 +353,16 @@342353 }343354 344355 @Composable345-private fun ChoiceButton(label: String, detail: String, onClick: () -> Unit, pro: Boolean = false) {356+private fun ChoiceButton(label: String, detail: String, onClick: () -> Unit, primary: Boolean = false, pro: Boolean = false) {357+    val accent = LocalPeachAccent.current358+    val labelColor = if (primary) Color(0f, 0f, 0f, 0.92f) else peachColors.T0359+    val detailColor = if (primary) Color(0f, 0f, 0f, 0.72f) else peachColors.T1346360     Column(347361         modifier = Modifier348362             .fillMaxWidth()349363             .clip(RoundedCornerShape(8.dp))350-            .background(peachColors.T0.copy(alpha = 0.07f))351-            .border(1.dp, peachColors.T0.copy(alpha = 0.16f), RoundedCornerShape(8.dp))364+            .background(if (primary) accent else peachColors.T0.copy(alpha = 0.07f))365+            .border(1.dp, if (primary) accent else peachColors.T0.copy(alpha = 0.16f), RoundedCornerShape(8.dp))352366             .clickable(353367                 interactionSource = remember { MutableInteractionSource() },354368                 indication = null,@@ -359,12 +373,11 @@359373         Row(verticalAlignment = Alignment.CenterVertically) {360374             Text(361375                 label,362-                color = peachColors.T0,376+                color = labelColor,363377                 style = PeachType.labelMono.copy(fontSize = 11.sp, letterSpacing = 0.04.em),364378             )365379             if (pro) {366380                 Spacer(Modifier.width(6.dp))367-                val accent = LocalPeachAccent.current368381                 Box(369382                     Modifier370383                         .clip(RoundedCornerShape(4.dp))@@ -383,7 +396,7 @@383396         Spacer(Modifier.height(2.dp))384397         Text(385398             detail,386-            color = peachColors.T1,399+            color = detailColor,387400             style = PeachType.labelMono.copy(fontSize = 9.sp),388401         )389402     }

view file

app/src/test/java/com/peachpasswords/ui/onboarding/OnboardingTest.kt+1 −0
@@ -87,6 +87,7 @@8787     }8888 8989     @Test fun existing_user_choices_put_pairing_first_and_name_restore_separately() {90+        assertEquals("Create a new vault", ONBOARD_CREATE_LABEL)9091         assertEquals("Pair with another device", ONBOARD_PAIR_LABEL)9192         assertEquals("Restore a backup", ONBOARD_RESTORE_LABEL)9293     }

view file