098f165bba88
fix: Stop post-unlock nav clobbering the autofill new-entry redirect (v2.14.9)
- time
- 2026-08-06 00:33 UTC · 2 months ago
- machine
- koh2
- parent
- ba1cd3cf8da3
↓ peach-android-098f165b.tar.gzatlas at this save
files changed4 files
VERSION+1 −1app/src/main/java/com/peachpasswords/ui/lock/LockScreen.kt+8 −2app/src/test/java/com/peachpasswords/autofill/AutofillNavRepositoryTest.kt+50 −0releases/v2.14.9.md+2 −0app/src/main/java/com/peachpasswords/ui/lock/LockScreen.kt+8 −2
@@ -102,12 +102,18 @@102102 val createBlocker = if (state.hasVault || password.isEmpty()) null103103 else createValidationError(password, confirm, createScore)104104 105- LaunchedEffect(state.unlocked, autofillPending) {105+ // Keyed on `state.unlocked` only: the autofill nav path in PeachAppNavHost consumes106+ // `newEntryRequest` synchronously, which would otherwise flip `autofillPending` to107+ // false mid-unlock and re-fire this effect — landing the user on the vault list108+ // instead of the new-entry editor. Capturing `autofillPending` at the unlock109+ // transition (rather than re-reading it on every key change) makes the two effects110+ // cooperative instead of racing.111+ LaunchedEffect(state.unlocked) {106112 if (state.unlocked) {107113 // A freshly created vault routes through recovery-word setup before the list;108114 // an ordinary unlock lands on the last-viewed entry (brief Fix 3). The autofill109115 // nav host handles its own destinations when autofillPending is set; stepping in110- // here would race with it (this LaunchedEffect's popUpTo(0) wins by ordering).116+ // here would clobber that navigation with `popUpTo(0)`.111117 if (state.created) onNavigate(PeachNav.RecoverySetup)112118 else if (autofillPending) Unit113119 else onUnlocked(vm.postUnlockDestination())app/src/test/java/com/peachpasswords/autofill/AutofillNavRepositoryTest.kt+50 −0
@@ -0,0 +1,50 @@1+package com.peachpasswords.autofill2+3+import org.junit.Assert.assertEquals4+import org.junit.Assert.assertNull5+import org.junit.Test6+7+/**8+ * AutofillNavRepository carries the one-shot "open the new-entry editor" request9+ * from the autofill picker through MainActivity to PeachAppNavHost. The NavHost10+ * consumes the request as part of its LaunchedEffect, so the repository must11+ * surface the request exactly once before clearing — re-firing the LockScreen12+ * post-unlock branch after the consume is what made the new-entry redirect13+ * land on the vault list instead of the editor.14+ */15+class AutofillNavRepositoryTest {16+17+ @Test fun request_makes_payload_visible_to_collectors() {18+ val repo = AutofillNavRepository()19+ assertNull(repo.newEntryRequest.value)20+ repo.requestNewEntry(url = "https://github.com/login", username = "june", email = null)21+ val req = repo.newEntryRequest.value22+ assertEquals("https://github.com/login", req?.url)23+ assertEquals("june", req?.username)24+ assertNull(req?.email)25+ }26+27+ @Test fun blank_optional_fields_are_dropped_from_the_payload() {28+ // Hosts that don't surface a typed username/email pass empty strings;29+ // these must not pollute the new-entry editor's prefill.30+ val repo = AutofillNavRepository()31+ repo.requestNewEntry(url = "", username = "", email = "")32+ val req = repo.newEntryRequest.value33+ assertEquals(null, req?.url)34+ assertEquals(null, req?.username)35+ assertEquals(null, req?.email)36+ }37+38+ @Test fun consume_clears_the_request_so_lock_screen_does_not_re_fire_on_post_unlock() {39+ // Regression: the v2.14.5 guard in LockScreen was keyed on `autofillPending`,40+ // so when the NavHost's LaunchedEffect consumed the request the key41+ // flipped and LockScreen re-fired `onUnlocked(...)`, dropping the user42+ // on the vault list. The repository must surface exactly one non-null43+ // value across the request/consume cycle, never two.44+ val repo = AutofillNavRepository()45+ repo.requestNewEntry(url = "https://example.com", username = null, email = null)46+ assertEquals("https://example.com", repo.newEntryRequest.value?.url)47+ repo.consumeNewEntryRequest()48+ assertNull(repo.newEntryRequest.value)49+ }50+}releases/v2.14.9.md+2 −0
@@ -0,0 +1,2 @@1+## Fixes2+- Tapping "+ Create new entry" from the autofill picker used to land you back in the vault list after unlocking instead of opening the new-entry editor with the URL pre-filled. LockScreen and the NavHost were both reacting to the unlock transition; the NavHost consumed the autofill request first, which flipped the LockScreen guard's key and re-fired its "where to land?" branch — overwriting the editor with a `popUpTo(0)`.