aa9cb4d3508c

mirror deck-root EntryDetailScreen top bar to the browser's persistent peach-chrome header: leading PeachMark + peach wordmark title (was a lock icon + entry/domain title), actions reordered to Notes, Settings, New entry, Delete, Lock trailing-last (was Lock leading, Add/Settings/Delete trailing); add PeachNav.VaultNotes route (VaultListScreen with startNoteOnly) as the nearest Android equivalent to the browser's dedicated secure-notes overlay for the new Notes action

time
2026-07-24 17:13 UTC · 3 months ago
machine
koh2
agent
claude-sonnet-5
session
mirror entry-deck top bar to browser chrome
parent
501a671f57b5
4 files app/src/main/java/com/peachpasswords/ui/PeachAppNavHost.kt+8 −0app/src/main/java/com/peachpasswords/ui/PeachNav.kt+5 −0app/src/main/java/com/peachpasswords/ui/vault/EntryDetailScreen.kt+42 −22app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+7 −0
app/src/main/java/com/peachpasswords/ui/PeachAppNavHost.kt+8 −0
@@ -155,6 +155,14 @@155155                 onBack = if (hasOrigin) ({ navController.popBackStack() }) else null,156156             )157157         }158+        composable(PeachNav.VaultNotes.route) {159+            val hasOrigin = navController.previousBackStackEntry != null160+            VaultListScreen(161+                onNavigate = nav,162+                onBack = if (hasOrigin) ({ navController.popBackStack() }) else null,163+                startNoteOnly = true,164+            )165+        }158166 159167         composable(160168             route = PeachNav.EntryDetail.ROUTE,

view file

app/src/main/java/com/peachpasswords/ui/PeachNav.kt+5 −0
@@ -10,6 +10,11 @@1010     data object Lock : PeachNav("lock")1111     data object VaultList : PeachNav("vault")1212 13+    /** Same list, pre-filtered to notes — the closest Android equivalent to the14+     * browser's dedicated secure-notes overlay, reached from the entry-deck15+     * chrome's "Notes" action. */16+    data object VaultNotes : PeachNav("vault/notes")17+1318     data class EntryDetail(val id: String) : PeachNav("entry/$id") {1419         companion object {1520             const val ROUTE = "entry/{id}"

view file

app/src/main/java/com/peachpasswords/ui/vault/EntryDetailScreen.kt+42 −22
@@ -41,6 +41,7 @@4141 import androidx.compose.material.icons.Icons4242 import androidx.compose.material.icons.automirrored.rounded.ArrowBack4343 import androidx.compose.material.icons.automirrored.rounded.ArrowForward44+import androidx.compose.material.icons.automirrored.outlined.Notes4445 import androidx.compose.material.icons.outlined.DeleteOutline4546 import androidx.compose.material.icons.outlined.Lock4647 import androidx.compose.material3.Icon@@ -78,6 +79,7 @@7879 import com.peachpasswords.ui.components.CharEnterText7980 import com.peachpasswords.ui.components.CopyButton8081 import com.peachpasswords.ui.components.PeachEmptyOrEndState82+import com.peachpasswords.ui.components.PeachMark8183 import com.peachpasswords.ui.components.PeachTopBar8284 import com.peachpasswords.ui.components.SecureFlagEffect8385 import com.peachpasswords.ui.components.TOTPRing@@ -167,6 +169,7 @@167169                     },168170                     onAddEntry = { onNavigate(PeachNav.EntryEdit(null)) },169171                     onSettings = { onNavigate(PeachNav.Settings) },172+                    onOpenNotes = { onNavigate(PeachNav.VaultNotes) },170173                 )171174                 Spacer(Modifier.height(PeachSpacing.lg))172175 @@ -433,12 +436,18 @@433436     onDelete: () -> Unit,434437     onAddEntry: () -> Unit,435438     onSettings: () -> Unit,439+    onOpenNotes: () -> Unit,436440 ) {437441     val domain = remember(entry?.url, entry?.title) { entry?.displayDomain().orEmpty() }438442     PeachTopBar(439443         title = when {444+            confirmingDelete && entry != null -> "delete \"${entry.title}\"?"445+            // Deck root (no back target) mirrors the browser's persistent446+            // header, which always shows the "peach" wordmark — never the447+            // current entry's identity — leaving PeachMark in `leading` below448+            // to complete the wordmark pairing (see LockScreen's same pattern).449+            onBack == null -> "peach"440450             entry == null -> "entry"441-            confirmingDelete -> "delete \"${entry.title}\"?"442451             domain.isNotEmpty() -> domain443452             else -> entry.title444453         },@@ -455,21 +464,7 @@455464                         .padding(PeachSpacing.sm),456465                 )457466             } else {458-                // This entry is the post-unlock landing surface, not pushed459-                // from the vault list — there's nothing to go "back" to, so460-                // the chrome offers the one action that actually makes sense461-                // here instead (lock vault list's own affordance). Same 40dp462-                // tap target and padding as every other icon in this bar.463-                Icon(464-                    Icons.Outlined.Lock,465-                    contentDescription = "Lock vault",466-                    tint = peachColors.T1,467-                    modifier = Modifier468-                        .size(40.dp)469-                        .clip(CircleShape)470-                        .clickable(onClick = onLock)471-                        .padding(PeachSpacing.sm),472-                )467+                PeachMark(modifier = Modifier.padding(start = PeachSpacing.sm, end = PeachSpacing.xs))473468             }474469             // The favicon chip used to sit here, but it's the one loud,475470             // colorful element in an otherwise quiet/muted bar (matching the@@ -480,18 +475,21 @@480475         actions = {481476             // This entry is the deck root (no back target) — it's the closest482477             // thing this app has to a "home" screen, so it's where the483-            // persistent add/settings actions live now. They used to sit in a484-            // bar on the vault list, but that's a sheet reached by sliding up485-            // from here (C1), not a screen of its own anymore.478+            // persistent chrome actions live now, mirroring the browser's479+            // peach-chrome header exactly: Notes, Settings, New entry, then480+            // Lock last/trailing (peach-browser/src/popup/App.tsx ~1347-1408).481+            // Delete has no browser-chrome equivalent (it lives in the entry's482+            // own view there) — kept here, grouped with the other483+            // content-mutating actions just before the terminal Lock action.486484             if (onBack == null) {487485                 Icon(488-                    Icons.Rounded.Add,489-                    contentDescription = "new entry",486+                    Icons.AutoMirrored.Outlined.Notes,487+                    contentDescription = "Notes",490488                     tint = peachColors.T1,491489                     modifier = Modifier492490                         .size(40.dp)493491                         .clip(CircleShape)494-                        .clickable(onClick = onAddEntry)492+                        .clickable(onClick = onOpenNotes)495493                         .padding(PeachSpacing.sm),496494                 )497495                 Icon(@@ -504,6 +502,16 @@504502                         .clickable(onClick = onSettings)505503                         .padding(PeachSpacing.sm),506504                 )505+                Icon(506+                    Icons.Rounded.Add,507+                    contentDescription = "new entry",508+                    tint = peachColors.T1,509+                    modifier = Modifier510+                        .size(40.dp)511+                        .clip(CircleShape)512+                        .clickable(onClick = onAddEntry)513+                        .padding(PeachSpacing.sm),514+                )507515             }508516             if (entry != null) {509517                 Icon(@@ -514,6 +522,18 @@514522                         .size(40.dp)515523                         .clip(CircleShape)516524                         .clickable(onClick = onDelete)525+                        .padding(PeachSpacing.sm),526+                )527+            }528+            if (onBack == null) {529+                Icon(530+                    Icons.Outlined.Lock,531+                    contentDescription = "Lock vault",532+                    tint = peachColors.T1,533+                    modifier = Modifier534+                        .size(40.dp)535+                        .clip(CircleShape)536+                        .clickable(onClick = onLock)517537                         .padding(PeachSpacing.sm),518538                 )519539             }

view file

app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+7 −0
@@ -114,8 +114,15 @@114114     // search strip — slide back down to collapse to that entry. Null when115115     // the list itself is the deck root (e.g. empty vault, nothing to open).116116     onBack: (() -> Unit)? = null,117+    // True when reached via the entry-deck chrome's "Notes" action — pre-applies118+    // the notes filter pill so the list opens already scoped to notes, the119+    // closest equivalent to the browser's dedicated secure-notes overlay.120+    startNoteOnly: Boolean = false,117121     vm: VaultListViewModel = hiltViewModel(),118122 ) {123+    LaunchedEffect(Unit) {124+        if (startNoteOnly && !vm.noteOnly.value) vm.toggleNoteFilter()125+    }119126     val entries by vm.entries.collectAsState()120127     val sort by vm.sort.collectAsState()121128     val search by vm.search.collectAsState()

view file