mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Added group avatar for group chat rooms
This commit is contained in:
parent
3dc23d906e
commit
8a62a68d6e
7 changed files with 259 additions and 76 deletions
|
|
@ -112,45 +112,52 @@ class ConversationEventAdapter(
|
|||
selectedAdapterPosition = -1
|
||||
}
|
||||
|
||||
fun groupPreviousItem(item: ChatMessageModel, position: Int): Boolean {
|
||||
return if (position == 0) {
|
||||
false
|
||||
} else {
|
||||
val previous = position - 1
|
||||
if (getItemViewType(position) == getItemViewType(previous)) {
|
||||
val previousItem = getItem(previous).data as ChatMessageModel
|
||||
if (kotlin.math.abs(item.timestamp - previousItem.timestamp) < MAX_TIME_TO_GROUP_MESSAGES) {
|
||||
previousItem.fromSipUri == item.fromSipUri
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isLastItemOfGroup(item: ChatMessageModel, position: Int): Boolean {
|
||||
return if (position == itemCount - 1) {
|
||||
true
|
||||
} else {
|
||||
val next = position + 1
|
||||
if (getItemViewType(next) == getItemViewType(position)) {
|
||||
val nextItem = getItem(next).data as ChatMessageModel
|
||||
if (kotlin.math.abs(item.timestamp - nextItem.timestamp) < MAX_TIME_TO_GROUP_MESSAGES) {
|
||||
nextItem.fromSipUri != item.fromSipUri
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class IncomingBubbleViewHolder(
|
||||
val binding: ChatBubbleIncomingBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(chatMessageData: ChatMessageModel) {
|
||||
fun bind(message: ChatMessageModel) {
|
||||
with(binding) {
|
||||
model = chatMessageData
|
||||
model = message
|
||||
|
||||
val position = bindingAdapterPosition
|
||||
isGroupedWithPreviousOne = if (position == 0) {
|
||||
false
|
||||
} else {
|
||||
val previous = position - 1
|
||||
if (getItemViewType(previous) == INCOMING_CHAT_MESSAGE) {
|
||||
val previousItem = getItem(previous).data as ChatMessageModel
|
||||
if (kotlin.math.abs(chatMessageData.timestamp - previousItem.timestamp) < MAX_TIME_TO_GROUP_MESSAGES) {
|
||||
previousItem.fromSipUri == chatMessageData.fromSipUri
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
isLastOneOfGroup = if (position == itemCount - 1) {
|
||||
true
|
||||
} else {
|
||||
val next = position + 1
|
||||
if (getItemViewType(next) == INCOMING_CHAT_MESSAGE) {
|
||||
val nextItem = getItem(next).data as ChatMessageModel
|
||||
if (kotlin.math.abs(chatMessageData.timestamp - nextItem.timestamp) < MAX_TIME_TO_GROUP_MESSAGES) {
|
||||
nextItem.fromSipUri != chatMessageData.fromSipUri
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
isGroupedWithPreviousOne = groupPreviousItem(message, position)
|
||||
isLastOneOfGroup = isLastItemOfGroup(message, position)
|
||||
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
executePendingBindings()
|
||||
|
|
@ -161,42 +168,13 @@ class ConversationEventAdapter(
|
|||
inner class OutgoingBubbleViewHolder(
|
||||
val binding: ChatBubbleOutgoingBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(chatMessageData: ChatMessageModel) {
|
||||
fun bind(message: ChatMessageModel) {
|
||||
with(binding) {
|
||||
model = chatMessageData
|
||||
model = message
|
||||
|
||||
val position = bindingAdapterPosition
|
||||
isGroupedWithPreviousOne = if (position == 0) {
|
||||
false
|
||||
} else {
|
||||
val previous = position - 1
|
||||
if (getItemViewType(previous) == OUTGOING_CHAT_MESSAGE) {
|
||||
val previousItem = getItem(previous).data as ChatMessageModel
|
||||
if (kotlin.math.abs(chatMessageData.timestamp - previousItem.timestamp) < MAX_TIME_TO_GROUP_MESSAGES) {
|
||||
previousItem.fromSipUri == chatMessageData.fromSipUri
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
isLastOneOfGroup = if (position == itemCount - 1) {
|
||||
true
|
||||
} else {
|
||||
val next = position + 1
|
||||
if (getItemViewType(next) == INCOMING_CHAT_MESSAGE) {
|
||||
val nextItem = getItem(next).data as ChatMessageModel
|
||||
if (kotlin.math.abs(chatMessageData.timestamp - nextItem.timestamp) < MAX_TIME_TO_GROUP_MESSAGES) {
|
||||
nextItem.fromSipUri != chatMessageData.fromSipUri
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
isGroupedWithPreviousOne = groupPreviousItem(message, position)
|
||||
isLastOneOfGroup = isLastItemOfGroup(message, position)
|
||||
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
executePendingBindings()
|
||||
|
|
@ -206,9 +184,9 @@ class ConversationEventAdapter(
|
|||
inner class EventViewHolder(
|
||||
val binding: ChatEventBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(eventData: EventModel) {
|
||||
fun bind(event: EventModel) {
|
||||
with(binding) {
|
||||
model = eventData
|
||||
model = event
|
||||
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
executePendingBindings()
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ import org.linphone.R
|
|||
import org.linphone.core.ChatMessage
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.ChatRoom.Capabilities
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.tools.Log
|
||||
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.LinphoneUtils
|
||||
import org.linphone.utils.TimestampUtils
|
||||
|
|
@ -72,10 +74,13 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
|
|||
|
||||
val avatarModel: ContactAvatarModel
|
||||
|
||||
val groupAvatarModel: GroupAvatarModel
|
||||
|
||||
init {
|
||||
subject.postValue(chatRoom.subject)
|
||||
lastUpdateTime.postValue(chatRoom.lastUpdateTime)
|
||||
|
||||
val friends = arrayListOf<Friend>()
|
||||
val address = if (chatRoom.hasCapability(Capabilities.Basic.toInt())) {
|
||||
Log.i("$TAG Chat room [$id] is 'Basic'")
|
||||
chatRoom.peerAddress
|
||||
|
|
@ -83,6 +88,14 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
|
|||
val firstParticipant = chatRoom.participants.firstOrNull()
|
||||
if (isGroup) {
|
||||
Log.i("$TAG Group chat room [$id] has [${chatRoom.nbParticipants}] participant(s)")
|
||||
for (participant in chatRoom.participants) {
|
||||
val friend = coreContext.contactsManager.findContactByAddress(
|
||||
participant.address
|
||||
)
|
||||
if (friend != null) {
|
||||
friends.add(friend)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i(
|
||||
"$TAG Chat room [$id] is with participant [${firstParticipant?.address?.asStringUriOnly()}]"
|
||||
|
|
@ -90,7 +103,6 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
|
|||
}
|
||||
firstParticipant?.address ?: chatRoom.peerAddress
|
||||
}
|
||||
|
||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||
if (friend != null) {
|
||||
avatarModel = ContactAvatarModel(friend)
|
||||
|
|
@ -99,6 +111,7 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
|
|||
fakeFriend.address = address
|
||||
avatarModel = ContactAvatarModel(fakeFriend)
|
||||
}
|
||||
groupAvatarModel = GroupAvatarModel(friends)
|
||||
|
||||
isMuted.postValue(chatRoom.muted)
|
||||
isEphemeral.postValue(chatRoom.isEphemeralEnabled)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ import org.linphone.LinphoneApplication.Companion.coreContext
|
|||
import org.linphone.core.Address
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.chat.model.EventLogModel
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
import org.linphone.ui.main.contacts.model.GroupAvatarModel
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class ConversationViewModel @UiThread constructor() : ViewModel() {
|
||||
|
|
@ -41,6 +43,8 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val avatarModel = MutableLiveData<ContactAvatarModel>()
|
||||
|
||||
val groupAvatarModel = MutableLiveData<GroupAvatarModel>()
|
||||
|
||||
val events = MutableLiveData<ArrayList<EventLogModel>>()
|
||||
|
||||
val isGroup = MutableLiveData<Boolean>()
|
||||
|
|
@ -106,14 +110,24 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
)
|
||||
subject.postValue(chatRoom.subject)
|
||||
|
||||
val friends = arrayListOf<Friend>()
|
||||
val address = if (chatRoom.hasCapability(ChatRoom.Capabilities.Basic.toInt())) {
|
||||
chatRoom.peerAddress
|
||||
} else {
|
||||
for (participant in chatRoom.participants) {
|
||||
val friend = coreContext.contactsManager.findContactByAddress(participant.address)
|
||||
if (friend != null) {
|
||||
friends.add(friend)
|
||||
}
|
||||
}
|
||||
|
||||
val firstParticipant = chatRoom.participants.firstOrNull()
|
||||
firstParticipant?.address ?: chatRoom.peerAddress
|
||||
}
|
||||
|
||||
avatarModel.postValue(getAvatarModelForAddress(address))
|
||||
val avatar = getAvatarModelForAddress(address)
|
||||
avatarModel.postValue(avatar)
|
||||
val groupAvatar = GroupAvatarModel(friends)
|
||||
groupAvatarModel.postValue(groupAvatar)
|
||||
|
||||
val eventsList = arrayListOf<EventLogModel>()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ import org.linphone.core.ChatRoom
|
|||
import org.linphone.core.ConsolidatedPresence
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
import org.linphone.ui.main.contacts.model.GroupAvatarModel
|
||||
import org.linphone.ui.main.model.AccountModel
|
||||
|
||||
/**
|
||||
|
|
@ -311,6 +312,44 @@ fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) {
|
|||
onSuccess = { _, _ ->
|
||||
// If loading is successful, remove initials otherwise image won't be visible
|
||||
avatarInitials = ""
|
||||
},
|
||||
onError = { _, result ->
|
||||
Log.e("[Contact Avatar Model] Can't load data: ${result.throwable}")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@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}")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
android:layout_marginStart="5dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/shape_circle_light_blue_background"
|
||||
android:visibility="@{viewModel.isGroup ? View.GONE : View.VISIBLE}"
|
||||
contactAvatar="@{viewModel.avatarModel}"
|
||||
app:avatarViewPlaceholder="@drawable/user_circle"
|
||||
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
|
||||
|
|
@ -67,10 +68,38 @@
|
|||
android:layout_width="@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:visibility="@{viewModel.avatarModel.trust == SecurityLevel.Encrypted || viewModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{!viewModel.isGroup && viewModel.avatarModel.trust == SecurityLevel.Encrypted || viewModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintStart_toStartOf="@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 && 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
|
||||
style="@style/default_text_style"
|
||||
android:id="@+id/title"
|
||||
|
|
@ -85,7 +114,7 @@
|
|||
android:textColor="@color/gray_main2_600"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintEnd_toStartOf="@id/call"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintStart_toEndOf="@id/group_avatar"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/shape_circle_light_blue_background"
|
||||
contactAvatar="@{model.avatarModel}"
|
||||
android:visibility="@{model.isGroup ? View.GONE : View.VISIBLE}"
|
||||
app:avatarViewPlaceholder="@drawable/user_circle"
|
||||
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
|
||||
app:avatarViewInitialsTextColor="@color/gray_main2_600"
|
||||
|
|
@ -57,7 +58,7 @@
|
|||
android:background="@drawable/led_background"
|
||||
android:padding="@dimen/avatar_presence_badge_padding"
|
||||
app:presenceIcon="@{model.avatarModel.presenceStatus}"
|
||||
android:visibility="@{model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{model.isGroup || model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||
|
||||
|
|
@ -66,10 +67,38 @@
|
|||
android:layout_width="@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:visibility="@{model.avatarModel.trust == SecurityLevel.Encrypted || model.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{!model.isGroup && model.avatarModel.trust == SecurityLevel.Encrypted || model.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintStart_toStartOf="@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 && 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
|
||||
android:id="@+id/right_border"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -91,7 +120,7 @@
|
|||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_main2_800"
|
||||
android:textStyle="@{model.unreadMessageCount > 0 ? Typeface.BOLD : Typeface.NORMAL}"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintStart_toEndOf="@id/group_avatar"
|
||||
app:layout_constraintEnd_toStartOf="@id/right_border"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/last_message_or_composing"/>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue