ac25ca315a1b

refactor: homogenize entry edit options (v2.14.52)

time
2026-08-15 00:12 UTC · 2 months ago
machine
koh2
parent
5cf4b795ab7d
5 files VERSION+1 −1app/src/main/java/com/peachpasswords/ui/vault/AdditionalUrlsEditor.kt+7 −3app/src/main/java/com/peachpasswords/ui/vault/EntryEditScreen.kt+49 −43app/src/main/java/com/peachpasswords/ui/vault/PasswordHistorySection.kt+2 −1app/src/test/java/com/peachpasswords/ui/vault/EntryEditScreenTest.kt+2 −3
VERSION+1 −1
@@ -1 +1 @@1-2.14.511+2.14.52

view file

app/src/main/java/com/peachpasswords/ui/vault/AdditionalUrlsEditor.kt+7 −3
@@ -27,6 +27,7 @@2727 import com.peachpasswords.ui.theme.LocalPeachAccent2828 import com.peachpasswords.ui.theme.peachColors2929 import com.peachpasswords.ui.theme.PeachType30+import com.peachpasswords.ui.theme.PeachSpacing3031 3132 /** E3 — hard cap on additional URLs, matching the spec. */3233 const val MAX_ADDITIONAL_URLS = 5@@ -46,9 +47,12 @@4647     onChange: (Int, String) -> Unit,4748     onAdd: () -> Unit,4849     onRemove: (Int) -> Unit,50+    embedded: Boolean = false,4951 ) {5052     val accent = LocalPeachAccent.current51-    Column(Modifier.fillMaxWidth()) {53+    Column(54+        Modifier.fillMaxWidth().padding(horizontal = if (embedded) PeachSpacing.lg else 0.dp),55+    ) {5256         urls.forEachIndexed { index, value ->5357             // Label numbering starts at 2 so it reads as a continuation of the5458             // primary URL field (which is conceptually "URL 1").@@ -105,7 +109,7 @@105109                     .clickable(onClick = onAdd)106110                     .padding(vertical = 4.dp),107111             )108-            Spacer(Modifier.height(14.dp))112+            Spacer(Modifier.height(if (embedded) 8.dp else 14.dp))109113         } else {110114             Text(111115                 "Max $MAX_ADDITIONAL_URLS additional URLs",@@ -113,7 +117,7 @@113117                 fontFamily = PeachType.Mono,114118                 fontSize = 9.sp,115119             )116-            Spacer(Modifier.height(14.dp))120+            Spacer(Modifier.height(if (embedded) 8.dp else 14.dp))117121         }118122     }119123 }

view file

app/src/main/java/com/peachpasswords/ui/vault/EntryEditScreen.kt+49 −43
@@ -109,7 +109,7 @@109109                     Modifier.fillMaxSize().verticalScroll(rememberScrollState()),110110                 ) {111111                     PeachSegmentedControl(112-                        segments = entryEditTypeSegments(vm.isNew),112+                        segments = entryEditTypeSegments(),113113                         selectedKey = f.type,114114                         onSelected = vm::setType,115115                     )@@ -119,6 +119,13 @@119119                     if (f.type == "login") {120120                         PeachFieldStack {121121                             Field("url", f.url, vm::setUrl, joined = true, divider = true)122+                            AdditionalUrlsEditor(123+                                urls = f.additionalUrls,124+                                onChange = vm::setAdditionalUrl,125+                                onAdd = vm::addAdditionalUrl,126+                                onRemove = vm::removeAdditionalUrl,127+                                embedded = true,128+                            )122129                             IdentitySuggestField(123130                                 "username", f.username, usernameSuggestions, vm::setUsername,124131                                 joined = true,@@ -137,34 +144,42 @@137144                                 onToggleShow = vm::toggleShowPassword,138145                                 onToggleGenerator = vm::toggleGenerator,139146                                 joined = true,147+                                divider = true,140148                             )149+                            GeneratorDrawer(150+                                open = f.generatorOpen,151+                                length = f.genLength,152+                                upper = f.genUpper, lower = f.genLower, numbers = f.genNumbers, symbols = f.genSymbols,153+                                password = f.password,154+                                copied = f.genCopied,155+                                onLength = vm::setGenLength,156+                                onUpper = vm::setGenUpper, onLower = vm::setGenLower,157+                                onNumbers = vm::setGenNumbers, onSymbols = vm::setGenSymbols,158+                                onGenerate = vm::generate,159+                                onCopy = vm::copyGenerated,160+                                onUse = vm::useGeneratedPassword,161+                                embedded = true,162+                            )163+                            PasswordHistorySection(164+                                history = f.history,165+                                expanded = f.showHistory,166+                                onToggle = vm::toggleHistory,167+                                onRestore = vm::restorePassword,168+                                onCopy = vm::copyHistoryPassword,169+                                embedded = true,170+                            )141171                         }142-                        GeneratorDrawer(143-                            open = f.generatorOpen,144-                            length = f.genLength,145-                            upper = f.genUpper, lower = f.genLower, numbers = f.genNumbers, symbols = f.genSymbols,146-                            password = f.password,147-                            copied = f.genCopied,148-                            onLength = vm::setGenLength,149-                            onUpper = vm::setGenUpper, onLower = vm::setGenLower,150-                            onNumbers = vm::setGenNumbers, onSymbols = vm::setGenSymbols,151-                            onGenerate = vm::generate,152-                            onCopy = vm::copyGenerated,153-                            onUse = vm::useGeneratedPassword,172+                        OptionalLoginAddLinks(173+                            showTotpLink = shouldShowAddTotpLink(f.type, f.showTotp, f.totp),174+                            showNotesLink = shouldShowLoginNotesLink(175+                                isNew = vm.isNew,176+                                type = f.type,177+                                revealed = f.showNotes,178+                                notes = f.notes,179+                            ),180+                            onAddTotp = vm::revealTotp,181+                            onAddNotes = vm::revealNotes,154182                         )155-                        AdditionalUrlsEditor(156-                            urls = f.additionalUrls,157-                            onChange = vm::setAdditionalUrl,158-                            onAdd = vm::addAdditionalUrl,159-                            onRemove = vm::removeAdditionalUrl,160-                        )161-                        PasswordHistorySection(162-                            history = f.history,163-                            expanded = f.showHistory,164-                            onToggle = vm::toggleHistory,165-                            onRestore = vm::restorePassword,166-                            onCopy = vm::copyHistoryPassword,167-                        )168183                         if (shouldShowLoginTotp(f.type, f.showTotp, f.totp)) {169184                             Field("2FA secret (otpauth:// or base32)", f.totp, vm::setTotp)170185                         }@@ -190,17 +205,6 @@190205                         Field("notes", f.notes, vm::setNotes, singleLine = false)191206                     }192207                     if (f.type == "login") {193-                        OptionalLoginAddLinks(194-                            showTotpLink = shouldShowAddTotpLink(f.type, f.showTotp, f.totp),195-                            showNotesLink = shouldShowLoginNotesLink(196-                                isNew = vm.isNew,197-                                type = f.type,198-                                revealed = f.showNotes,199-                                notes = f.notes,200-                            ),201-                            onAddTotp = vm::revealTotp,202-                            onAddNotes = vm::revealNotes,203-                        )204208                         CanaryEditSection(205209                             entryId = id ?: "new",206210                             modifiedAt = f.canary?.lastPinged ?: 0L,@@ -274,11 +278,10 @@274278     else -> "new entry"275279 }276280 277-internal fun entryEditTypeSegments(isNew: Boolean): List<PeachSegment> = buildList {278-    add(PeachSegment("login", "login"))279-    if (!isNew) add(PeachSegment("note", "note"))280-    add(PeachSegment("card", "card"))281-}281+internal fun entryEditTypeSegments(): List<PeachSegment> = listOf(282+    PeachSegment("login", "login"),283+    PeachSegment("card", "card"),284+)282285 283286 internal fun entryEditPrimaryActionLabel(isNew: Boolean, saving: Boolean): String = when {284287     saving -> "saving..."@@ -371,6 +374,7 @@371374     onToggleShow: () -> Unit,372375     onToggleGenerator: () -> Unit,373376     joined: Boolean = false,377+    divider: Boolean = false,374378 ) {375379     Field(376380         label = "password",@@ -378,6 +382,7 @@378382         onChange = onChange,379383         transformation = if (show) VisualTransformation.None else PasswordVisualTransformation(),380384         joined = joined,385+        divider = divider,381386         trailing = {382387             Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {383388                 PasswordAction(if (show) "hide" else "show", onToggleShow)@@ -418,6 +423,7 @@418423     onGenerate: () -> Unit,419424     onCopy: () -> Unit,420425     onUse: () -> Unit,426+    embedded: Boolean = false,421427 ) {422428     val height by animateDpAsState(423429         targetValue = if (open) 326.dp else 0.dp,@@ -441,7 +447,7 @@441447             onUse = onUse,442448         )443449     }444-    if (open) Spacer(Modifier.height(14.dp))450+    if (open) Spacer(Modifier.height(if (embedded) 8.dp else 14.dp))445451 }446452 447453 /**

view file

app/src/main/java/com/peachpasswords/ui/vault/PasswordHistorySection.kt+2 −1
@@ -50,8 +50,9 @@5050     onToggle: () -> Unit,5151     onRestore: (String) -> Unit,5252     onCopy: (String) -> Unit,53+    embedded: Boolean = false,5354 ) {54-    Column(Modifier.fillMaxWidth().padding(bottom = 14.dp)) {55+    Column(Modifier.fillMaxWidth().padding(bottom = if (embedded) 8.dp else 14.dp)) {5556         PasswordHistoryToggle(count = history.size, expanded = expanded, onToggle = onToggle)5657         if (expanded) {5758             Spacer(Modifier.height(8.dp))

view file

app/src/test/java/com/peachpasswords/ui/vault/EntryEditScreenTest.kt+2 −3
@@ -37,9 +37,8 @@3737 3838     // ── New Entry creates logins/cards; Notes mode creates notes ─────────────3939 40-    @Test fun new_entry_type_picker_excludes_notes() {41-        assertEquals(listOf("login", "card"), entryEditTypeSegments(isNew = true).map { it.key })42-        assertEquals(listOf("login", "note", "card"), entryEditTypeSegments(isNew = false).map { it.key })40+    @Test fun entry_type_picker_excludes_notes_for_new_and_existing_entries() {41+        assertEquals(listOf("login", "card"), entryEditTypeSegments().map { it.key })4342     }4443 4544     // ── Ghost watermark fades in as the title is typed ────────────────────────

view file