messenger-android

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

commit 266e317f8bb4add7f99a8aa85cde802101159df7
parent 9845584db41e9d0a89bfd9e4be2c28ab74deb4ec
Author: t3sserakt <t3ss@posteo.de>
Date:   Tue,  9 Dec 2025 16:45:06 +0100

method implementation

Diffstat:
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/boundimpl/GnunetChatBoundService.kt | 551+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
1 file changed, 357 insertions(+), 194 deletions(-)

diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/boundimpl/GnunetChatBoundService.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/boundimpl/GnunetChatBoundService.kt @@ -14,26 +14,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout -import org.gnunet.gnunetmessenger.ipc.ChatAccountDto -import org.gnunet.gnunetmessenger.ipc.ChatContextDto -import org.gnunet.gnunetmessenger.ipc.ChatMessageDto -import org.gnunet.gnunetmessenger.ipc.IAccountCallback -import org.gnunet.gnunetmessenger.ipc.IChatCallback -import org.gnunet.gnunetmessenger.ipc.IGnunetChat -import org.gnunet.gnunetmessenger.model.ChatAccount -import org.gnunet.gnunetmessenger.model.ChatContact -import org.gnunet.gnunetmessenger.model.ChatContext -import org.gnunet.gnunetmessenger.model.ChatContextType -import org.gnunet.gnunetmessenger.model.ChatGroup -import org.gnunet.gnunetmessenger.model.ChatHandle -import org.gnunet.gnunetmessenger.model.ChatMessage -import org.gnunet.gnunetmessenger.model.ChatMessageType -import org.gnunet.gnunetmessenger.model.ChatUri -import org.gnunet.gnunetmessenger.model.GnunetReturnValue -import org.gnunet.gnunetmessenger.model.MessageKind -import org.gnunet.gnunetmessenger.model.MessengerApp +import org.gnunet.gnunetmessenger.ipc.* +import org.gnunet.gnunetmessenger.model.* import org.gnunet.gnunetmessenger.service.GnunetChat import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicReference @@ -44,7 +29,6 @@ class GnunetChatBoundService( private var uuidCounter: Long = 0 - // --- Scopes --- private val mainScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) @@ -436,305 +420,485 @@ class GnunetChatBoundService( } } - - companion object { - private const val TAG = "GnunetChatBoundService" - private const val ACTION_BIND_GNUNET_CHAT = - "org.gnunet.gnunetmessenger.ipc.BIND_GNUNET_CHAT" - private const val SERVER_PACKAGE = "org.gnu.gnunet" - private const val DEFAULT_APP_NAME = "Default" - } - - // ---------------- DTO -> App Mapper ---------------- - - private fun ChatAccount.toDto(): ChatAccountDto = - ChatAccountDto().apply { - key = this@toDto.key - name = this@toDto.name - } - - private fun ChatAccountDto.toLocal(): ChatAccount { - return ChatAccount( - key = this.key ?: "", - name = this.name ?: "", - pointer = 0 // falls du hier etwas Eigenes brauchst - ) - } - - private fun ChatContextDto.toLocal(): ChatContext { - val type = ChatContextType.fromCode(chatContextType) - return ChatContext( - chatContextType = type, - userPointer = userPointer?.takeIf { it.isNotEmpty() }, - isGroup = isGroup, - isPlatform = isPlatform - ) - } - - private fun ChatMessageDto.toLocal(ctx: ChatContext): ChatMessage { - val kindEnum = MessageKind.fromCode(kind) - val typeEnum = if (type < 0) null else ChatMessageType.fromCode(type) - return ChatMessage( - chatContext = ctx, - text = text ?: "", - timestamp = timestamp, - sender = null, // senderKey kannst du später auflösen - kind = kindEnum, - type = typeEnum - ) - } - + // --- Remote Call Implementations --- override fun getProfileKey(handle: ChatHandle): String { - return "somekey1337" + return runBlocking { + withReadyRemote(handle) { remote, h -> + remote.getProfileKey(h) + } + } } override fun isContactBlocked(contact: ChatContact): Boolean { - return true + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.isContactBlocked(contact.toDto()) + } + } } override fun setContactBlocked(contact: ChatContact, isBlocked: Boolean) { - println("isblocked:" + isBlocked) + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.setContactBlocked(contact.toDto(), isBlocked) + } + } } override fun setAttribute(handle: ChatHandle, key: String, value: String) { - println("setting Attribute withj key: ${key} and value ${value}") + runBlocking { + withReadyRemote(handle) { remote, h -> + remote.setAttribute(h, key, value) + } + } } override fun getAttributes(handle: ChatHandle, callback: (String, String) -> Unit) { - val mockAttributes = listOf( - "nickname" to "Alice", - "location" to "Berlin", - "status" to "Online" - ) + val bridge = object : IAttributeCallback.Stub() { + override fun onAttribute(key: String, value: String) { + mainScope.launch { callback(key, value) } + } + override fun onDone() { Log.d(TAG, "getAttributes: done") } + override fun onError(code: Int, message: String?) { + Log.e(TAG, "getAttributes: error $code $message") + } + } - for ((key, value) in mockAttributes) { - callback(key, value) + val remote = remoteRef.get() + if (remote != null) { + ioScope.launch { + try { + remote.getAttributes(handle.pointer, bridge) + } catch (e: RemoteException) { + Log.e(TAG, "getAttributes failed", e) + } + } + } else { + bind() + synchronized(pendingAfterHandle) { + pendingAfterHandle += { r, real -> + runCatching { r.getAttributes(real, bridge) } + .onFailure { Log.e(TAG, "getAttributes (deferred) failed", it) } + } + } } } override fun lobbyOpen(handle: ChatHandle, callback: (String) -> Unit) { - callback("000G006K2TJNMD9VTCYRX7BRVV3HAEPS15E6NHDXKPJA1KAJJEG9AFF884") + val bridge = object : ILobbyCallback.Stub() { + override fun onLobbyUri(uri: String) { + mainScope.launch { callback(uri) } + } + override fun onError(code: Int, message: String?) { + Log.e(TAG, "lobbyOpen: error $code $message") + } + } + + val remote = remoteRef.get() + if (remote != null) { + ioScope.launch { + try { + remote.lobbyOpen(handle.pointer, bridge) + } catch (e: RemoteException) { + Log.e(TAG, "lobbyOpen failed", e) + } + } + } else { + bind() + synchronized(pendingAfterHandle) { + pendingAfterHandle += { r, real -> + runCatching { r.lobbyOpen(real, bridge) } + .onFailure { Log.e(TAG, "lobbyOpen (deferred) failed", it) } + } + } + } } - override fun lobbyJoin( - handle: ChatHandle, - uri: String - ) { - println("join lobby") + override fun lobbyJoin(handle: ChatHandle, uri: String) { + runBlocking { + withReadyRemote(handle) { remote, h -> + remote.lobbyJoin(h, uri) + } + } } override fun setGroupName(group: ChatGroup, name: String) { - group.name = name + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.setGroupName(group.toDto(), name) + } + } } override fun createGroup(handle: ChatHandle, topic: String): ChatGroup { - return ChatGroup(ChatContext(ChatContextType.GROUP, null, - true, false), topic) + return runBlocking { + val groupDto = withReadyRemote(handle) { remote, h -> + remote.createGroup(h, topic) + } + groupDto.toLocal() + } } override fun parseUri(uri: String): ChatUri { - TODO("Not yet implemented") + return runBlocking { + val uriDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.parseUri(uri) + } + uriDto.toLocal() + } } override fun destroyUri(uri: ChatUri) { - TODO("Not yet implemented") + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.destroyUri(uri.toDto()) + } + } } override fun inviteContactToGroup(group: ChatGroup, contact: ChatContact) { - println("contact ${contact.name} invited") + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.inviteContactToGroup(group.toDto(), contact.toDto()) + } + } } override fun getUserPointerForContext(context: ChatContext): String? { - return context.userPointer + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getUserPointerForContext(context.toDto()) + } + } } override fun setUserPointerForContext(context: ChatContext, userPointer: String) { - context.userPointer = userPointer + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.setUserPointerForContext(context.toDto(), userPointer) + } + } } override fun getSenderFromMessage(message: ChatMessage): ChatContact { - return ChatContact(ChatContext(ChatContextType.CONTACT, null, true, false), message.sender?.name ?: "") + return runBlocking { + val contactDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getSenderFromMessage(message.toDto()) + } + contactDto.toLocal() + } } override fun getGroupFromContext(context: ChatContext): ChatGroup? { - if ("3" == context.userPointer){ - val contextDev = ChatContext(ChatContextType.GROUP, null, true, false) - return ChatGroup(contextDev, name = "Dev Team") + return runBlocking { + val groupDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getGroupFromContext(context.toDto()) + } + groupDto.toLocal() } - val contextDev = ChatContext(ChatContextType.GROUP, null, true, false) - return ChatGroup(contextDev, name = "GNUnet Team") } override fun getMessageForGroupContact(group: ChatGroup, contact: ChatContact): ChatMessage { - TODO("Not yet implemented") + return runBlocking { + val messageDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getMessageForGroupContact(group.toDto(), contact.toDto()) + } + messageDto.toLocal(ChatContext(ChatContextType.UNKNOWN, null, false, false)) + } } override fun getMessageKind(message: ChatMessage): MessageKind { - TODO("Not yet implemented") + return runBlocking { + val kind = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getMessageKind(message.toDto()) + } + MessageKind.fromCode(kind) + } } override fun isMessageRecent(message: ChatMessage): GnunetReturnValue { - TODO("Not yet implemented") + return runBlocking { + val result = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.isMessageRecent(message.toDto()) + } + result.toGnunetReturn() + } } override fun getMessageTimestamp(message: ChatMessage): Long { - TODO("Not yet implemented") + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getMessageTimestamp(message.toDto()) + } + } } - override fun setMessageForGroupContact( - group: ChatGroup, - contact: ChatContact, - message: ChatMessage - ) { - TODO("Not yet implemented") + override fun setMessageForGroupContact(group: ChatGroup, contact: ChatContact, message: ChatMessage) { + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.setMessageForGroupContact(group.toDto(), contact.toDto(), message.toDto()) + } + } } override fun iterateContacts(handle: ChatHandle, callback: (ChatContact) -> Int) { - val contextAlice = ChatContext(ChatContextType.CONTACT, null, false, false) - val contextBob = ChatContext(ChatContextType.CONTACT, null, false, false) - val contacts = listOf( + val bridge = object : IContactCallback.Stub() { + override fun onContact(contactDto: ChatContactDto) { + val contact = contactDto.toLocal() + mainScope.launch { callback(contact) } + } + override fun onDone() { Log.d(TAG, "iterateContacts: done") } + override fun onError(code: Int, message: String?) { + Log.e(TAG, "iterateContacts: error $code $message") + } + } - ChatContact(contextAlice, name = "Alice"), - ChatContact(contextBob, name = "Bob") - ) - for (contact in contacts) { - callback(contact) + val remote = remoteRef.get() + if (remote != null) { + ioScope.launch { + try { + remote.iterateContacts(handle.pointer, bridge) + } catch (e: RemoteException) { + Log.e(TAG, "iterateContacts failed", e) + } + } + } else { + bind() + synchronized(pendingAfterHandle) { + pendingAfterHandle += { r, real -> + runCatching { r.iterateContacts(real, bridge) } + .onFailure { Log.e(TAG, "iterateContacts (deferred) failed", it) } + } + } } } override fun iterateGroups(handle: ChatHandle, callback: (ChatGroup) -> Int) { - println("iterate groups") - val contextDev = ChatContext(ChatContextType.GROUP, null, true, false) - val contextFriends = ChatContext(ChatContextType.GROUP, null, true, false) - val groups = listOf( - ChatGroup(contextDev, name = "Dev Team"), - ChatGroup(contextFriends, name = "Friends") - ) - for (group in groups) { - callback(group) + val bridge = object : IGroupCallback.Stub() { + override fun onGroup(groupDto: ChatGroupDto) { + val group = groupDto.toLocal() + mainScope.launch { callback(group) } + } + override fun onDone() { Log.d(TAG, "iterateGroups: done") } + override fun onError(code: Int, message: String?) { + Log.e(TAG, "iterateGroups: error $code $message") + } } - messageCallback(ChatContext(ChatContextType.CONTACT, null, true, false), - ChatMessage(ChatContext(ChatContextType.CONTACT,null, true, false),"",0, - ChatContact(ChatContext(ChatContextType.CONTACT, null, true, false), "Mallory"),MessageKind.JOIN, null) - ) - - messageCallback(ChatContext(ChatContextType.CONTACT,"5", true, false), - ChatMessage(ChatContext(ChatContextType.CONTACT,null, true, false),"Hi, I am Mallory!",0, - ChatContact(ChatContext(ChatContextType.CONTACT, "6", true, false), "Mallory"),MessageKind.TEXT, null) - ) - - messageCallback(ChatContext(ChatContextType.GROUP,"3", true, false), - ChatMessage(ChatContext(ChatContextType.GROUP,null, true, false),"",0, - ChatContact(ChatContext(ChatContextType.CONTACT, null, true, false), "Flo"),MessageKind.JOIN, null) - ) - - messageCallback(ChatContext(ChatContextType.GROUP,"3", true, false), - ChatMessage(ChatContext(ChatContextType.GROUP,null, true, false),"Hi, I am Flo!",0, - ChatContact(ChatContext(ChatContextType.CONTACT, "7", true, false), "Flo"),MessageKind.TEXT, null) - ) - - messageCallback(ChatContext(ChatContextType.GROUP,"3", true, false), - ChatMessage(ChatContext(ChatContextType.GROUP,null, true, false),"",0, - ChatContact(ChatContext(ChatContextType.CONTACT, "1", true, false), "Alice"),MessageKind.JOIN, null) - ) - - messageCallback(ChatContext(ChatContextType.GROUP,"3", true, false), - ChatMessage(ChatContext(ChatContextType.GROUP,null, true, false),"Hi, I am Alice!",0, - ChatContact(ChatContext(ChatContextType.CONTACT, "1", true, false), "Alice"),MessageKind.TEXT, null) - ) - + val remote = remoteRef.get() + if (remote != null) { + ioScope.launch { + try { + remote.iterateGroups(handle.pointer, bridge) + } catch (e: RemoteException) { + Log.e(TAG, "iterateGroups failed", e) + } + } + } else { + bind() + synchronized(pendingAfterHandle) { + pendingAfterHandle += { r, real -> + runCatching { r.iterateGroups(real, bridge) } + .onFailure { Log.e(TAG, "iterateGroups (deferred) failed", it) } + } + } + } } override fun getContactContext(chatContact: ChatContact): ChatContext { - return chatContact.chatContext + return runBlocking { + val contextDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getContactContext(chatContact.toDto()) + } + contextDto.toLocal() + } } override fun getGroupContext(chatGroup: ChatGroup): ChatContext { - return chatGroup.chatContext + return runBlocking { + val contextDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getGroupContext(chatGroup.toDto()) + } + contextDto.toLocal() + } } override fun getContactUserPointer(chatContact: ChatContact): String { - TODO("Not yet implemented") + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getContactUserPointer(chatContact.toDto()) + } + } } override fun setContactUserPointer(chatContact: ChatContact, userPointer: String) { - TODO("Not yet implemented") + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.setContactUserPointer(chatContact.toDto(), userPointer) + } + } } override fun getGroupUserPointer(chatGroup: ChatGroup): String { - TODO("Not yet implemented") + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getGroupUserPointer(chatGroup.toDto()) + } + } } override fun setGroupUserPointer(chatGroup: ChatGroup, userPointer: String) { - println("set group name") + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.setGroupUserPointer(chatGroup.toDto(), userPointer) + } + } } override fun sendText(chatContext: ChatContext, text: String) { - println("send text: $text") + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.sendText(chatContext.toDto(), text) + } + } } override fun getContactKey(chatContact: ChatContact): String { - return "otherkey42" + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getContactKey(chatContact.toDto()) + } + } } override fun getContextContact(context: ChatContext): ChatContact { - println("get contact for context") - return ChatContact(context,"test") + return runBlocking { + val contactDto = withReadyRemote(ChatHandle(0)) { remote, h -> + remote.getContextContact(context.toDto()) + } + contactDto.toLocal() + } } override fun deleteContact(chatContact: ChatContact) { - println("delete contact") + runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.deleteContact(chatContact.toDto()) + } + } } override fun isGroup(context: ChatContext): Boolean { - return context.isGroup + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.isGroup(context.toDto()) + } + } } override fun isPlatform(context: ChatContext): Boolean { - return context.isPlatform + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.isPlatform(context.toDto()) + } + } } - override fun iterateGroupContacts( - chatGroup: ChatGroup, - callback: (ChatGroup, ChatContact) -> Int - ) { - val contextCharlie = ChatContext(ChatContextType.CONTACT, null, true, false) - val contacts = listOf( + override fun iterateGroupContacts(chatGroup: ChatGroup, callback: (ChatGroup, ChatContact) -> Int) { + val bridge = object : IGroupContactCallback.Stub() { + override fun onGroupContact(groupDto: ChatGroupDto, contactDto: ChatContactDto) { + val group = groupDto.toLocal() + val contact = contactDto.toLocal() + mainScope.launch { callback(group, contact) } + } + override fun onDone() { Log.d(TAG, "iterateGroupContacts: done") } + override fun onError(code: Int, message: String?) { + Log.e(TAG, "iterateGroupContacts: error $code $message") + } + } - ChatContact(contextCharlie, name = "Charlie") - ) - for (contact in contacts) { - callback(chatGroup, contact) + val remote = remoteRef.get() + if (remote != null) { + ioScope.launch { + try { + remote.iterateGroupContacts(chatGroup.toDto(), bridge) + } catch (e: RemoteException) { + Log.e(TAG, "iterateGroupContacts failed", e) + } + } + } else { + bind() + synchronized(pendingAfterHandle) { + pendingAfterHandle += { r, real -> + runCatching { r.iterateGroupContacts(chatGroup.toDto(), bridge) } + .onFailure { Log.e(TAG, "iterateGroupContacts (deferred) failed", it) } + } + } } } override fun randomUUID(): String { - return uuidCounter++.toString() + return runBlocking { + withReadyRemote(ChatHandle(0)) { remote, h -> + remote.randomUUID() + } + } } - override fun getContactAttributes( - contact: ChatContact, - callback: (String, String) -> Unit - ) { - val mockAttributes = listOf( - "nickname" to "Alice", - "location" to "Berlin", - "status" to "Online" - ) + override fun getContactAttributes(contact: ChatContact, callback: (String, String) -> Unit) { + val bridge = object : IAttributeCallback.Stub() { + override fun onAttribute(key: String, value: String) { + mainScope.launch { callback(key, value) } + } + override fun onDone() { Log.d(TAG, "getContactAttributes: done") } + override fun onError(code: Int, message: String?) { + Log.e(TAG, "getContactAttributes: error $code $message") + } + } - for ((key, value) in mockAttributes) { - callback(key, value) + val remote = remoteRef.get() + if (remote != null) { + ioScope.launch { + try { + remote.getContactAttributes(contact.toDto(), bridge) + } catch (e: RemoteException) { + Log.e(TAG, "getContactAttributes failed", e) + } + } + } else { + bind() + synchronized(pendingAfterHandle) { + pendingAfterHandle += { r, real -> + runCatching { r.getContactAttributes(contact.toDto(), bridge) } + .onFailure { Log.e(TAG, "getContactAttributes (deferred) failed", it) } + } + } } } override fun shareAttributes(handle: ChatHandle, contact: ChatContact, key: String) { - println("share ${key} for contact ${contact.name}") + runBlocking { + withReadyRemote(handle) { remote, h -> + remote.shareAttributes(h, contact.toDto(), key) + } + } } override fun unshareAttributes(handle: ChatHandle, contact: ChatContact, key: String) { - println("unshare ${key} for contact ${contact.name}") + runBlocking { + withReadyRemote(handle) { remote, h -> + remote.unshareAttributes(h, contact.toDto(), key) + } + } + } + + companion object { + private const val TAG = "GnunetChatBoundService" + private const val ACTION_BIND_GNUNET_CHAT = + "org.gnunet.gnunetmessenger.ipc.BIND_GNUNET_CHAT" + private const val SERVER_PACKAGE = "org.gnu.gnunet" + private const val DEFAULT_APP_NAME = "Default" } -} -\ No newline at end of file +}