65202b932d76

feat: organize Vault settings card into collapsible groups (v2.10.21)

Vault card grew busy, so its six sections are now collapsible groups with tappable headings: ENTRIES, MAINTENANCE, DATA, UPDATES open by default; VAULT HISTORY and ADVANCED (replace-from-backup, destroy) start collapsed. Reuses existing row vocabulary via a SettingsGroup helper; no behavior changed, all rows preserved.

time
2026-08-04 14:59 UTC · 2 months ago
machine
koh2
parent
6f9ce481dbfb
2 files VERSION+1 −1app/src/main/java/com/peachpasswords/ui/settings/SettingsCardBodies.kt+51 −13
VERSION+1 −1
@@ -1 +1 @@1-2.10.201+2.10.21

view file

app/src/main/java/com/peachpasswords/ui/settings/SettingsCardBodies.kt+51 −13
@@ -122,7 +122,46 @@122122     )123123 }124124 125+/**126+ * Collapsible group inside a card body: the uppercase heading row toggles its127+ * rows, so busy cards can fold rarely-used sections away. Groups holding128+ * dangerous or rarely-used actions start collapsed.129+ */125130 @Composable131+private fun SettingsGroup(132+    label: String,133+    fg: Color,134+    initiallyOpen: Boolean = true,135+    top: Dp = 14.dp,136+    content: @Composable () -> Unit,137+) {138+    var open by remember { mutableStateOf(initiallyOpen) }139+    Row(140+        Modifier.fillMaxWidth()141+            .clip(RoundedCornerShape(6.dp))142+            .clickable { open = !open }143+            .padding(top = top, bottom = 4.dp),144+        verticalAlignment = Alignment.CenterVertically,145+    ) {146+        Text(147+            label,148+            modifier = Modifier.weight(1f),149+            color = fg.copy(alpha = 0.58f),150+            fontFamily = PeachType.Mono,151+            fontSize = 8.sp,152+            letterSpacing = 0.22.em,153+        )154+        Text(155+            if (open) "–" else "+",156+            color = fg.copy(alpha = 0.58f),157+            fontFamily = PeachType.Mono,158+            fontSize = 10.sp,159+        )160+    }161+    AnimatedVisibility(visible = open) { content() }162+}163+164+@Composable126165 private fun RowLine(127166     fg: Color,128167     modifier: Modifier = Modifier,@@ -547,7 +586,7 @@547586     val history by vm.vaultHistory.collectAsState()548587     val restoringSnapshotId by vm.restoringSnapshotId.collectAsState()549588 550-    SubLabel("ENTRIES", fg, top = 0.dp)589+    SettingsGroup("ENTRIES", fg, top = 0.dp) {551590     RowLine(fg) { Name("Entries", fg); ValueText("$entriesCount", fg) }552591     RowLine(fg) {553592         Name("Duplicates", fg)@@ -591,8 +630,9 @@591630             }592631         }593632     }633+    }594634 595-    SubLabel("MAINTENANCE", fg)635+    SettingsGroup("MAINTENANCE", fg) {596636     RowLine(fg) {597637         Name("Trash auto-delete", fg)598638         val idx = trashOptions.indexOfFirst { it.first == current }.coerceAtLeast(0)@@ -602,8 +642,9 @@602642     }603643     RowLine(fg) { Name("Advanced Vault Health", fg); SubtleButton("open", fg) { onNavigate(PeachNav.Health) } }604644     RowLine(fg) { Name("Trash", fg); SubtleButton("open", fg) { onNavigate(PeachNav.Trash) } }645+    }605646 606-    SubLabel("DATA", fg)647+    SettingsGroup("DATA", fg) {607648     RowLine(fg) { Name("Import passwords", fg); SubtleButton("open", fg) { onNavigate(PeachNav.Import) } }608649     RowLine(fg) { Name("Export backup", fg); SubtleButton("open", fg) { onNavigate(PeachNav.Export) } }609650     RowLine(fg) {@@ -611,12 +652,14 @@611652         SubtleButton(if (isPro) "open" else "Pro", fg) { if (isPro) onNavigate(PeachNav.CodexGenerate) }612653     }613654     RowLine(fg) { Name("Restore from Codex", fg); SubtleButton("open", fg) { onNavigate(PeachNav.CodexRestore) } }655+    }614656 615-    var historyShowAll by remember { mutableStateOf(false) }616-    SubLabel("UPDATES", fg)657+    SettingsGroup("UPDATES", fg) {617658     UpdatesRows(fg, onNavigate)659+    }618660 619-    SubLabel("VAULT HISTORY", fg)661+    SettingsGroup("VAULT HISTORY", fg, initiallyOpen = false) {662+    var historyShowAll by remember { mutableStateOf(false) }620663     if (history.isEmpty()) {621664         Text(622665             "No snapshots yet. Peach saves automatically before every change — saves, syncs, and imports.",@@ -660,14 +703,9 @@660703             modifier = Modifier.padding(top = 2.dp, bottom = 6.dp),661704         )662705     }663-664-    var advancedOpen by remember { mutableStateOf(false) }665-    SubLabel("ADVANCED", fg)666-    RowLine(fg) {667-        Name("Advanced", fg)668-        SubtleButton(if (advancedOpen) "hide" else "show", fg) { advancedOpen = !advancedOpen }669706     }670-    if (advancedOpen) {707+708+    SettingsGroup("ADVANCED", fg, initiallyOpen = false) {671709         RowLine(fg) {672710             Name("Replace vault from backup", com.peachpasswords.ui.theme.peachColors.SyncBusy)673711             SubtleButton("open", com.peachpasswords.ui.theme.peachColors.SyncBusy) { onNavigate(PeachNav.Import) }

view file