b3531443f01c

fix C4 (persistent orange dot had a 0.28 alpha floor, now rests at 0), C6a (remove redundant global TOTP shell progress bar entirely), C6b (TOTP ring direction was inverted - now correctly depletes from full to empty), C7 (remove invented 'end of entry' marker from entry detail) - all live-verified on device against the 2026-07-24 critical corrections spec

time
2026-07-24 06:12 UTC · 3 months ago
machine
koh2
agent
claude-sonnet-5
session
critical-corrections-c1-c7
parent
8fe80db68ea0
5 files app/src/main/java/com/peachpasswords/ui/components/CopyFeedbackOverlay.kt+1 −1app/src/main/java/com/peachpasswords/ui/components/TOTPRing.kt+4 −1app/src/main/java/com/peachpasswords/ui/vault/EntryDetailScreen.kt+1 −5app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+1 −23app/src/test/java/com/peachpasswords/ui/vault/VaultListSyncDotTest.kt+0 −12
app/src/main/java/com/peachpasswords/ui/components/CopyFeedbackOverlay.kt+1 −1
@@ -78,7 +78,7 @@7878                     scaleY = scale7979                 }8080                 .clip(CircleShape)81-                .background(accent.copy(alpha = 0.28f + (pipPulse.value * 0.62f))),81+                .background(accent.copy(alpha = pipPulse.value)),8282         )8383     }8484 }

view file

app/src/main/java/com/peachpasswords/ui/components/TOTPRing.kt+4 −1
@@ -39,7 +39,10 @@3939         drawArc(4040             color = if (isHot) breach else accent,4141             startAngle = -90f,42-            sweepAngle = 360f * progress,42+            // Starts full at period start (progress=0), depletes to empty as the43+            // code approaches expiry (progress=1) — the conventional countdown44+            // direction, not "fills up as time passes."45+            sweepAngle = 360f * (1f - progress),4346             useCenter = false,4447             style = Stroke(stroke, cap = StrokeCap.Round),4548             topLeft = Offset(center.x - radius, center.y - radius),

view file

app/src/main/java/com/peachpasswords/ui/vault/EntryDetailScreen.kt+1 −5
@@ -334,11 +334,7 @@334334                     }335335                 }336336 337-                PeachEmptyOrEndState(338-                    message = "end of entry",339-                    detail = "All saved fields for this item are above.",340-                    modifier = Modifier.padding(top = PeachSpacing.md, bottom = PeachSpacing.lg),341-                )337+                Spacer(Modifier.height(PeachSpacing.xxl))342338             }343339 344340             if (e != null) {

view file

app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+1 −23
@@ -57,7 +57,6 @@5757 import androidx.compose.runtime.LaunchedEffect5858 import androidx.compose.runtime.getValue5959 import androidx.compose.runtime.mutableStateOf60-import androidx.compose.runtime.produceState6160 import androidx.compose.runtime.remember6261 import androidx.compose.runtime.setValue6362 import androidx.compose.ui.Alignment@@ -104,11 +103,9 @@104103 import com.peachpasswords.ui.theme.peachColors105104 import com.peachpasswords.ui.theme.PeachType106105 import com.peachpasswords.ui.theme.ShellBackground107-import com.peachpasswords.vault.TOTPGenerator108106 import com.peachpasswords.vault.VaultEntry109107 import com.peachpasswords.vault.hasTOTP110108 import com.peachpasswords.vault.isNote111-import kotlinx.coroutines.delay112109 import kotlin.math.abs113110 114111 @Composable@@ -180,7 +177,6 @@180177                 value = search,181178                 onChange = vm::setSearch,182179                 count = if (search.isNotBlank()) "${entries.size}/$total" else "$total",183-                totpActive = totpShellProgressActive(entries),184180             )185181             if (allTags.isNotEmpty()) {186182                 TagFilterStrip(@@ -423,24 +419,9 @@423419 }424420 425421 @Composable426-private fun SearchBar(value: String, onChange: (String) -> Unit, count: String, totpActive: Boolean) {422+private fun SearchBar(value: String, onChange: (String) -> Unit, count: String) {427423     val accent = LocalPeachAccent.current428-    // Global TOTP period progress — a 2dp accent tick above the field, ~10×/s.429-    val progress by produceState(0f) {430-        while (true) { this.value = TOTPGenerator.periodProgress(); delay(100) }431-    }432424     Column(Modifier.fillMaxWidth()) {433-        Box(434-            Modifier.fillMaxWidth().height(2.dp).drawBehind {435-                if (totpActive) {436-                    drawRect(437-                        color = accent.copy(alpha = 0.85f),438-                        size = Size(width = size.width * progress, height = size.height),439-                        topLeft = Offset.Zero,440-                    )441-                }442-            },443-        )444425         Row(445426             Modifier446427                 .fillMaxWidth()@@ -470,9 +451,6 @@470451         }471452     }472453 }473-474-internal fun totpShellProgressActive(entries: List<VaultEntry>): Boolean =475-    entries.any { it.hasTOTP() }476454 477455 @Composable478456 private fun SortBar(

view file

app/src/test/java/com/peachpasswords/ui/vault/VaultListSyncDotTest.kt+0 −12
@@ -2,10 +2,7 @@22 33 import androidx.compose.ui.graphics.Color44 import com.peachpasswords.sync.SyncStatus5-import com.peachpasswords.vault.VaultEntry65 import org.junit.Assert.assertEquals7-import org.junit.Assert.assertFalse8-import org.junit.Assert.assertTrue96 import org.junit.Test107 118 class VaultListSyncDotTest {@@ -20,15 +17,6 @@2017         assertEquals(syncing, dot(SyncStatus.Syncing))2118         assertEquals(synced, dot(SyncStatus.LastSynced(123L)))2219         assertEquals(error, dot(SyncStatus.Error("timeout")))23-    }24-25-    @Test fun totp_shell_progress_only_activates_when_entries_have_totp() {26-        val plain = VaultEntry(id = "plain", title = "Plain", createdAt = 1L, modifiedAt = 1L)27-        val totp = plain.copy(id = "totp", totp = "GEZDGNBVGY3TQOJQ")28-29-        assertFalse(totpShellProgressActive(emptyList()))30-        assertFalse(totpShellProgressActive(listOf(plain)))31-        assertTrue(totpShellProgressActive(listOf(plain, totp)))3220     }3321 3422     private fun dot(status: SyncStatus): Color =

view file