messenger-android

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

commit 535db0401c5e1bb1076870fe4f6a2f887b48590d
parent 2f85060ea131efbf6b9f4468430d4d99f04fc506
Author: t3sserakt <t3ss@posteo.de>
Date:   Wed,  6 May 2026 22:20:39 +0200

WIP: chat text survives until app re run

Diffstat:
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/MainActivity.kt | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 74 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 @@ -685,20 +685,86 @@ class MainActivity : AppCompatActivity() { chatMessage: ChatMessage ) { val current = currentSession() - if (current != null && + val isForeground = current != null && current.account.name.equals(session.account.name, ignoreCase = true) - ) { + + if (isForeground) { processChatMessage(chatContext, chatMessage) - } else { - Log.d( - TAG, - "background-session ${session.account.name}: kind=${chatMessage.kind} " + - "(deferred — will re-render on next switch)" - ) + return + } + + // Background session: route TEXT/FILE messages into the global chat + // viewmodel using the session's own service so they're visible when + // the user later switches to this session. Other event kinds will be + // re-rendered via loadChats() on switch. + 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) { + Log.d( + TAG, + "background-session ${session.account.name}: kind=${chatMessage.kind} " + + "(own echo, skip)" + ) + return + } + val key = stableChatKeyFor(session, chatContext) + if (key == null) { + Log.w( + TAG, + "background-session ${session.account.name}: kind=${chatMessage.kind} " + + "no stableChatKey — dropping" + ) + return + } + val vm = chatViewModels.getOrPut(key) { ChatViewModel(chatContext) } + chatMessage.type = ChatMessageType.OTHER + vm.addMessage(chatMessage) + Log.d( + TAG, + "background-session ${session.account.name}: kind=${chatMessage.kind} " + + "added to viewmodel '$key' (msgCount=${vm.messages.value?.size ?: 0})" + ) + } + else -> { + Log.d( + TAG, + "background-session ${session.account.name}: kind=${chatMessage.kind} " + + "(deferred — will re-render on next switch)" + ) + } } } /** + * Same as [stableChatKey] but resolves group/contact info via the given + * [session]'s service. Required when the message arrived on a background + * session whose native context pointer is in that session's address + * space — the foreground service can't dereference it. + */ + private fun stableChatKeyFor( + session: AccountSession, + chatContext: ChatContext + ): String? { + val gnunetChat = session.gnunetChat + runCatching { gnunetChat.getGroupFromContext(chatContext) } + .getOrNull() + ?.takeIf { it.name.isNotBlank() } + ?.let { return "group:${it.name}" } + + runCatching { gnunetChat.getContextContact(chatContext) } + .getOrNull() + ?.key + ?.takeIf { it.isNotBlank() } + ?.let { return "contact:$it" } + + return chatContext.userPointer?.takeIf { it.isNotBlank() } + } + + /** * Switches the foreground UI to [account]. Spawns a new session if one * doesn't exist. **Never disconnects** existing sessions — both the lobby * host and the joiner can stay live across the switch, which is what