From 5ee5982e3cb37dd28c9d705d052ce57c368d484e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 18 Dec 2023 17:14:03 +0100 Subject: [PATCH] Generate conversations & conferences avatars on worker thread & save result in cache directory --- .../ui/main/chat/model/ConversationModel.kt | 4 +- .../viewmodel/ConversationInfoViewModel.kt | 4 +- .../chat/viewmodel/ConversationViewModel.kt | 4 +- .../main/contacts/model/ContactAvatarModel.kt | 11 ----- .../java/org/linphone/utils/ImageUtils.kt | 49 +++++++++++++++++++ .../java/org/linphone/utils/LinphoneUtils.kt | 39 ++++++++++----- .../java/org/linphone/utils/ShortcutUtils.kt | 24 ++------- 7 files changed, 90 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt b/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt index 08449d6af..5e008575b 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt @@ -35,6 +35,7 @@ import org.linphone.core.Friend import org.linphone.core.tools.Log import org.linphone.ui.main.contacts.model.ContactAvatarModel import org.linphone.utils.AppUtils +import org.linphone.utils.ImageUtils import org.linphone.utils.LinphoneUtils import org.linphone.utils.ShortcutUtils import org.linphone.utils.TimestampUtils @@ -328,9 +329,10 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) { if (isGroup) { val fakeFriend = coreContext.core.createFriend() + fakeFriend.name = chatRoom.subject + fakeFriend.photo = ImageUtils.generateBitmapForChatRoom(chatRoom) val model = ContactAvatarModel(fakeFriend) model.defaultToConversationIcon.postValue(true) - model.setPicturesFromFriends(friends) avatarModel.postValue(model) } else { avatarModel.postValue( diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt index b0aca27e6..7cd438d7a 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt @@ -37,6 +37,7 @@ import org.linphone.ui.main.chat.model.ParticipantModel import org.linphone.ui.main.contacts.model.ContactAvatarModel import org.linphone.utils.AppUtils import org.linphone.utils.Event +import org.linphone.utils.ImageUtils import org.linphone.utils.LinphoneUtils class ConversationInfoViewModel @UiThread constructor() : ViewModel() { @@ -539,9 +540,10 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() { val avatar = if (groupChatRoom) { val fakeFriend = coreContext.core.createFriend() + fakeFriend.name = chatRoom.subject + fakeFriend.photo = ImageUtils.generateBitmapForChatRoom(chatRoom) val model = ContactAvatarModel(fakeFriend) model.defaultToConversationIcon.postValue(true) - model.setPicturesFromFriends(friends) model } else { participantsList.first().avatarModel diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt index 31236f28f..2ac1c4010 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt @@ -39,6 +39,7 @@ import org.linphone.ui.main.chat.model.MessageModel import org.linphone.ui.main.contacts.model.ContactAvatarModel import org.linphone.utils.AppUtils import org.linphone.utils.Event +import org.linphone.utils.ImageUtils import org.linphone.utils.LinphoneUtils class ConversationViewModel @UiThread constructor() : ViewModel() { @@ -436,8 +437,9 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { val avatar = if (group) { val fakeFriend = coreContext.core.createFriend() + fakeFriend.name = chatRoom.subject + fakeFriend.photo = ImageUtils.generateBitmapForChatRoom(chatRoom) val model = ContactAvatarModel(fakeFriend) - model.setPicturesFromFriends(friends) model } else { coreContext.contactsManager.getContactAvatarModelForAddress(address) diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt index 3ecdb06cc..014e2f72d 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt @@ -86,17 +86,6 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) : Abstrac } } - @WorkerThread - fun setPicturesFromFriends(friends: List) { - if (friends.isNotEmpty()) { - val list = arrayListOf() - for (friend in friends) { - list.add(getAvatarUri(friend).toString()) - } - images.postValue(list) - } - } - @WorkerThread private fun getAvatarUri(friend: Friend): Uri? { val picturePath = friend.photo diff --git a/app/src/main/java/org/linphone/utils/ImageUtils.kt b/app/src/main/java/org/linphone/utils/ImageUtils.kt index 45b499e6c..e6118691e 100644 --- a/app/src/main/java/org/linphone/utils/ImageUtils.kt +++ b/app/src/main/java/org/linphone/utils/ImageUtils.kt @@ -30,7 +30,12 @@ import android.net.Uri import androidx.annotation.AnyThread import androidx.annotation.WorkerThread import java.io.FileNotFoundException +import java.io.FileOutputStream +import java.io.OutputStream +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.R import org.linphone.contacts.AvatarGenerator +import org.linphone.core.ChatRoom import org.linphone.core.tools.Log class ImageUtils { @@ -86,6 +91,50 @@ class ImageUtils { return null } + @WorkerThread + fun generateBitmapForChatRoom(chatRoom: ChatRoom): String { + val id = LinphoneUtils.getChatRoomId(chatRoom) + val hash = id.hashCode().toString() + val file = FileUtils.getFileStorageCacheDir("$hash.jpg", overrideExisting = true) + if (file.exists()) { + Log.i("$TAG Bitmap for conversation [$id]($hash) exists, using it") + return FileUtils.getProperFilePath(file.absolutePath) + } + + val list = arrayListOf() + for (participant in chatRoom.participants) { + val contact = + coreContext.contactsManager.findContactByAddress(participant.address) + val picture = contact?.photo + if (picture != null) { + list.add(picture) + } + } + if (list.isNotEmpty()) { + Log.i( + "$TAG Found at [${list.size}] participant(s) with a picture for conversation [$id]($hash), creating avatar" + ) + val bitmap = generateBitmapFromList(list) + val outputStream: OutputStream = FileOutputStream(file) + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream) + outputStream.close() + val generatedPath = FileUtils.getProperFilePath(file.absolutePath) + Log.i("$TAG Avatar for conversation [$id]($hash) was generated at [$generatedPath]") + return generatedPath + } else { + Log.w( + "$TAG Not once picture found for conversation [$id], couldn't generate avatar" + ) + } + return "" + } + + @WorkerThread + fun generateBitmapFromList(list: ArrayList): Bitmap { + val size = AppUtils.getDimension(R.dimen.avatar_in_call_size).toInt() + return getBitmapFromMultipleAvatars(coreContext.context, size, list) + } + @AnyThread fun getBitmapFromMultipleAvatars(context: Context, size: Int, images: List): Bitmap { val drawables = images.mapNotNull { diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt index 510d2f8d8..2bae91f3e 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt @@ -19,10 +19,13 @@ */ package org.linphone.utils +import android.graphics.Bitmap import androidx.annotation.AnyThread import androidx.annotation.DrawableRes import androidx.annotation.IntegerRes import androidx.annotation.WorkerThread +import java.io.FileOutputStream +import java.io.OutputStream import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Date @@ -39,7 +42,6 @@ import org.linphone.core.ChatMessage import org.linphone.core.ChatRoom import org.linphone.core.ConferenceInfo import org.linphone.core.Core -import org.linphone.core.Friend import org.linphone.core.tools.Log import org.linphone.ui.main.contacts.model.ContactAvatarModel @@ -342,21 +344,34 @@ class LinphoneUtils { fakeFriend.address = conferenceInfo.uri fakeFriend.name = conferenceInfo.subject + val hash = conferenceInfo.uri?.asStringUriOnly().hashCode().toString() + val file = FileUtils.getFileStorageCacheDir("$hash.jpg", overrideExisting = true) + if (!file.exists()) { + val list = arrayListOf() + for (participant in conferenceInfo.participantInfos) { + val friend = coreContext.contactsManager.findContactByAddress( + participant.address + ) + if (friend != null) { + val picture = friend.photo + if (picture != null) { + list.add(picture) + } + } + } + if (list.isNotEmpty()) { + val bitmap = ImageUtils.generateBitmapFromList(list) + val outputStream: OutputStream = FileOutputStream(file) + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream) + outputStream.close() + } + } + fakeFriend.photo = FileUtils.getProperFilePath(file.absolutePath) + val avatarModel = ContactAvatarModel(fakeFriend) avatarModel.defaultToConferenceIcon.postValue(true) avatarModel.skipInitials.postValue(true) - val list = arrayListOf() - for (participant in conferenceInfo.participantInfos) { - val friend = coreContext.contactsManager.findContactByAddress( - participant.address - ) - if (friend != null) { - list.add(friend) - } - } - - avatarModel.setPicturesFromFriends(list) return avatarModel } } diff --git a/app/src/main/java/org/linphone/utils/ShortcutUtils.kt b/app/src/main/java/org/linphone/utils/ShortcutUtils.kt index 559761925..88e822a6b 100644 --- a/app/src/main/java/org/linphone/utils/ShortcutUtils.kt +++ b/app/src/main/java/org/linphone/utils/ShortcutUtils.kt @@ -22,6 +22,7 @@ package org.linphone.utils import android.content.Context import android.content.Intent import android.content.pm.ShortcutInfo +import android.graphics.BitmapFactory import android.os.Bundle import androidx.annotation.WorkerThread import androidx.collection.ArraySet @@ -31,7 +32,6 @@ import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat import org.linphone.LinphoneApplication.Companion.coreContext -import org.linphone.R import org.linphone.contacts.AvatarGenerator import org.linphone.contacts.getPerson import org.linphone.core.ChatRoom @@ -77,6 +77,7 @@ class ShortcutUtils { } if (isShortcutToChatRoomAlreadyCreated(context, chatRoom)) { + count += 1 continue } @@ -145,25 +146,10 @@ class ShortcutUtils { ).buildIcon() } else { subject = chatRoom.subject.orEmpty() - val list = arrayListOf() - for (participant in chatRoom.participants) { - val contact = - coreContext.contactsManager.findContactByAddress(participant.address) - if (contact != null) { - personsList.add(contact.getPerson()) - - val picture = contact.photo - if (picture != null) { - list.add(picture) - } - } - } - AvatarGenerator(context).setInitials(subject).buildIcon() - if (list.isNotEmpty()) { - val iconSize = AppUtils.getDimension(R.dimen.avatar_list_cell_size).toInt() - + val picture = ImageUtils.generateBitmapForChatRoom(chatRoom) + if (picture.isNotEmpty()) { IconCompat.createWithAdaptiveBitmap( - ImageUtils.getBitmapFromMultipleAvatars(context, iconSize, list) + BitmapFactory.decodeFile(picture) ) } else { AvatarGenerator(context).setInitials(subject).buildIcon()