b2f98db39dab
fix task 29: expose username and email as separate fields on entry detail - VaultEntry already had both as distinct optional fields (username, email), but EntryDetailScreen only ever rendered whichever was present and silently dropped the row entirely for a blank one, with no way to add the missing field from the detail screen at all - a real gap vs. the browser, which shows a '+ add username'/'+ add email' link for the missing field. Added per-field show/hide state seeded from whether the entry already has a value, with '+ add username'/'+ add email' links (reusing the existing '+ add another url' link pattern) that reveal an EditableFieldRow with the matching placeholder when tapped. Live-verified on the GitHub demo entry (username only): '+ add email' link appears, tapping it reveals an EMAIL row with 'add email' placeholder ready to edit.
- time
- 2026-07-24 13:42 UTC · 3 months ago
- machine
- koh2
- agent
- claude-sonnet-5
- session
- critical-corrections-c1-c7
- parent
- 1476a6674ce6
↓ peach-android-b2f98db3.tar.gzatlas at this save
files changed1 file
app/src/main/java/com/peachpasswords/ui/vault/EntryDetailScreen.kt+37 −6app/src/main/java/com/peachpasswords/ui/vault/EntryDetailScreen.kt+37 −6
@@ -254,23 +254,54 @@254254 placeholder = "add url",255255 )256256 }257- e.username?.takeIf { it.isNotBlank() }?.let { v ->257+ // Browser distinguishes USERNAME and EMAIL as separate258+ // optional fields, with a "+ add X" link for whichever the259+ // entry doesn't have yet — an entry can carry both. This260+ // used to just omit the row entirely for a blank field,261+ // with no way to add it from the detail screen.262+ var showUsernameField by remember(e.id) { mutableStateOf(!e.username.isNullOrBlank()) }263+ var showEmailField by remember(e.id) { mutableStateOf(!e.email.isNullOrBlank()) }264+ if (showUsernameField) {258265 EditableFieldRow(259- label = "username", field = "username", value = v,266+ label = "username", field = "username", value = e.username.orEmpty(),260267 copied = copiedField == "username",261- onCopy = { vm.copy("username", v) },268+ onCopy = { vm.copy("username", e.username) },262269 onSave = { vm.updateField("username", it) },263270 suggestions = identitySuggestions,271+ placeholder = "add username",264272 )265273 }266- e.email?.takeIf { it.isNotBlank() }?.let { v ->274+ if (showEmailField) {267275 EditableFieldRow(268- label = "email", field = "email", value = v,276+ label = "email", field = "email", value = e.email.orEmpty(),269277 copied = copiedField == "email",270- onCopy = { vm.copy("email", v) },278+ onCopy = { vm.copy("email", e.email) },271279 onSave = { vm.updateField("email", it) },272280 suggestions = identitySuggestions,281+ placeholder = "add email",273282 )283+ }284+ if (!showUsernameField || !showEmailField) {285+ Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {286+ if (!showUsernameField) {287+ Text(288+ "+ add username", color = accent, style = PeachType.labelMono,289+ modifier = Modifier290+ .clip(RoundedCornerShape(6.dp))291+ .clickable { showUsernameField = true }292+ .padding(vertical = 6.dp),293+ )294+ }295+ if (!showEmailField) {296+ Text(297+ "+ add email", color = accent, style = PeachType.labelMono,298+ modifier = Modifier299+ .clip(RoundedCornerShape(6.dp))300+ .clickable { showEmailField = true }301+ .padding(vertical = 6.dp),302+ )303+ }304+ }274305 }275306 AdditionalUrlRows(276307 urls = e.additionalUrls.orEmpty(),