eb3db0cf92c2
fix: Match browser note save and delete behavior (v2.3.18)
- time
- 2026-06-26 01:38 UTC · 4 months ago
- machine
- koh2
- parent
- df73b22b6f1b
↓ peach-android-eb3db0cf.tar.gzatlas at this save
files changed4 files
app/build.gradle+2 −2app/src/main/java/com/peachpasswords/ui/vault/NotesModeScreen.kt+10 −1app/src/main/java/com/peachpasswords/ui/vault/NotesModeViewModel.kt+18 −0app/src/test/java/com/peachpasswords/ui/vault/NotesModeTest.kt+29 −0app/build.gradle+2 −2
@@ -16,8 +16,8 @@1616 applicationId "com.peachpasswords"1717 minSdk 261818 targetSdk 3519- versionCode 23170020- versionName "2.3.17"19+ versionCode 23180020+ versionName "2.3.18"2121 2222 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"2323 vectorDrawables {app/src/main/java/com/peachpasswords/ui/vault/NotesModeScreen.kt+10 −1
@@ -22,6 +22,7 @@2222 import androidx.compose.foundation.text.BasicTextField2323 import androidx.compose.material.icons.Icons2424 import androidx.compose.material.icons.automirrored.rounded.ArrowBack25+import androidx.compose.material.icons.outlined.DeleteOutline2526 import androidx.compose.material3.Icon2627 import androidx.compose.material3.Text2728 import androidx.compose.runtime.Composable@@ -111,7 +112,7 @@111112 Icon(112113 Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "back", tint = peachColors.T0,113114 modifier = Modifier.size(40.dp).clip(CircleShape)114- .clickable { vm.saveTitleNow(title); onBack() }.padding(8.dp),115+ .clickable { vm.saveNow(title, body.text); onBack() }.padding(8.dp),115116 )116117 Box(Modifier.weight(1f).padding(horizontal = 4.dp)) {117118 if (title.isEmpty()) {@@ -140,6 +141,14 @@140141 color = peachColors.T2,141142 style = TextStyle(fontFamily = PeachType.Mono, fontSize = 9.sp),142143 modifier = Modifier.padding(end = 8.dp).alpha(savedAlpha),144+ )145+ Icon(146+ Icons.Outlined.DeleteOutline,147+ contentDescription = "delete note",148+ tint = peachColors.T2,149+ modifier = Modifier.size(36.dp).clip(CircleShape)150+ .clickable { vm.delete(onBack) }151+ .padding(8.dp),143152 )144153 }145154 app/src/main/java/com/peachpasswords/ui/vault/NotesModeViewModel.kt+18 −0
@@ -60,6 +60,24 @@6060 commit { it.copy(title = title) }6161 }6262 63+ /** Browser parity: back navigation commits both title and body before leaving. */64+ fun saveNow(title: String, plainText: String) {65+ saveJob?.cancel()66+ commit {67+ it.copy(68+ title = title.ifBlank { "Untitled" },69+ notes = plainText.ifBlank { null },70+ )71+ }72+ }73+74+ fun delete(onDone: () -> Unit) {75+ viewModelScope.launch {76+ runCatching { vault.deleteEntry(id) }77+ onDone()78+ }79+ }80+6381 private fun scheduleSave(patch: (VaultEntry) -> VaultEntry) {6482 saveJob?.cancel()6583 saveJob = viewModelScope.launch {app/src/test/java/com/peachpasswords/ui/vault/NotesModeTest.kt+29 −0
@@ -123,4 +123,33 @@123123 advanceUntilIdle()124124 assertEquals("Trip plans", repo.getEntry(saved.id)?.title)125125 }126+127+ @Test fun notes_back_save_commits_title_and_body_immediately() = runTest(dispatcher) {128+ val repo = VaultRepository(FakeStorage())129+ repo.createVault("correct horse battery")130+ val saved = repo.addEntry(note("untitled"))131+ val vm = NotesModeViewModel(repo, SavedStateHandle(mapOf("id" to saved.id)))132+133+ vm.onContentChanged("draft")134+ advanceTimeBy(200)135+ vm.saveNow("Trip plans", "final body")136+ advanceUntilIdle()137+138+ assertEquals("Trip plans", repo.getEntry(saved.id)?.title)139+ assertEquals("final body", repo.getEntry(saved.id)?.notes)140+ }141+142+ @Test fun notes_delete_removes_note_from_active_lookup() = runTest(dispatcher) {143+ val repo = VaultRepository(FakeStorage())144+ repo.createVault("correct horse battery")145+ val saved = repo.addEntry(note("delete me"))146+ val vm = NotesModeViewModel(repo, SavedStateHandle(mapOf("id" to saved.id)))147+ var done = false148+149+ vm.delete { done = true }150+ advanceUntilIdle()151+152+ assertEquals(true, done)153+ assertNull(repo.getEntry(saved.id))154+ }126155 }