Generate conversations & conferences avatars on worker thread & save result in cache directory

This commit is contained in:
Sylvain Berfini 2023-12-18 17:14:03 +01:00
parent 03ee116ed4
commit 5ee5982e3c
7 changed files with 90 additions and 45 deletions

View file

@ -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(

View file

@ -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

View file

@ -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)

View file

@ -86,17 +86,6 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) : Abstrac
}
}
@WorkerThread
fun setPicturesFromFriends(friends: List<Friend>) {
if (friends.isNotEmpty()) {
val list = arrayListOf<String>()
for (friend in friends) {
list.add(getAvatarUri(friend).toString())
}
images.postValue(list)
}
}
@WorkerThread
private fun getAvatarUri(friend: Friend): Uri? {
val picturePath = friend.photo

View file

@ -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<String>()
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<String>): 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<String>): Bitmap {
val drawables = images.mapNotNull {

View file

@ -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<String>()
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<Friend>()
for (participant in conferenceInfo.participantInfos) {
val friend = coreContext.contactsManager.findContactByAddress(
participant.address
)
if (friend != null) {
list.add(friend)
}
}
avatarModel.setPicturesFromFriends(list)
return avatarModel
}
}

View file

@ -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<String>()
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()