messenger-android

Android graphical user interfaces for GNUnet Messenger
Log | Files | Refs | README | LICENSE

commit 7dfcf601a5803aaeeec6dff82a2e1f6e0687ca29
parent ccc537d422172539be6b8f29f904f5809c52574d
Author: t3sserakt <t3ss@posteo.de>
Date:   Wed, 20 May 2026 17:46:18 +0200

WIP: open bug fixing: group chat showing only on right side for all users

Diffstat:
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/MainActivity.kt | 42++++++++++++++++++++++++++++++++++++------
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/chat/ChatFragment.kt | 14++++++++++++--
2 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/MainActivity.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/MainActivity.kt @@ -325,7 +325,14 @@ class MainActivity : AppCompatActivity() { MessageKind.FILE -> { val senderKey = chatMessage.sender?.key ?: "" val profileKey = gnunetChat.getProfileKey(handle) - if (senderKey.isNotEmpty() && senderKey == profileKey) { + val ownEchoSkip = senderKey.isNotEmpty() && senderKey == profileKey + Log.d( + TAG, + "TEXT/FILE foreground: senderKey='${senderKey.take(16)}...' " + + "(len=${senderKey.length}) profileKey='${profileKey.take(16)}...' " + + "(len=${profileKey.length}) match=$ownEchoSkip text='${chatMessage.text}'" + ) + if (ownEchoSkip) { // Already added this message to the view when we sent it, // so skip the echo to avoid a duplicate. return @@ -707,17 +714,40 @@ class MainActivity : AppCompatActivity() { when (chatMessage.kind) { MessageKind.TEXT, MessageKind.FILE -> { val senderKey = chatMessage.sender?.key ?: "" - val ownKey = runCatching { - session.gnunetChat.getProfileKey(session.handle) - }.getOrDefault("") - if (senderKey.isNotEmpty() && senderKey == ownKey) { + + // Skip if the sender matches ANY of our local sessions' + // profile keys (not just this background session's). In + // multi-handle group chat, when account A (foreground) + // sends a message, the daemon broadcasts it to every + // handle subscribed to the group, including B's. B's + // background handler then sees a TEXT whose sender is A. + // A's foreground has already optimistically added that + // message to the shared "group:<name>" viewmodel via + // ChatFragment's sendButton; if we also add it here, the + // user sees the same text twice. Treat "sender is any of + // our active accounts" as an own-echo and skip. + // + // Edge case left open intentionally: an external peer + // sending to a group where multiple of our local + // accounts are both members would still duplicate + // (foreground handler adds + background handler adds). + // Rare enough that we accept it for now; can be tackled + // with viewmodel-level dedup if it ever matters. + val isOurOwnEcho = senderKey.isNotEmpty() && sessions.values.any { other -> + val k = runCatching { + other.gnunetChat.getProfileKey(other.handle) + }.getOrDefault("") + k.isNotEmpty() && k == senderKey + } + if (isOurOwnEcho) { Log.d( TAG, "background-session ${session.account.name}: kind=${chatMessage.kind} " + - "(own echo, skip)" + "(own echo from one of our sessions, skip)" ) return } + val key = stableChatKeyFor(session, chatContext) if (key == null) { Log.w( diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/chat/ChatFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/chat/ChatFragment.kt @@ -213,9 +213,19 @@ class ChatFragment : Fragment(R.layout.fragment_chat) { try { val profileKey = gnunetChat.getProfileKey(mainActivity.getChatHandle()) val history = gnunetChat.iterateContextMessages(chatContext) + Log.d( + "ChatFragment", + "iterate: profileKey='${profileKey.take(16)}...' " + + "(len=${profileKey.length}) historySize=${history.size}" + ) for (msg in history) { - val isOwn = msg.sender?.key?.isNotBlank() == true && - msg.sender.key == profileKey + val sKey = msg.sender?.key ?: "" + val isOwn = sKey.isNotBlank() && sKey == profileKey + Log.d( + "ChatFragment", + "iterate.msg: senderKey='${sKey.take(16)}...' " + + "(len=${sKey.length}) isOwn=$isOwn text='${msg.text}'" + ) val typed = msg.copy(type = if (isOwn) ChatMessageType.OWN else ChatMessageType.OTHER) chatViewModel.addMessage(typed) }