33e27acd130d

fix: Match browser optional add-entry fields (v2.3.10)

time
2026-06-26 01:05 UTC · 4 months ago
machine
koh2
parent
83e1953cc74f
4 files app/build.gradle+2 −2app/src/main/java/com/peachpasswords/ui/vault/EntryEditScreen.kt+54 −2app/src/main/java/com/peachpasswords/ui/vault/EntryEditViewModel.kt+6 −0app/src/test/java/com/peachpasswords/ui/vault/EntryEditScreenTest.kt+18 −0
app/build.gradle+2 −2
@@ -16,8 +16,8 @@1616         applicationId "com.peachpasswords"1717         minSdk 261818         targetSdk 3519-        versionCode 23090020-        versionName "2.3.9"19+        versionCode 23100020+        versionName "2.3.10"2121 2222         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"2323         vectorDrawables {

view file

app/src/main/java/com/peachpasswords/ui/vault/EntryEditScreen.kt+54 −2
@@ -149,7 +149,9 @@149149                         onRestore = vm::restorePassword,150150                         onCopy = vm::copyHistoryPassword,151151                     )152-                    Field("2FA secret (otpauth:// or base32)", f.totp, vm::setTotp)152+                    if (shouldShowLoginTotp(f.type, f.showTotp, f.totp)) {153+                        Field("2FA secret (otpauth:// or base32)", f.totp, vm::setTotp)154+                    }153155                 }154156                 if (f.type == "card") {155157                     CardEditFields(@@ -166,7 +168,17 @@166168                         onToggleShowCvc = vm::toggleShowCvc,167169                     )168170                 }169-                Field("notes", f.notes, vm::setNotes, singleLine = false)171+                if (f.type == "note" || shouldShowLoginNotes(f.type, f.showNotes, f.notes)) {172+                    Field("notes", f.notes, vm::setNotes, singleLine = false)173+                }174+                if (f.type == "login") {175+                    OptionalLoginAddLinks(176+                        showTotpLink = shouldShowAddTotpLink(f.type, f.showTotp, f.totp),177+                        showNotesLink = shouldShowAddNotesLink(f.type, f.showNotes, f.notes),178+                        onAddTotp = vm::revealTotp,179+                        onAddNotes = vm::revealNotes,180+                    )181+                }170182                 TagChipEditor(171183                     tags = f.tags,172184                     allTags = vm.allTags,@@ -223,6 +235,46 @@223235 224236 /** Target alpha for the edit-screen ghost watermark — visible only once a title exists. */225237 internal fun editGhostWatermarkTarget(title: String): Float = if (title.isNotBlank()) 0.03f else 0f238+239+internal fun shouldShowLoginTotp(type: String, revealed: Boolean, totp: String): Boolean =240+    type == "login" && (revealed || totp.isNotBlank())241+242+internal fun shouldShowLoginNotes(type: String, revealed: Boolean, notes: String): Boolean =243+    type == "login" && (revealed || notes.isNotBlank())244+245+internal fun shouldShowAddTotpLink(type: String, revealed: Boolean, totp: String): Boolean =246+    type == "login" && !shouldShowLoginTotp(type, revealed, totp)247+248+internal fun shouldShowAddNotesLink(type: String, revealed: Boolean, notes: String): Boolean =249+    type == "login" && !shouldShowLoginNotes(type, revealed, notes)250+251+@Composable252+private fun OptionalLoginAddLinks(253+    showTotpLink: Boolean,254+    showNotesLink: Boolean,255+    onAddTotp: () -> Unit,256+    onAddNotes: () -> Unit,257+) {258+    if (!showTotpLink && !showNotesLink) return259+    Row(260+        Modifier.fillMaxWidth().padding(top = 4.dp, bottom = 8.dp),261+        horizontalArrangement = Arrangement.spacedBy(14.dp),262+    ) {263+        if (showTotpLink) AddFieldLink("+ add 2FA", onAddTotp)264+        if (showNotesLink) AddFieldLink("+ add notes", onAddNotes)265+    }266+}267+268+@Composable269+private fun AddFieldLink(label: String, onClick: () -> Unit) {270+    Text(271+        label,272+        color = LocalPeachAccent.current,273+        fontFamily = PeachType.Mono,274+        fontSize = 11.sp,275+        modifier = Modifier.clip(RoundedCornerShape(6.dp)).clickable(onClick = onClick).padding(vertical = 6.dp),276+    )277+}226278 227279 @Composable228280 private fun Field(

view file

app/src/main/java/com/peachpasswords/ui/vault/EntryEditViewModel.kt+6 −0
@@ -47,6 +47,8 @@4747     val genSymbols: Boolean = true,4848     val saving: Boolean = false,4949     val error: String? = null,50+    val showTotp: Boolean = false,51+    val showNotes: Boolean = false,5052 )5153 5254 @HiltViewModel@@ -78,6 +80,8 @@7880                 cardNetwork = it.cardNetwork ?: CardFieldUtils.detectNetwork(it.cardNumber.orEmpty()),7981                 tags = it.tags.orEmpty(),8082                 history = it.passwordHistory.orEmpty(),83+                showTotp = !it.totp.isNullOrBlank(),84+                showNotes = !it.notes.isNullOrBlank(),8185             )8286         } ?: EditForm(),8387     )@@ -123,6 +127,8 @@123127     }124128     fun setTotp(v: String) = _form.update { it.copy(totp = v) }125129     fun setNotes(v: String) = _form.update { it.copy(notes = v) }130+    fun revealTotp() = _form.update { it.copy(showTotp = true) }131+    fun revealNotes() = _form.update { it.copy(showNotes = true) }126132     fun setCardNumber(v: String) = _form.update {127133         val formatted = CardFieldUtils.formatPan(v)128134         it.copy(cardNumber = formatted, cardNetwork = CardFieldUtils.detectNetwork(formatted), error = null)

view file

app/src/test/java/com/peachpasswords/ui/vault/EntryEditScreenTest.kt+18 −0
@@ -38,6 +38,24 @@3838         assertEquals(0.03f, editGhostWatermarkTarget("GitHub"), 0f)3939     }4040 41+    // ── Browser AddView optional login fields ────────────────────────────────42+43+    @Test fun new_login_hides_optional_totp_and_notes_until_requested() {44+        assertFalse(shouldShowLoginTotp("login", revealed = false, totp = ""))45+        assertFalse(shouldShowLoginNotes("login", revealed = false, notes = ""))46+        assertTrue(shouldShowAddTotpLink("login", revealed = false, totp = ""))47+        assertTrue(shouldShowAddNotesLink("login", revealed = false, notes = ""))48+    }49+50+    @Test fun optional_login_fields_show_when_revealed_or_populated() {51+        assertTrue(shouldShowLoginTotp("login", revealed = true, totp = ""))52+        assertTrue(shouldShowLoginTotp("login", revealed = false, totp = "JBSWY3DPEHPK3PXP"))53+        assertTrue(shouldShowLoginNotes("login", revealed = true, notes = ""))54+        assertTrue(shouldShowLoginNotes("login", revealed = false, notes = "remember this"))55+        assertFalse(shouldShowAddTotpLink("login", revealed = true, totp = ""))56+        assertFalse(shouldShowAddNotesLink("login", revealed = false, notes = "remember this"))57+    }58+4159     // ── Card field formatting (CardFieldUtils, used live by setCardNumber etc.) ─4260 4361     @Test fun new_card_number_auto_formats() {

view file