From 077c82b63d6af8607846da8969202ea927b46c74 Mon Sep 17 00:00:00 2001 From: Shubham Bhandari Date: Tue, 15 Sep 2026 11:39:37 +0800 Subject: [PATCH] The watch had the reactivity bug too, on all four screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checked the wear module for the same mistake review had just caught twice on the phone, and it was there. `WearPeerIdentityState.snapshot` now reads the announced nickname to decide whether the seal still applies, but all four screens cache it with `remember(peerID, revision)` — and `revision` is bumped by favourites and verification changes, never by a peer renaming. So the name repainted while the cached `isVerified`, and its seal, survived. Same defect Codex found in `PeopleSection` and `PrivateChatSheet`, in a module neither reviewer looked at. All four now key on the announced nickname: DmScreen, PeerDebugScreen, VerificationCodeScreen and UserDetailScreen. The last of those I had missed even after deciding to audit this module — grepping for the snapshot call found three, and the fourth only turned up when I grepped for the remember key instead. It draws a seal like the others. Nothing else here needs gating: every wear screen reads `identity.isVerified` straight from the snapshot, so there is no second independent source the way the phone's SecurityVerificationSheet had one. Co-Authored-By: Claude Opus 5 --- wear/src/main/java/com/bitchat/watch/ui/DmScreen.kt | 7 ++++++- wear/src/main/java/com/bitchat/watch/ui/PeerDebugScreen.kt | 3 ++- .../src/main/java/com/bitchat/watch/ui/UserDetailScreen.kt | 7 +++++-- .../java/com/bitchat/watch/ui/VerificationCodeScreen.kt | 4 +++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/wear/src/main/java/com/bitchat/watch/ui/DmScreen.kt b/wear/src/main/java/com/bitchat/watch/ui/DmScreen.kt index d0e675ea..280fee4a 100644 --- a/wear/src/main/java/com/bitchat/watch/ui/DmScreen.kt +++ b/wear/src/main/java/com/bitchat/watch/ui/DmScreen.kt @@ -75,7 +75,12 @@ fun DmScreen( val nickname = mesh?.getPeerNickname(peerID) ?: peerID.take(8) val identityRevision by WearPeerIdentityState.revision.collectAsState() - val identity = remember(peerID, identityRevision) { + // Keyed on the announced nickname too: the snapshot now reads it to + // decide whether the seal still applies, and `revision` is bumped by + // favourites and verification changes, never by a peer renaming. Without + // this the name repaints while the cached "verified" — and its seal — + // survives, which is the live impersonation the binding exists to stop. + val identity = remember(peerID, identityRevision, nickname) { WearPeerIdentityState.snapshot(peerID, mesh) } var sessionEstablished by remember { diff --git a/wear/src/main/java/com/bitchat/watch/ui/PeerDebugScreen.kt b/wear/src/main/java/com/bitchat/watch/ui/PeerDebugScreen.kt index 1994f976..d9e8ac3c 100644 --- a/wear/src/main/java/com/bitchat/watch/ui/PeerDebugScreen.kt +++ b/wear/src/main/java/com/bitchat/watch/ui/PeerDebugScreen.kt @@ -76,7 +76,8 @@ fun PeerDebugScreen() { items(peers) { peerID -> val nick = nicknames[peerID] ?: peerID.take(8) val encrypted = mesh?.hasEstablishedSession(peerID) == true - val identity = androidx.compose.runtime.remember(peerID, identityRevision) { + // Keyed on the nickname too — see DmScreen. + val identity = androidx.compose.runtime.remember(peerID, identityRevision, nick) { WearPeerIdentityState.snapshot(peerID, mesh) } Row( diff --git a/wear/src/main/java/com/bitchat/watch/ui/UserDetailScreen.kt b/wear/src/main/java/com/bitchat/watch/ui/UserDetailScreen.kt index fd6a347f..ec39e318 100644 --- a/wear/src/main/java/com/bitchat/watch/ui/UserDetailScreen.kt +++ b/wear/src/main/java/com/bitchat/watch/ui/UserDetailScreen.kt @@ -40,10 +40,13 @@ fun UserDetailScreen( ) { val mesh = WearMeshService.peek() val revision by WearPeerIdentityState.revision.collectAsState() - val identity = androidx.compose.runtime.remember(peerID, revision) { + val nickname = mesh?.getPeerNickname(peerID) ?: peerID.take(8) + // Keyed on the announced nickname too — see DmScreen. This screen draws the + // seal as well, so without it a rename repaints the name here and leaves + // the checkmark sitting beside the new one. + val identity = androidx.compose.runtime.remember(peerID, revision, nickname) { WearPeerIdentityState.snapshot(peerID, mesh) } - val nickname = mesh?.getPeerNickname(peerID) ?: peerID.take(8) val listState = rememberScalingLazyListState(initialCenterItemIndex = 0) val palette = LocalBitchatPalette.current diff --git a/wear/src/main/java/com/bitchat/watch/ui/VerificationCodeScreen.kt b/wear/src/main/java/com/bitchat/watch/ui/VerificationCodeScreen.kt index 4644e9bd..09218ed7 100644 --- a/wear/src/main/java/com/bitchat/watch/ui/VerificationCodeScreen.kt +++ b/wear/src/main/java/com/bitchat/watch/ui/VerificationCodeScreen.kt @@ -36,7 +36,9 @@ import com.bitchat.watch.ui.theme.LocalBitchatPalette fun VerificationCodeScreen(peerID: String) { val mesh = WearMeshService.peek() val revision by WearPeerIdentityState.revision.collectAsState() - val identity = androidx.compose.runtime.remember(peerID, revision) { + // Keyed on the announced nickname too — see DmScreen. + val announcedNickname = mesh?.getPeerNickname(peerID) + val identity = androidx.compose.runtime.remember(peerID, revision, announcedNickname) { WearPeerIdentityState.snapshot(peerID, mesh) } val myFingerprint = WearPeerIdentityState.myFingerprint(mesh)