commit bd90c26ce7d9ef6b610738a2ca9d9c17a47ba2cb
parent 50ce6cb10ff4847a2f86bd6ff3664bebf6f2ca09
Author: t3sserakt <t3ss@posteo.de>
Date: Tue, 31 Mar 2026 19:34:32 +0200
WIP: fixing UI and lobby join
Diffstat:
6 files changed, 133 insertions(+), 18 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
@@ -41,7 +41,9 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.isActive
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import org.gnunet.gnunetmessenger.model.ChatAccount
import org.gnunet.gnunetmessenger.model.ChatContact
import org.gnunet.gnunetmessenger.model.ChatContext
@@ -314,11 +316,22 @@ class MainActivity : AppCompatActivity() {
return chatMenuViewModel
}
- private fun loadChats() {
+ fun loadChats() {
+ lifecycleScope.launch {
+ try {
+ loadChatsSuspend()
+ } catch (t: Throwable) {
+ Log.e(TAG, "loadChats failed", t)
+ }
+ }
+ }
+
+ private suspend fun loadChatsSuspend() = withContext(Dispatchers.IO) {
val summaries = mutableListOf<ChatSummary>()
val contacts = mutableListOf<ChatContact>()
- gnunetChat.iterateContacts(handle) { contact ->
+ val contactList = gnunetChat.listContacts(handle)
+ for (contact in contactList) {
val chatContext = gnunetChat.getContactContext(contact)
val uuid = gnunetChat.randomUUID()
contacts.add(contact)
@@ -333,11 +346,10 @@ class MainActivity : AppCompatActivity() {
contact = contact
)
)
- 0
}
- contactListViewModel.setContacts(contacts)
- gnunetChat.iterateGroups(handle) { group ->
+ val groupList = gnunetChat.listGroups(handle)
+ for (group in groupList) {
val chatContext = gnunetChat.getGroupContext(group)
val uuid = gnunetChat.randomUUID()
@@ -350,10 +362,23 @@ class MainActivity : AppCompatActivity() {
group = group
)
)
- 0
}
- chatOverviewViewModel.setChats(summaries)
+ withContext(Dispatchers.Main) {
+ contactListViewModel.setContacts(contacts)
+ chatOverviewViewModel.setChats(summaries)
+ }
+ Log.d(TAG, "loadChats: loaded ${contacts.size} contacts, ${groupList.size} groups")
+ }
+
+ fun clearChatState() {
+ chatOverviewViewModel.clearModel()
+ contactListViewModel.clearModel()
+ chatViewModels.values.forEach { it.clearModel() }
+ chatViewModels.clear()
+ chatMenuViewModels.clear()
+ chats.clear()
+ Log.d(TAG, "clearChatState: all chat state cleared")
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/GnunetChat.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/GnunetChat.kt
@@ -38,7 +38,7 @@ interface GnunetChat {
fun getAttributes(handle: ChatHandle, callback: (String, String) -> Unit)
fun lobbyOpen(handle: ChatHandle, callback: (String) -> Unit)
- fun lobbyJoin(handle: ChatHandle, uri: String)
+ suspend fun lobbyJoin(handle: ChatHandle, uri: String)
fun setGroupName(group: ChatGroup, name: String)
fun createGroup(handle: ChatHandle, topic: String): ChatGroup
@@ -60,6 +60,8 @@ interface GnunetChat {
fun iterateContacts(handle: ChatHandle, callback: (ChatContact) -> Int)
fun iterateGroups(handle: ChatHandle, callback: (ChatGroup) -> Int)
+ suspend fun listContacts(handle: ChatHandle): List<ChatContact>
+ suspend fun listGroups(handle: ChatHandle): List<ChatGroup>
fun getContactContext(chatContact: ChatContact): ChatContext
fun getGroupContext(chatGroup: ChatGroup): ChatContext
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
@@ -488,11 +488,9 @@ class GnunetChatBoundService(
}
}
- override fun lobbyJoin(handle: ChatHandle, uri: String) {
- runBlocking {
- withReadyRemote(handle) { remote, h ->
- remote.lobbyJoin(h, uri)
- }
+ override suspend fun lobbyJoin(handle: ChatHandle, uri: String) {
+ withReadyRemote(handle) { remote, h ->
+ withContext(Dispatchers.IO) { remote.lobbyJoin(h, uri) }
}
}
@@ -619,6 +617,68 @@ class GnunetChatBoundService(
}
}
+ override suspend fun listContacts(handle: ChatHandle): List<ChatContact> {
+ return withReadyRemote(handle) { remote, h ->
+ val result = mutableListOf<ChatContact>()
+ val done = CompletableDeferred<Unit>()
+
+ val bridge = object : IContactCallback.Stub() {
+ override fun onContact(contactDto: ChatContactDto) {
+ result.add(contactDto.toLocal())
+ }
+
+ override fun onDone() {
+ if (!done.isCompleted) {
+ done.complete(Unit)
+ }
+ }
+
+ override fun onError(code: Int, message: String?) {
+ if (!done.isCompleted) {
+ done.completeExceptionally(
+ IllegalStateException("iterateContacts failed: $code ${message ?: ""}".trim())
+ )
+ }
+ }
+ }
+
+ remote.iterateContacts(h, bridge)
+ done.await()
+ result.toList()
+ }
+ }
+
+ override suspend fun listGroups(handle: ChatHandle): List<ChatGroup> {
+ return withReadyRemote(handle) { remote, h ->
+ val result = mutableListOf<ChatGroup>()
+ val done = CompletableDeferred<Unit>()
+
+ val bridge = object : IGroupCallback.Stub() {
+ override fun onGroup(groupDto: ChatGroupDto) {
+ result.add(groupDto.toLocal())
+ }
+
+ override fun onDone() {
+ if (!done.isCompleted) {
+ done.complete(Unit)
+ }
+ }
+
+ override fun onError(code: Int, message: String?) {
+ if (!done.isCompleted) {
+ done.completeExceptionally(
+ IllegalStateException("iterateGroups failed: $code ${message ?: ""}".trim())
+ )
+ }
+ }
+ }
+
+ remote.iterateGroups(h, bridge)
+ done.await()
+ result.toList()
+ }
+ }
+
override fun iterateContacts(handle: ChatHandle, callback: (ChatContact) -> Int) {
val bridge = object : IContactCallback.Stub() {
override fun onContact(contactDto: ChatContactDto) {
diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/mock/GnunetChatMock.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/mock/GnunetChatMock.kt
@@ -167,7 +167,7 @@ class GnunetChatMock : GnunetChat {
callback("000G006K2TJNMD9VTCYRX7BRVV3HAEPS15E6NHDXKPJA1KAJJEG9AFF884")
}
- override fun lobbyJoin(handle: ChatHandle, uri: String) {
+ override suspend fun lobbyJoin(handle: ChatHandle, uri: String) {
println("join lobby")
}
@@ -346,6 +346,24 @@ class GnunetChatMock : GnunetChat {
)
}
+ override suspend fun listContacts(handle: ChatHandle): List<ChatContact> {
+ val contextAlice = ChatContext(ChatContextType.CONTACT, null, false, false)
+ val contextBob = ChatContext(ChatContextType.CONTACT, null, false, false)
+ return listOf(
+ ChatContact(contextAlice, name = "Alice"),
+ ChatContact(contextBob, name = "Bob")
+ )
+ }
+
+ override suspend fun listGroups(handle: ChatHandle): List<ChatGroup> {
+ val contextDev = ChatContext(ChatContextType.GROUP, null, true, false)
+ val contextFriends = ChatContext(ChatContextType.GROUP, null, true, false)
+ return listOf(
+ ChatGroup(contextDev, name = "Dev Team"),
+ ChatGroup(contextFriends, name = "Friends")
+ )
+ }
+
override fun getContactContext(chatContact: ChatContact): ChatContext {
return chatContact.chatContext
}
diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountListFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountListFragment.kt
@@ -80,12 +80,13 @@ class AccountListFragment : Fragment() {
viewLifecycleOwner.lifecycleScope.launch {
try {
- /*if (activity.currentAccount != null) {
+ if (activity.currentAccount != null) {
+ activity.clearChatState()
runCatching { gnunetChat.disconnect(handle) }
.onFailure {
Log.w(TAG, "disconnect before connect failed", it)
}
- }*/
+ }
gnunetChat.connect(handle, selectedAccount)
selectedAccount.key = gnunetChat.getProfileKey(handle)
diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/contact/LobbyJoinFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/contact/LobbyJoinFragment.kt
@@ -38,12 +38,14 @@ import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
+import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import org.gnunet.gnunetmessenger.R
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.common.InputImage
import org.gnunet.gnunetmessenger.MainActivity
import java.util.concurrent.Executors
+import kotlinx.coroutines.launch
class LobbyJoinFragment : Fragment() {
@@ -71,8 +73,15 @@ class LobbyJoinFragment : Fragment() {
val activity = activity as MainActivity
val gnunetChat = activity.getGnunetChatInstance()
val handle = activity.getChatHandle()
- gnunetChat.lobbyJoin(handle, lobbyId)
- findNavController().popBackStack()
+ viewLifecycleOwner.lifecycleScope.launch {
+ try {
+ gnunetChat.lobbyJoin(handle, lobbyId)
+ activity.loadChats()
+ findNavController().popBackStack()
+ } catch (t: Throwable) {
+ android.util.Log.e("LobbyJoinFragment", "lobbyJoin failed", t)
+ }
+ }
}
cancelButton.setOnClickListener {