messenger-android

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

commit 41c195465d0ae6d54650075531f129e2d54b14ff
parent 6c1b09427fd9d977bbcea1291b6eb186621c0b94
Author: t3sserakt <t3sserakt@posteo.de>
Date:   Mon, 14 Apr 2025 11:17:59 +0200

Added avatar handling.

Diffstat:
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/model/ChatAccount.kt | 3++-
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/service/mock/GnunetChatMock.kt | 8++++----
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountAdapter.kt | 13++++++++++++-
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountDetailsFragment.kt | 9++++++++-
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountListFragment.kt | 2++
MGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/CreateAccountFragment.kt | 16+++++++++++++++-
AGNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/util/AvatarStorageUtil.kt | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp-debug.apk | 0
8 files changed, 104 insertions(+), 8 deletions(-)

diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/model/ChatAccount.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/model/ChatAccount.kt @@ -6,6 +6,7 @@ import kotlinx.parcelize.Parcelize @Parcelize data class ChatAccount( val pointer: Long, - val name: String + val name: String, + var key: String ) : Parcelable 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 @@ -20,9 +20,9 @@ class GnunetChatMock : GnunetChat { override fun iterateAccounts(handle: ChatHandle, callback: (ChatAccount) -> Unit) { val mockAccounts = listOf( - ChatAccount(1, "Alice"), - ChatAccount(2, "Bob"), - ChatAccount(3, "Charlie") + ChatAccount(1, "Alice",""), + ChatAccount(2, "Bob",""), + ChatAccount(3, "Charlie","") ) for (account in mockAccounts) { @@ -48,7 +48,7 @@ class GnunetChatMock : GnunetChat { } override fun getProfileKey(handle: ChatHandle): String { - return "somekey" + (1000..9999).random() + return "somekey1337" } override fun setContactBlock(isBlocked: Boolean) { diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountAdapter.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountAdapter.kt @@ -8,8 +8,10 @@ import android.widget.TextView import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import org.gnunet.gnunetmessenger.MainActivity import org.gnunet.gnunetmessenger.R import org.gnunet.gnunetmessenger.model.ChatAccount +import org.gnunet.gnunetmessenger.util.AvatarStorageUtil class AccountAdapter( private val onClick: (ChatAccount) -> Unit @@ -39,9 +41,18 @@ class AccountAdapter( private val nameView: TextView = view.findViewById(R.id.account_name) private val avatarView: ImageView = view.findViewById(R.id.account_avatar) + fun bind(account: ChatAccount) { nameView.text = account.name - avatarView.setImageResource(R.drawable.ic_account_circle) + val context = itemView.context + val avatarBitmap = AvatarStorageUtil.loadAvatar(context, account.key) + + if (avatarBitmap != null) { + avatarView.setImageBitmap(avatarBitmap) + } else { + avatarView.setImageResource(R.drawable.ic_account_circle) + } + itemView.setOnClickListener { onClick(account) } } } diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountDetailsFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/AccountDetailsFragment.kt @@ -11,6 +11,7 @@ import androidx.navigation.fragment.findNavController import org.gnunet.gnunetmessenger.MainActivity import org.gnunet.gnunetmessenger.R import org.gnunet.gnunetmessenger.databinding.FragmentAccountDetailsBinding +import org.gnunet.gnunetmessenger.util.AvatarStorageUtil class AccountDetailsFragment : Fragment() { @@ -33,7 +34,13 @@ class AccountDetailsFragment : Fragment() { val newName = binding.accountName.text.toString() gnunetChat.setProfileName(handle, newName) } - binding.accountAvatar.setImageResource(R.drawable.ic_account_circle) // Beispiel für Avatar + val avatar = AvatarStorageUtil.loadAvatar(requireContext(), gnunetChat.getProfileKey(handle)) + if (avatar != null) { + binding.accountAvatar.setImageBitmap(avatar) + } else { + binding.accountAvatar.setImageResource(R.drawable.ic_account_circle) + } + binding.btnListAttributes.setOnClickListener { val navController = activity.supportFragmentManager.findFragmentById(R.id.nav_host_fragment)?.findNavController() navController?.navigate(R.id.action_accountDetailsFragment_to_attributeListFragment) 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 @@ -38,6 +38,7 @@ class AccountListFragment : Fragment() { adapter = AccountAdapter { selectedAccount -> gnunetChat.connect(handle, selectedAccount) + selectedAccount.key = gnunetChat.getProfileKey(handle) val action = AccountListFragmentDirections.actionAccountListFragmentToAccountOverviewFragment(account = selectedAccount) findNavController().navigate(action) } @@ -51,6 +52,7 @@ class AccountListFragment : Fragment() { } (activity as MainActivity).getGnunetChatInstance().iterateAccounts((activity as MainActivity).getChatHandle()) { account -> + account.key = gnunetChat.getProfileKey(handle) list.add(account) } diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/CreateAccountFragment.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/ui/account/CreateAccountFragment.kt @@ -1,5 +1,6 @@ package org.gnunet.gnunetmessenger.ui.account +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -13,6 +14,7 @@ import org.gnunet.gnunetmessenger.model.ChatAccount import org.gnunet.gnunetmessenger.model.ChatHandle import org.gnunet.gnunetmessenger.service.GnunetChat import org.gnunet.gnunetmessenger.model.GnunetReturnValue +import org.gnunet.gnunetmessenger.util.AvatarStorageUtil class CreateAccountFragment : Fragment() { @@ -20,10 +22,16 @@ class CreateAccountFragment : Fragment() { private lateinit var mainActivity: MainActivity private lateinit var gnunetChat: GnunetChat private lateinit var handle: ChatHandle + private var selectedAvatarUri: Uri? = null // Request code for selecting avatar image private val avatarImageRequest = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> - // Handle the selected avatar image URI here (e.g., upload to server or local storage) + uri?.let { + selectedAvatarUri = it + binding.avatarPreview.setImageURI(it) + AvatarStorageUtil.saveAvatarFromUri(requireContext(), uri, gnunetChat.getProfileKey(handle)) + binding.avatarPreview.setImageURI(it) + } } override fun onCreateView( @@ -41,6 +49,12 @@ class CreateAccountFragment : Fragment() { avatarImageRequest.launch("image/*") // Start the image picker } + val avatar = AvatarStorageUtil.loadAvatar(requireContext(), gnunetChat.getProfileKey(handle)) + avatar?.let { + binding.avatarPreview.setImageBitmap(it) + } + + binding.confirmButton.setOnClickListener { val accountName = binding.accountNameInput.text.toString() if (accountName.isNotEmpty()) { diff --git a/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/util/AvatarStorageUtil.kt b/GNUnetMessenger/app/src/main/java/org/gnunet/gnunetmessenger/util/AvatarStorageUtil.kt @@ -0,0 +1,61 @@ +package org.gnunet.gnunetmessenger.util + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.net.Uri +import java.io.File +import java.io.FileOutputStream + +object AvatarStorageUtil { + + fun saveAvatarFromUri(context: Context, uri: Uri, accountKey: String): Boolean { + val filename = getAvatarFilename(accountKey) + val file = File(context.filesDir, filename) + + return try { + val inputStream = context.contentResolver.openInputStream(uri) + val outputStream = FileOutputStream(file) + + inputStream?.use { input -> + outputStream.use { output -> + input.copyTo(output) + } + } + true + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + fun saveAvatarBitmap(context: Context, bitmap: Bitmap, accountKey: String): Boolean { + val filename = getAvatarFilename(accountKey) + val file = File(context.filesDir, filename) + + return try { + FileOutputStream(file).use { output -> + bitmap.compress(Bitmap.CompressFormat.PNG, 100, output) + } + true + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + fun loadAvatar(context: Context, accountKey: String): Bitmap? { + val filename = getAvatarFilename(accountKey) + val file = File(context.filesDir, filename) + + return if (file.exists()) { + BitmapFactory.decodeFile(file.absolutePath) + } else { + null + } + } + + private fun getAvatarFilename(accountKey: String): String { + return "avatar_$accountKey.png" + } +} diff --git a/app-debug.apk b/app-debug.apk Binary files differ.