From 4b81b7f97af5ec2198495bba600fe7aa4b9267cc Mon Sep 17 00:00:00 2001 From: lollerfirst <43107113+lollerfirst@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:41:02 +0200 Subject: [PATCH] fix: action message routing and duplicate local echo in geohash channels (#374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: send action messages to correct chat * fix(action): avoid double local echo for action messages in geohash channels When sending /hug or /slap in a location (geohash) channel, CommandProcessor was adding a local echo and then routing to NostrGeohashService, which also adds a local echo. This resulted in duplicate action messages on the sender’s screen. Change: detect when the selectedLocationChannel is a Location and, in that case, skip adding the local echo in CommandProcessor and only call the onSendMessage transport callback (NostrGeohashService will add the echo with proper metadata). Private and mesh (non-location) behavior is unchanged. --- .../java/com/bitchat/android/ui/ChatViewModel.kt | 16 ++++++++++++++-- .../com/bitchat/android/ui/CommandProcessor.kt | 9 ++++++++- 2 files changed, 22 insertions(+), 3 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 1b120b9b..74302cb9 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -266,9 +266,21 @@ class ChatViewModel( // Check for commands if (content.startsWith("/")) { + val selectedLocationForCommand = state.selectedLocationChannel.value commandProcessor.processCommand(content, meshService, meshService.myPeerID, { messageContent, mentions, channel -> - meshService.sendMessage(messageContent, mentions, channel) - }, this) + if (selectedLocationForCommand is com.bitchat.android.geohash.ChannelID.Location) { + // Route command-generated public messages via Nostr in geohash channels + nostrGeohashService.sendGeohashMessage( + messageContent, + selectedLocationForCommand.channel, + meshService.myPeerID, + state.getNicknameValue() + ) + } else { + // Default: route via mesh + meshService.sendMessage(messageContent, mentions, channel) + } + }) return } 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 4e426454..d36f67b4 100644 --- a/app/src/main/java/com/bitchat/android/ui/CommandProcessor.kt +++ b/app/src/main/java/com/bitchat/android/ui/CommandProcessor.kt @@ -291,7 +291,11 @@ class CommandProcessor( if (parts.size > 1) { val targetName = parts[1].removePrefix("@") val actionMessage = "* ${state.getNicknameValue() ?: "someone"} $verb $targetName $object_ *" - + + // If we're in a geohash location channel, don't add a local echo here. + // NostrGeohashService.sendGeohashMessage() will add the local echo with proper metadata. + val isInLocationChannel = state.selectedLocationChannel.value is com.bitchat.android.geohash.ChannelID.Location + // Send as regular message if (state.getSelectedPrivateChatPeerValue() != null) { val peerID = state.getSelectedPrivateChatPeerValue()!! @@ -304,6 +308,9 @@ class CommandProcessor( ) { content, peerIdParam, recipientNicknameParam, messageId -> sendPrivateMessageVia(meshService, content, peerIdParam, recipientNicknameParam, messageId) } + } else if (isInLocationChannel) { + // Let the transport layer add the echo; just send it out + onSendMessage(actionMessage, emptyList(), null) } else { val message = BitchatMessage( sender = state.getNicknameValue() ?: myPeerID,