From 8294887398978f98534b2f76be3064e130ed53c5 Mon Sep 17 00:00:00 2001 From: Taksh Date: Fri, 4 Sep 2026 22:11:09 +0530 Subject: [PATCH] Don't suggest blocked peers in @-mention autocomplete Blocking someone and still seeing them in the mention list felt wrong. Skip mesh peers whose fingerprint is blocked and geohash people whose Nostr pubkey is blocked, matching iOS ChatComposerCoordinator. --- .../com/bitchat/android/ui/ChatViewModel.kt | 5 ++ .../bitchat/android/ui/CommandProcessor.kt | 49 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index f40549b6..20e6544f 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -1675,6 +1675,11 @@ class ChatViewModel( geohashViewModel.blockUserInGeohash(targetNickname) } + /** True when this Nostr pubkey is blocked for geohash/location chats. */ + fun isGeohashPubkeyBlocked(pubkeyHex: String): Boolean { + return dataManager.isGeohashUserBlocked(pubkeyHex.lowercase()) + } + // MARK: - Navigation Management fun showAppInfo() { diff --git a/app/src/main/java/com/bitchat/android/ui/CommandProcessor.kt b/app/src/main/java/com/bitchat/android/ui/CommandProcessor.kt index 1cccfb19..ab0b33a0 100644 --- a/app/src/main/java/com/bitchat/android/ui/CommandProcessor.kt +++ b/app/src/main/java/com/bitchat/android/ui/CommandProcessor.kt @@ -562,14 +562,20 @@ class CommandProcessor( when (val selectedChannel = viewModel.selectedLocationChannel.value) { is com.bitchat.android.geohash.ChannelID.Mesh, null -> { - // Mesh channel: use Bluetooth mesh peer nicknames - val peerNicknames = meshService.getPeerNicknames() - peerNicknames.values.filter { it != peerNicknames[meshService.myPeerID] } + meshMentionCandidates( + peerNicknames = meshService.getPeerNicknames(), + myPeerID = meshService.myPeerID, + isPeerBlocked = privateChatManager::isPeerBlocked + ) } is com.bitchat.android.geohash.ChannelID.Location -> { // Location channel: use geohash participants with collision-resistant suffixes - val geohashPeople = viewModel.geohashPeople.value + val geohashPeople = excludeBlockedGeohashPeople( + people = viewModel.geohashPeople.value, + pubkeyOf = { it.id }, + isBlocked = viewModel::isGeohashPubkeyBlocked + ) val currentNickname = state.getNicknameValue() val duplicateNames = duplicateGeohashBaseNames(geohashPeople) @@ -593,9 +599,11 @@ class CommandProcessor( } } } else { - // Fallback to mesh peers if no viewModel available - val peerNicknames = meshService.getPeerNicknames() - peerNicknames.values.filter { it != peerNicknames[meshService.myPeerID] } + meshMentionCandidates( + peerNicknames = meshService.getPeerNicknames(), + myPeerID = meshService.myPeerID, + isPeerBlocked = privateChatManager::isPeerBlocked + ) } val filteredNicknames = filterMentionCandidates(peerCandidates, textAfterAt) @@ -719,3 +727,30 @@ internal fun filterMentionCandidates( .sortedWith(String.CASE_INSENSITIVE_ORDER) .toList() } + +/** + * Mesh @-mention candidates excluding self and blocked peers (iOS ChatComposerCoordinator parity). + */ +internal fun meshMentionCandidates( + peerNicknames: Map, + myPeerID: String, + isPeerBlocked: (String) -> Boolean +): List { + val myNickname = peerNicknames[myPeerID] + return peerNicknames + .filter { (peerID, nick) -> + nick != myNickname && !isPeerBlocked(peerID) + } + .values + .toList() +} + +/** + * Drop geohash people whose Nostr pubkey is blocked before building mention tokens. + */ +internal fun excludeBlockedGeohashPeople( + people: List, + pubkeyOf: (T) -> String, + isBlocked: (String) -> Boolean +): List = people.filterNot { isBlocked(pubkeyOf(it)) } +