mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Updated ImageUtils.getBitmapFromMultipleAvatars() to make it synchronous, fixing avatar in conversations list when quickly scrolling + shortcuts for group conversation
This commit is contained in:
parent
f702054ac4
commit
03ee116ed4
8 changed files with 79 additions and 36 deletions
|
|
@ -21,6 +21,7 @@ package org.linphone.ui.main.chat.adapter
|
|||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
|
|
@ -180,7 +181,9 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
|
|||
model = message
|
||||
executePendingBindings()
|
||||
|
||||
binding.deliveryStatus.startAnimatedDrawable()
|
||||
binding.root.doOnPreDraw {
|
||||
binding.deliveryStatus.startAnimatedDrawable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -193,7 +196,9 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
|
|||
model = message
|
||||
executePendingBindings()
|
||||
|
||||
binding.deliveryStatus.startAnimatedDrawable()
|
||||
binding.root.doOnPreDraw {
|
||||
binding.deliveryStatus.startAnimatedDrawable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.linphone.ui.main.chat.adapter
|
|||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
|
|
@ -74,7 +75,9 @@ class ConversationsListAdapter : ListAdapter<ConversationModel, RecyclerView.Vie
|
|||
|
||||
executePendingBindings()
|
||||
|
||||
binding.lastSentMessageStatus.startAnimatedDrawable()
|
||||
binding.root.doOnPreDraw {
|
||||
binding.lastSentMessageStatus.startAnimatedDrawable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,12 +60,12 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) {
|
|||
|
||||
val isComposing = MutableLiveData<Boolean>()
|
||||
|
||||
val composingLabel = MutableLiveData<String>()
|
||||
|
||||
val isMuted = MutableLiveData<Boolean>()
|
||||
|
||||
val isEphemeral = MutableLiveData<Boolean>()
|
||||
|
||||
val composingLabel = MutableLiveData<Boolean>()
|
||||
|
||||
val lastMessageText = MutableLiveData<String>()
|
||||
|
||||
val lastMessageIcon = MutableLiveData<Int>()
|
||||
|
|
@ -341,6 +341,32 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) {
|
|||
|
||||
@WorkerThread
|
||||
private fun computeComposingLabel() {
|
||||
// TODO
|
||||
val composing = chatRoom.isRemoteComposing
|
||||
isComposing.postValue(composing)
|
||||
if (!composing) {
|
||||
composingLabel.postValue("")
|
||||
return
|
||||
}
|
||||
|
||||
val composingFriends = arrayListOf<String>()
|
||||
var label = ""
|
||||
for (address in chatRoom.composingAddresses) {
|
||||
val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val name = avatar.name.value ?: LinphoneUtils.getDisplayName(address)
|
||||
composingFriends.add(name)
|
||||
label += "$name, "
|
||||
}
|
||||
if (composingFriends.size > 0) {
|
||||
label = label.dropLast(2)
|
||||
|
||||
val format = AppUtils.getStringWithPlural(
|
||||
R.plurals.conversation_composing_label,
|
||||
composingFriends.size,
|
||||
label
|
||||
)
|
||||
composingLabel.postValue(format)
|
||||
} else {
|
||||
composingLabel.postValue("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ import androidx.databinding.ViewDataBinding
|
|||
import androidx.emoji2.emojipicker.EmojiPickerView
|
||||
import androidx.emoji2.emojipicker.EmojiViewItem
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||
import coil.dispose
|
||||
import coil.load
|
||||
|
|
@ -56,7 +55,6 @@ import coil.request.videoFrameMillis
|
|||
import coil.size.Dimension
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
import kotlinx.coroutines.launch
|
||||
import org.linphone.BR
|
||||
import org.linphone.R
|
||||
import org.linphone.contacts.AbstractAvatarModel
|
||||
|
|
@ -412,10 +410,8 @@ private fun loadContactPictureWithCoil(
|
|||
} else {
|
||||
AppUtils.getDimension(R.dimen.avatar_list_cell_size).toInt()
|
||||
}
|
||||
(context as AppCompatActivity).lifecycleScope.launch {
|
||||
val bitmap = ImageUtils.getBitmapFromMultipleAvatars(imageView.context, w, images)
|
||||
imageView.load(bitmap)
|
||||
}
|
||||
val bitmap = ImageUtils.getBitmapFromMultipleAvatars(imageView.context, w, images)
|
||||
imageView.load(bitmap)
|
||||
}
|
||||
} else {
|
||||
imageView.load(R.drawable.smiley)
|
||||
|
|
|
|||
|
|
@ -207,13 +207,19 @@ class FileUtils {
|
|||
return contentUri
|
||||
}
|
||||
|
||||
suspend fun getFilePath(context: Context, uri: Uri, overrideExisting: Boolean): String? {
|
||||
suspend fun getFilePath(
|
||||
context: Context,
|
||||
uri: Uri,
|
||||
overrideExisting: Boolean,
|
||||
copyToCache: Boolean = false
|
||||
): String? {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val name: String = getNameFromUri(uri, context)
|
||||
try {
|
||||
val path = uri.path
|
||||
if (path.isNullOrEmpty()) return@withContext null
|
||||
if (Os.fstat(
|
||||
ParcelFileDescriptor.open(
|
||||
File(uri.path),
|
||||
File(path),
|
||||
ParcelFileDescriptor.MODE_READ_ONLY
|
||||
).fileDescriptor
|
||||
).st_uid != Process.myUid()
|
||||
|
|
@ -225,12 +231,17 @@ class FileUtils {
|
|||
Log.e("$TAG Can't check file ownership: ", e)
|
||||
}
|
||||
|
||||
val name: String = getNameFromUri(uri, context)
|
||||
val extension = getExtensionFromFileName(name)
|
||||
val type = getMimeTypeFromExtension(extension)
|
||||
val isImage = getMimeType(type) == MimeType.Image
|
||||
|
||||
try {
|
||||
val localFile: File = getFileStoragePath(name, isImage, overrideExisting)
|
||||
val localFile: File = if (copyToCache) {
|
||||
getFileStorageCacheDir(name, overrideExisting)
|
||||
} else {
|
||||
getFileStoragePath(name, isImage, overrideExisting)
|
||||
}
|
||||
copyFile(uri, localFile)
|
||||
return@withContext localFile.absolutePath
|
||||
} catch (e: Exception) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package org.linphone.utils
|
|||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.ImageDecoder
|
||||
import android.graphics.Rect
|
||||
|
|
@ -28,9 +29,6 @@ import android.graphics.drawable.BitmapDrawable
|
|||
import android.net.Uri
|
||||
import androidx.annotation.AnyThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import coil.imageLoader
|
||||
import coil.request.ImageRequest
|
||||
import java.io.FileNotFoundException
|
||||
import org.linphone.contacts.AvatarGenerator
|
||||
import org.linphone.core.tools.Log
|
||||
|
|
@ -39,7 +37,7 @@ class ImageUtils {
|
|||
companion object {
|
||||
private const val TAG = "[Image Utils]"
|
||||
|
||||
@WorkerThread
|
||||
@AnyThread
|
||||
fun getGeneratedAvatar(context: Context, size: Int = 0, textSize: Int = 0, initials: String): BitmapDrawable {
|
||||
val builder = AvatarGenerator(context)
|
||||
builder.setInitials(initials)
|
||||
|
|
@ -89,17 +87,20 @@ class ImageUtils {
|
|||
}
|
||||
|
||||
@AnyThread
|
||||
suspend fun getBitmapFromMultipleAvatars(context: Context, size: Int, images: List<String>): Bitmap {
|
||||
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(bitmap)
|
||||
|
||||
fun getBitmapFromMultipleAvatars(context: Context, size: Int, images: List<String>): Bitmap {
|
||||
val drawables = images.mapNotNull {
|
||||
val request = ImageRequest.Builder(context)
|
||||
.data(it)
|
||||
.size(size / 2)
|
||||
.allowHardware(false)
|
||||
.build()
|
||||
context.imageLoader.execute(request).drawable
|
||||
try {
|
||||
val uri = Uri.parse(it)
|
||||
val stream = context.contentResolver.openInputStream(uri)
|
||||
val bm = BitmapFactory.decodeStream(stream)
|
||||
if (bm != null) {
|
||||
Bitmap.createScaledBitmap(bm, size, size, false)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val rectangles = if (drawables.size == 2) {
|
||||
|
|
@ -124,6 +125,9 @@ class ImageUtils {
|
|||
arrayListOf(Rect(0, 0, size, size))
|
||||
}
|
||||
|
||||
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(bitmap)
|
||||
|
||||
for (i in 0 until rectangles.size) {
|
||||
val src = if (drawables.size == 3 && i == 2) {
|
||||
// To prevent deformation for the bottom image when merging 3 of them
|
||||
|
|
@ -139,7 +143,7 @@ class ImageUtils {
|
|||
|
||||
try {
|
||||
canvas.drawBitmap(
|
||||
drawables[i].toBitmap(size, size, Bitmap.Config.ARGB_8888),
|
||||
drawables[i]/*.toBitmap(size, size, Bitmap.Config.ARGB_8888)*/,
|
||||
src,
|
||||
rectangles[i],
|
||||
null
|
||||
|
|
|
|||
|
|
@ -145,9 +145,7 @@ class ShortcutUtils {
|
|||
).buildIcon()
|
||||
} else {
|
||||
subject = chatRoom.subject.orEmpty()
|
||||
IconCompat.createWithResource(context, R.drawable.users_three)
|
||||
// TODO FIXME: use generated chat room avatar
|
||||
/*val list = arrayListOf<String>()
|
||||
val list = arrayListOf<String>()
|
||||
for (participant in chatRoom.participants) {
|
||||
val contact =
|
||||
coreContext.contactsManager.findContactByAddress(participant.address)
|
||||
|
|
@ -169,7 +167,7 @@ class ShortcutUtils {
|
|||
)
|
||||
} else {
|
||||
AvatarGenerator(context).setInitials(subject).buildIcon()
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
val persons = arrayOfNulls<Person>(personsList.size)
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@
|
|||
android:text="@{model.isBeingDeleted ? @string/conversations_list_is_being_removed_label : model.isComposing ? model.composingLabel : model.lastMessageText, default=`Hello there!`}"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_400"
|
||||
android:textStyle="@{model.isBeingDeleted || model.unreadMessageCount > 0 ? Typeface.BOLD : Typeface.NORMAL}"
|
||||
android:textStyle="@{model.isBeingDeleted || model.unreadMessageCount > 0 || model.isComposing ? Typeface.BOLD : Typeface.NORMAL}"
|
||||
app:layout_constraintStart_toStartOf="@id/name"
|
||||
app:layout_constraintEnd_toStartOf="@id/right_border"
|
||||
app:layout_constraintTop_toBottomOf="@id/name"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue