Finished removing AvatarView (still borders to do and fix display issue when group has 3 participants)

This commit is contained in:
Sylvain Berfini 2023-10-14 15:27:45 +02:00
parent e4a3ec37c5
commit 43cf0f5cba
12 changed files with 146 additions and 383 deletions

View file

@ -99,9 +99,6 @@ dependencies {
implementation("io.coil-kt:coil-svg:$coil_version") implementation("io.coil-kt:coil-svg:$coil_version")
implementation("io.coil-kt:coil-video:$coil_version") implementation("io.coil-kt:coil-video:$coil_version")
// https://github.com/GetStream/avatarview-android/blob/main/LICENSE Apache v2.0
implementation "io.getstream:avatarview-coil:1.0.7"
// https://github.com/tommybuonomo/dotsindicator/blob/master/LICENSE Apache v2.0 // https://github.com/tommybuonomo/dotsindicator/blob/master/LICENSE Apache v2.0
implementation("com.tbuonomo:dotsindicator:5.0") implementation("com.tbuonomo:dotsindicator:5.0")

View file

@ -30,8 +30,6 @@ import coil.decode.VideoFrameDecoder
import coil.disk.DiskCache import coil.disk.DiskCache
import coil.memory.MemoryCache import coil.memory.MemoryCache
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import io.getstream.avatarview.coil.AvatarCoil
import io.getstream.avatarview.coil.AvatarImageLoaderFactory
import org.linphone.core.CoreContext import org.linphone.core.CoreContext
import org.linphone.core.CorePreferences import org.linphone.core.CorePreferences
import org.linphone.core.Factory import org.linphone.core.Factory
@ -76,11 +74,6 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
coreContext.start() coreContext.start()
DynamicColors.applyToActivitiesIfAvailable(this) DynamicColors.applyToActivitiesIfAvailable(this)
AvatarCoil.setImageLoader(
AvatarImageLoaderFactory(context) {
newImageLoader()
}
)
} }
override fun newImageLoader(): ImageLoader { override fun newImageLoader(): ImageLoader {

View file

@ -34,7 +34,6 @@ import org.linphone.core.EventLog
import org.linphone.core.Friend import org.linphone.core.Friend
import org.linphone.core.tools.Log import org.linphone.core.tools.Log
import org.linphone.ui.main.contacts.model.ContactAvatarModel import org.linphone.ui.main.contacts.model.ContactAvatarModel
import org.linphone.ui.main.contacts.model.GroupAvatarModel
import org.linphone.utils.AppUtils import org.linphone.utils.AppUtils
import org.linphone.utils.LinphoneUtils import org.linphone.utils.LinphoneUtils
import org.linphone.utils.TimestampUtils import org.linphone.utils.TimestampUtils
@ -78,8 +77,6 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
val avatarModel = MutableLiveData<ContactAvatarModel>() val avatarModel = MutableLiveData<ContactAvatarModel>()
val groupAvatarModel: GroupAvatarModel
private var lastMessage: ChatMessage? = null private var lastMessage: ChatMessage? = null
private val chatRoomListener = object : ChatRoomListenerStub() { private val chatRoomListener = object : ChatRoomListenerStub() {
@ -145,15 +142,24 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
} }
firstParticipant?.address ?: chatRoom.peerAddress firstParticipant?.address ?: chatRoom.peerAddress
} }
val friend = coreContext.contactsManager.findContactByAddress(address)
if (friend != null) { if (isGroup) {
avatarModel.postValue(ContactAvatarModel(friend))
} else {
val fakeFriend = coreContext.core.createFriend() val fakeFriend = coreContext.core.createFriend()
fakeFriend.address = address val model = ContactAvatarModel(fakeFriend)
avatarModel.postValue(ContactAvatarModel(fakeFriend)) model.addPicturesFromFriends(friends)
avatarModel.postValue(model)
} else {
val friend = coreContext.contactsManager.findContactByAddress(address)
if (friend != null) {
val model = ContactAvatarModel(friend)
avatarModel.postValue(model)
} else {
val fakeFriend = coreContext.core.createFriend()
fakeFriend.address = address
val model = ContactAvatarModel(fakeFriend)
avatarModel.postValue(model)
}
} }
groupAvatarModel = GroupAvatarModel(friends)
isMuted.postValue(chatRoom.muted) isMuted.postValue(chatRoom.muted)
isEphemeral.postValue(chatRoom.isEphemeralEnabled) isEphemeral.postValue(chatRoom.isEphemeralEnabled)

View file

@ -35,7 +35,6 @@ import org.linphone.core.tools.Log
import org.linphone.ui.main.chat.model.ChatMessageModel import org.linphone.ui.main.chat.model.ChatMessageModel
import org.linphone.ui.main.chat.model.EventLogModel import org.linphone.ui.main.chat.model.EventLogModel
import org.linphone.ui.main.contacts.model.ContactAvatarModel import org.linphone.ui.main.contacts.model.ContactAvatarModel
import org.linphone.ui.main.contacts.model.GroupAvatarModel
import org.linphone.utils.AppUtils import org.linphone.utils.AppUtils
import org.linphone.utils.Event import org.linphone.utils.Event
import org.linphone.utils.LinphoneUtils import org.linphone.utils.LinphoneUtils
@ -51,8 +50,6 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
val avatarModel = MutableLiveData<ContactAvatarModel>() val avatarModel = MutableLiveData<ContactAvatarModel>()
val groupAvatarModel = MutableLiveData<GroupAvatarModel>()
val events = MutableLiveData<ArrayList<EventLogModel>>() val events = MutableLiveData<ArrayList<EventLogModel>>()
val isGroup = MutableLiveData<Boolean>() val isGroup = MutableLiveData<Boolean>()
@ -244,10 +241,15 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
val firstParticipant = chatRoom.participants.firstOrNull() val firstParticipant = chatRoom.participants.firstOrNull()
firstParticipant?.address ?: chatRoom.peerAddress firstParticipant?.address ?: chatRoom.peerAddress
} }
val avatar = getAvatarModelForAddress(address)
val avatar = if (isGroupChatRoom) {
val fakeFriend = coreContext.core.createFriend()
ContactAvatarModel(fakeFriend)
} else {
getAvatarModelForAddress(address)
}
avatar.addPicturesFromFriends(friends)
avatarModel.postValue(avatar) avatarModel.postValue(avatar)
val groupAvatar = GroupAvatarModel(friends)
groupAvatarModel.postValue(groupAvatar)
val history = chatRoom.getHistoryEvents(0) val history = chatRoom.getHistoryEvents(0)
val eventsList = getEventsListFromHistory(history, isGroupChatRoom) val eventsList = getEventsListFromHistory(history, isGroupChatRoom)

View file

@ -71,7 +71,7 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) : Abstrac
initials.postValue(AppUtils.getInitials(friend.name.orEmpty())) initials.postValue(AppUtils.getInitials(friend.name.orEmpty()))
trust.postValue(SecurityLevel.Safe) // TODO FIXME: use API trust.postValue(SecurityLevel.Safe) // TODO FIXME: use API
showTrust.postValue(coreContext.core.defaultAccount?.isInSecureMode()) showTrust.postValue(coreContext.core.defaultAccount?.isInSecureMode())
images.postValue(arrayListOf(getAvatarUri().toString())) images.postValue(arrayListOf(getAvatarUri(friend).toString()))
name.postValue(friend.name) name.postValue(friend.name)
computePresence() computePresence()
@ -83,7 +83,19 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) : Abstrac
} }
@WorkerThread @WorkerThread
private fun getAvatarUri(): Uri? { fun addPicturesFromFriends(friends: List<Friend>) {
if (friends.isNotEmpty()) {
val list = arrayListOf<String>()
list.addAll(images.value.orEmpty())
for (friend in friends) {
list.add(getAvatarUri(friend).toString())
}
images.postValue(list)
}
}
@WorkerThread
private fun getAvatarUri(friend: Friend): Uri? {
val picturePath = friend.photo val picturePath = friend.photo
if (!picturePath.isNullOrEmpty()) { if (!picturePath.isNullOrEmpty()) {
return Uri.parse(picturePath) return Uri.parse(picturePath)

View file

@ -1,81 +0,0 @@
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.ui.main.contacts.model
import android.content.ContentUris
import android.net.Uri
import android.provider.ContactsContract
import androidx.annotation.WorkerThread
import androidx.lifecycle.MutableLiveData
import org.linphone.core.ChatRoom.SecurityLevel
import org.linphone.core.Friend
import org.linphone.core.tools.Log
class GroupAvatarModel @WorkerThread constructor(friends: ArrayList<Friend>) {
companion object {
private const val TAG = "[Group Avatar Model]"
}
val trust = MutableLiveData<SecurityLevel>()
val uris = MutableLiveData<List<Uri>>()
init {
trust.postValue(SecurityLevel.Safe) // TODO FIXME: use API
val list = arrayListOf<Uri>()
Log.d("$TAG [${friends.size}] friends to use")
for (friend in friends) {
val uri = getAvatarUri(friend)
if (uri != null) {
if (!list.contains(uri)) {
list.add(uri)
}
}
}
uris.postValue(list.toList())
}
@WorkerThread
private fun getAvatarUri(friend: Friend): Uri? {
val picturePath = friend.photo
if (!picturePath.isNullOrEmpty()) {
return Uri.parse(picturePath)
}
val refKey = friend.refKey
if (refKey != null) {
try {
val lookupUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
refKey.toLong()
)
return Uri.withAppendedPath(
lookupUri,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY
)
} catch (numberFormatException: NumberFormatException) {
// Expected for contacts created by Linphone
}
}
return null
}
}

View file

@ -21,7 +21,10 @@ package org.linphone.utils
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.graphics.Rect
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.LayoutInflater import android.view.LayoutInflater
@ -37,6 +40,7 @@ import androidx.annotation.UiThread
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.AppCompatEditText
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.doOnLayout import androidx.core.view.doOnLayout
@ -48,10 +52,10 @@ import androidx.emoji2.emojipicker.EmojiViewItem
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import coil.dispose import coil.dispose
import coil.imageLoader
import coil.load import coil.load
import coil.request.ImageRequest
import coil.transform.CircleCropTransformation import coil.transform.CircleCropTransformation
import io.getstream.avatarview.AvatarView
import io.getstream.avatarview.coil.loadImage
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -60,10 +64,8 @@ import org.linphone.BR
import org.linphone.R import org.linphone.R
import org.linphone.contacts.AbstractAvatarModel import org.linphone.contacts.AbstractAvatarModel
import org.linphone.contacts.AvatarGenerator import org.linphone.contacts.AvatarGenerator
import org.linphone.core.ChatRoom
import org.linphone.core.ConsolidatedPresence import org.linphone.core.ConsolidatedPresence
import org.linphone.core.tools.Log import org.linphone.core.tools.Log
import org.linphone.ui.main.contacts.model.GroupAvatarModel
/** /**
* This file contains all the data binding necessary for the app * This file contains all the data binding necessary for the app
@ -264,6 +266,20 @@ fun ImageView.loadCallAvatarWithCoil(model: AbstractAvatarModel?) {
} }
} }
@UiThread
@BindingAdapter("coilInitials")
fun ImageView.loadInitialsAvatarWithCoil(initials: String?) {
Log.i("[Data Binding Utils] Displaying initials [$initials] on ImageView")
val imageView = this
(context as AppCompatActivity).lifecycleScope.launch {
withContext(Dispatchers.IO) {
val builder = AvatarGenerator(context)
builder.setInitials(initials.orEmpty())
load(builder.build())
}
}
}
@SuppressLint("ResourceType") @SuppressLint("ResourceType")
private suspend fun loadContactPictureWithCoil( private suspend fun loadContactPictureWithCoil(
imageView: ImageView, imageView: ImageView,
@ -276,173 +292,86 @@ private suspend fun loadContactPictureWithCoil(
val context = imageView.context val context = imageView.context
if (model != null) { if (model != null) {
val image = model.images.value?.firstOrNull() val images = model.images.value.orEmpty()
imageView.load(image) { val count = images.size
transformations(CircleCropTransformation()) if (count == 1) {
error( val image = images.firstOrNull()
coroutineScope { imageView.load(image) {
withContext(Dispatchers.IO) { transformations(CircleCropTransformation())
val builder = AvatarGenerator(context) error(
builder.setInitials(model.initials.value.orEmpty()) coroutineScope {
if (size > 0) { withContext(Dispatchers.IO) {
builder.setAvatarSize(AppUtils.getDimension(size).toInt()) val builder = AvatarGenerator(context)
builder.setInitials(model.initials.value.orEmpty())
if (size > 0) {
builder.setAvatarSize(AppUtils.getDimension(size).toInt())
}
if (textSize > 0) {
builder.setTextSize(AppUtils.getDimension(textSize))
}
builder.build()
} }
if (textSize > 0) {
builder.setTextSize(AppUtils.getDimension(textSize))
}
/*if (color > 0) {
builder.setBackgroundColorAttribute(color)
}
if (textColor > 0) {
builder.setTextColorResource(textColor)
}*/
builder.build()
} }
} )
) }
} else if (count > 1) {
val w = if (size > 0) {
AppUtils.getDimension(size).toInt()
} else {
AppUtils.getDimension(R.dimen.avatar_list_cell_size).toInt()
}
val bitmap = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val drawables = images.mapNotNull {
val request = ImageRequest.Builder(imageView.context)
.data(it)
.size(w / 2)
.allowHardware(false)
.build()
context.imageLoader.execute(request).drawable
}
val rectangles = if (drawables.size == 2) {
arrayListOf(
Rect(0, 0, w / 2, w),
Rect(w / 2, 0, w, w)
)
} else if (drawables.size == 3) {
// TODO FIXME
arrayListOf(
Rect(0, 0, w / 2, w / 2),
Rect(w / 2, 0, w, w / 2),
Rect(0, w / 2, w, w)
)
} else if (drawables.size >= 4) {
arrayListOf(
Rect(0, 0, w / 2, w / 2),
Rect(w / 2, 0, w, w / 2),
Rect(0, w / 2, w / 2, w),
Rect(w / 2, w / 2, w, w)
)
} else {
arrayListOf()
}
for (i in 0 until rectangles.size) {
canvas.drawBitmap(
drawables[i].toBitmap(w, w, Bitmap.Config.ARGB_8888),
null,
rectangles[i],
null
)
}
imageView.load(bitmap) {
transformations(CircleCropTransformation())
}
} }
} }
} }
} }
/*@UiThread
@BindingAdapter("avatarInitials")
fun AvatarView.loadInitials(initials: String?) {
Log.i("[Data Binding Utils] Displaying initials [$initials] on AvatarView")
if (initials.orEmpty() != "+") {
avatarInitials = initials.orEmpty()
}
}
@UiThread
@BindingAdapter("accountAvatar")
fun AvatarView.loadAccountAvatar(account: AccountModel?) {
Log.i("[Data Binding Utils] Loading account picture [${account?.avatar?.value}] with coil")
if (account == null) {
loadImage(R.drawable.user_circle)
} else {
val lifecycleOwner = findViewTreeLifecycleOwner()
if (lifecycleOwner != null) {
account.avatar.observe(lifecycleOwner) { uri ->
loadImage(
data = uri,
onStart = {
if (account.showTrust.value == true) {
avatarBorderColor =
resources.getColor(R.color.blue_info_500, context.theme)
avatarBorderWidth =
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
} else {
avatarBorderWidth = AppUtils.getDimension(R.dimen.zero).toInt()
}
},
onError = { _, _ ->
// Use initials as fallback
val initials = account.initials.value.orEmpty()
if (initials != "+") {
avatarInitials = initials
}
}
)
}
} else {
loadImage(
data = account.avatar.value,
onStart = {
if (account.showTrust.value == true) {
avatarBorderColor = resources.getColor(R.color.blue_info_500, context.theme)
avatarBorderWidth = AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
} else {
avatarBorderWidth = AppUtils.getDimension(R.dimen.zero).toInt()
}
},
onError = { _, _ ->
// Use initials as fallback
val initials = account.initials.value.orEmpty()
if (initials != "+") {
avatarInitials = initials
}
}
)
}
}
}
@UiThread
@BindingAdapter("contactAvatar")
fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) {
if (contact == null) {
loadImage(R.drawable.user_circle)
} else {
val uri = contact.avatar.value
loadImage(
data = uri,
onStart = {
when (contact.trust.value) {
ChatRoom.SecurityLevel.Unsafe -> {
avatarBorderColor =
resources.getColor(R.color.red_danger_500, context.theme)
avatarBorderWidth =
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
}
ChatRoom.SecurityLevel.Safe -> {
avatarBorderColor =
resources.getColor(R.color.blue_info_500, context.theme)
avatarBorderWidth =
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
}
else -> {
avatarBorderWidth = AppUtils.getDimension(R.dimen.zero).toInt()
}
}
},
onError = { _, result ->
Log.e("[Contact Avatar Model] Can't load data: ${result.throwable}")
// Use initials as fallback
val initials = contact.initials
if (initials != "+") {
avatarInitials = initials
}
}
)
}
}*/
@UiThread
@BindingAdapter("groupAvatar")
fun AvatarView.loadGroupAvatar(contact: GroupAvatarModel?) {
if (contact == null) {
loadImage(R.drawable.user_circle)
} else {
val uris = contact.uris.value.orEmpty()
loadImage(
data = uris,
onStart = {
when (contact.trust.value) {
ChatRoom.SecurityLevel.Unsafe -> {
avatarBorderColor =
resources.getColor(R.color.red_danger_500, context.theme)
avatarBorderWidth =
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
}
ChatRoom.SecurityLevel.Encrypted -> {
avatarBorderColor =
resources.getColor(R.color.blue_info_500, context.theme)
avatarBorderWidth =
AppUtils.getDimension(R.dimen.avatar_trust_border_width).toInt()
}
else -> {
avatarBorderWidth = AppUtils.getDimension(R.dimen.zero).toInt()
}
}
},
onError = { _, result ->
Log.e("[Group Avatar Model] Can't load data: ${result.throwable}")
}
)
}
}
@UiThread @UiThread
@BindingAdapter("onValueChanged") @BindingAdapter("onValueChanged")
fun AppCompatEditText.editTextSetting(lambda: () -> Unit) { fun AppCompatEditText.editTextSetting(lambda: () -> Unit) {

View file

@ -111,7 +111,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<io.getstream.avatarview.AvatarView <ImageView
android:id="@+id/image1" android:id="@+id/image1"
android:layout_width="@dimen/avatar_list_cell_size" android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size" android:layout_height="@dimen/avatar_list_cell_size"
@ -120,14 +120,7 @@
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
android:src="@drawable/user_circle" android:src="@drawable/user_circle"
app:avatarViewPlaceholder="@drawable/user_circle" coilInitials="@{`JD`}"
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
app:avatarViewInitialsTextColor="@color/gray_main2_600"
app:avatarViewInitialsTextSize="16sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewShape="circle"
app:avatarViewInitials="JD"
app:avatarViewBorderWidth="0dp"
app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/arrow" app:layout_constraintEnd_toStartOf="@id/arrow"
@ -156,22 +149,14 @@
app:layout_constraintTop_toTopOf="@id/image1" app:layout_constraintTop_toTopOf="@id/image1"
app:layout_constraintBottom_toBottomOf="@id/image1"/> app:layout_constraintBottom_toBottomOf="@id/image1"/>
<io.getstream.avatarview.AvatarView <ImageView
android:id="@+id/image2" android:id="@+id/image2"
android:layout_width="@dimen/avatar_list_cell_size" android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size" android:layout_height="@dimen/avatar_list_cell_size"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
android:src="@drawable/user_circle" android:src="@drawable/user_circle"
app:avatarViewPlaceholder="@drawable/user_circle" coilInitials="@{`JD`}"
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
app:avatarViewInitialsTextColor="@color/gray_main2_600"
app:avatarViewInitialsTextSize="16sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewShape="circle"
app:avatarViewInitials="JD"
app:avatarViewBorderWidth="2dp"
app:avatarViewBorderColor="@color/blue_info_500"
app:layout_constraintStart_toEndOf="@id/arrow" app:layout_constraintStart_toEndOf="@id/arrow"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/image1" app:layout_constraintTop_toTopOf="@id/image1"

View file

@ -126,7 +126,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<io.getstream.avatarview.AvatarView <ImageView
android:id="@+id/image1" android:id="@+id/image1"
android:layout_width="@dimen/avatar_list_cell_size" android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size" android:layout_height="@dimen/avatar_list_cell_size"
@ -135,14 +135,7 @@
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
android:src="@drawable/user_circle" android:src="@drawable/user_circle"
app:avatarViewPlaceholder="@drawable/user_circle" coilInitials="@{`JD`}"
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
app:avatarViewInitialsTextColor="@color/gray_main2_600"
app:avatarViewInitialsTextSize="16sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewShape="circle"
app:avatarViewInitials="JD"
app:avatarViewBorderWidth="0dp"
app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/arrow" app:layout_constraintEnd_toStartOf="@id/arrow"
@ -171,22 +164,14 @@
app:layout_constraintTop_toTopOf="@id/image1" app:layout_constraintTop_toTopOf="@id/image1"
app:layout_constraintBottom_toBottomOf="@id/image1"/> app:layout_constraintBottom_toBottomOf="@id/image1"/>
<io.getstream.avatarview.AvatarView <ImageView
android:id="@+id/image2" android:id="@+id/image2"
android:layout_width="@dimen/avatar_list_cell_size" android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size" android:layout_height="@dimen/avatar_list_cell_size"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
android:src="@drawable/user_circle" android:src="@drawable/user_circle"
app:avatarViewPlaceholder="@drawable/user_circle" coilInitials="@{`JD`}"
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
app:avatarViewInitialsTextColor="@color/gray_main2_600"
app:avatarViewInitialsTextSize="16sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewShape="circle"
app:avatarViewInitials="JD"
app:avatarViewBorderWidth="2dp"
app:avatarViewBorderColor="@color/blue_info_500"
app:layout_constraintStart_toEndOf="@id/arrow" app:layout_constraintStart_toEndOf="@id/arrow"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/image1" app:layout_constraintTop_toTopOf="@id/image1"

View file

@ -50,7 +50,6 @@
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
android:visibility="@{viewModel.isGroup ? View.GONE : View.VISIBLE}"
coilAvatar="@{viewModel.avatarModel}" coilAvatar="@{viewModel.avatarModel}"
app:layout_constraintBottom_toBottomOf="@id/back" app:layout_constraintBottom_toBottomOf="@id/back"
app:layout_constraintStart_toEndOf="@id/back" app:layout_constraintStart_toEndOf="@id/back"
@ -61,38 +60,10 @@
android:layout_width="@dimen/avatar_presence_badge_size" android:layout_width="@dimen/avatar_presence_badge_size"
android:layout_height="@dimen/avatar_presence_badge_size" android:layout_height="@dimen/avatar_presence_badge_size"
android:src="@{viewModel.avatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}" android:src="@{viewModel.avatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
android:visibility="@{!viewModel.isGroup &amp;&amp; viewModel.avatarModel.trust == SecurityLevel.Encrypted || viewModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}" android:visibility="@{viewModel.avatarModel.trust == SecurityLevel.Encrypted || viewModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
app:layout_constraintStart_toStartOf="@id/avatar" app:layout_constraintStart_toStartOf="@id/avatar"
app:layout_constraintBottom_toBottomOf="@id/avatar"/> app:layout_constraintBottom_toBottomOf="@id/avatar"/>
<io.getstream.avatarview.AvatarView
android:id="@+id/group_avatar"
android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="5dp"
android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background"
android:visibility="@{viewModel.isGroup ? View.VISIBLE : View.GONE, default=gone}"
groupAvatar="@{viewModel.groupAvatarModel}"
app:avatarViewPlaceholder="@drawable/users_three"
app:avatarViewMaxSectionSize="four"
app:avatarViewShape="circle"
app:avatarViewBorderWidth="0dp"
app:layout_constraintBottom_toBottomOf="@id/back"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="@id/back" />
<ImageView
android:id="@+id/group_trust_badge"
android:layout_width="@dimen/avatar_presence_badge_size"
android:layout_height="@dimen/avatar_presence_badge_size"
android:src="@{viewModel.groupAvatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
android:visibility="@{viewModel.isGroup &amp;&amp; viewModel.groupAvatarModel.trust == SecurityLevel.Encrypted || viewModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintStart_toStartOf="@id/group_avatar"
app:layout_constraintBottom_toBottomOf="@id/group_avatar"/>
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style" style="@style/default_text_style"
android:id="@+id/title" android:id="@+id/title"
@ -107,7 +78,7 @@
android:textColor="@color/gray_main2_600" android:textColor="@color/gray_main2_600"
android:gravity="center_vertical" android:gravity="center_vertical"
app:layout_constraintEnd_toStartOf="@id/call" app:layout_constraintEnd_toStartOf="@id/call"
app:layout_constraintStart_toEndOf="@id/group_avatar" app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintTop_toTopOf="parent"/>
<ImageView <ImageView

View file

@ -38,7 +38,6 @@
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
coilAvatar="@{model.avatarModel}" coilAvatar="@{model.avatarModel}"
android:visibility="@{model.isGroup ? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -51,7 +50,7 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/avatar_presence_badge_padding" android:padding="@dimen/avatar_presence_badge_padding"
app:presenceIcon="@{model.avatarModel.presenceStatus}" app:presenceIcon="@{model.avatarModel.presenceStatus}"
android:visibility="@{model.isGroup || model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}" android:visibility="@{model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
app:layout_constraintEnd_toEndOf="@id/avatar" app:layout_constraintEnd_toEndOf="@id/avatar"
app:layout_constraintBottom_toBottomOf="@id/avatar"/> app:layout_constraintBottom_toBottomOf="@id/avatar"/>
@ -60,38 +59,10 @@
android:layout_width="@dimen/avatar_presence_badge_size" android:layout_width="@dimen/avatar_presence_badge_size"
android:layout_height="@dimen/avatar_presence_badge_size" android:layout_height="@dimen/avatar_presence_badge_size"
android:src="@{model.avatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}" android:src="@{model.avatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
android:visibility="@{!model.isGroup &amp;&amp; model.avatarModel.trust == SecurityLevel.Encrypted || model.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}" android:visibility="@{model.avatarModel.trust == SecurityLevel.Encrypted || model.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
app:layout_constraintStart_toStartOf="@id/avatar" app:layout_constraintStart_toStartOf="@id/avatar"
app:layout_constraintBottom_toBottomOf="@id/avatar"/> app:layout_constraintBottom_toBottomOf="@id/avatar"/>
<io.getstream.avatarview.AvatarView
android:id="@+id/group_avatar"
android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="5dp"
android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background"
android:visibility="@{model.isGroup ? View.VISIBLE : View.GONE, default=gone}"
groupAvatar="@{model.groupAvatarModel}"
app:avatarViewPlaceholder="@drawable/users_three"
app:avatarViewMaxSectionSize="four"
app:avatarViewShape="circle"
app:avatarViewBorderWidth="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/group_trust_badge"
android:layout_width="@dimen/avatar_presence_badge_size"
android:layout_height="@dimen/avatar_presence_badge_size"
android:src="@{model.groupAvatarModel.trust == SecurityLevel.Encrypted ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
android:visibility="@{model.isGroup &amp;&amp; model.groupAvatarModel.trust == SecurityLevel.Encrypted || model.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintStart_toStartOf="@id/group_avatar"
app:layout_constraintBottom_toBottomOf="@id/group_avatar"/>
<androidx.constraintlayout.widget.Barrier <androidx.constraintlayout.widget.Barrier
android:id="@+id/right_border" android:id="@+id/right_border"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -113,7 +84,7 @@
android:textSize="14sp" android:textSize="14sp"
android:textColor="@color/gray_main2_800" android:textColor="@color/gray_main2_800"
android:textStyle="@{model.unreadMessageCount > 0 ? Typeface.BOLD : Typeface.NORMAL}" android:textStyle="@{model.unreadMessageCount > 0 ? Typeface.BOLD : Typeface.NORMAL}"
app:layout_constraintStart_toEndOf="@id/group_avatar" app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintEnd_toStartOf="@id/right_border" app:layout_constraintEnd_toStartOf="@id/right_border"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/last_message_or_composing"/> app:layout_constraintBottom_toTopOf="@id/last_message_or_composing"/>

View file

@ -21,7 +21,7 @@
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"> android:layout_marginEnd="16dp">
<io.getstream.avatarview.AvatarView <ImageView
android:id="@+id/avatar" android:id="@+id/avatar"
android:layout_width="@dimen/avatar_list_cell_size" android:layout_width="@dimen/avatar_list_cell_size"
android:layout_height="@dimen/avatar_list_cell_size" android:layout_height="@dimen/avatar_list_cell_size"
@ -29,14 +29,7 @@
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@drawable/shape_circle_light_blue_background" android:background="@drawable/shape_circle_light_blue_background"
avatarInitials="@{model.initials, default=`JD`}" coilInitials="@{model.initials, default=`JD`}"
app:avatarViewPlaceholder="@drawable/user_circle"
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
app:avatarViewInitialsTextColor="@color/gray_main2_600"
app:avatarViewInitialsTextSize="16sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewShape="circle"
app:avatarViewBorderWidth="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />