From f2b85f64737e4c4dea72ec72e62503f7c75d9657 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 2 May 2022 12:41:54 +0200 Subject: [PATCH] Improved way of displaying contact's avatar or initials --- .../chat/data/GroupInfoParticipantData.kt | 22 +++- .../linphone/contact/BigContactAvatarView.kt | 74 ------------ .../contact/ContactAvatarGenerator.kt | 113 ++++++++++++++++++ .../org/linphone/contact/ContactAvatarView.kt | 83 ------------- .../linphone/contact/ContactDataInterface.kt | 18 +-- .../java/org/linphone/core/CorePreferences.kt | 9 -- .../org/linphone/utils/DataBindingUtils.kt | 106 ++++++++++++---- .../layout/chat_message_attachment_cell.xml | 4 +- .../res/layout/chat_message_content_cell.xml | 4 +- .../res/layout/chat_message_list_cell.xml | 13 +- .../chat_message_reply_content_cell.xml | 4 +- ...hat_message_reply_preview_content_cell.xml | 4 +- .../layout/chat_room_devices_group_cell.xml | 34 ++++-- .../chat_room_group_info_participant_cell.xml | 47 ++++++-- .../chat_room_imdn_participant_cell.xml | 25 ++-- .../main/res/layout/chat_room_list_cell.xml | 47 +++++--- ...conference_scheduling_participant_cell.xml | 38 ++++-- app/src/main/res/layout/contact_avatar.xml | 111 ----------------- .../main/res/layout/contact_avatar_big.xml | 87 -------------- .../res/layout/contact_detail_fragment.xml | 11 +- .../res/layout/contact_editor_fragment.xml | 24 ++-- app/src/main/res/layout/contact_list_cell.xml | 17 ++- .../res/layout/contact_selection_cell.xml | 44 ++++--- .../res/layout/file_image_viewer_fragment.xml | 2 +- .../res/layout/history_detail_fragment.xml | 11 +- app/src/main/res/layout/history_list_cell.xml | 16 ++- .../main/res/layout/side_menu_fragment.xml | 2 +- .../layout/voip_call_incoming_fragment.xml | 11 +- .../layout/voip_call_outgoing_fragment.xml | 33 +++-- app/src/main/res/layout/voip_calls_cell.xml | 17 ++- .../layout/voip_conference_active_speaker.xml | 11 +- .../voip_conference_participant_cell.xml | 17 ++- ...cipant_remote_active_speaker_miniature.xml | 8 +- ...nference_participant_remote_audio_only.xml | 6 +- ...oip_conference_participant_remote_grid.xml | 13 +- .../main/res/layout/voip_contact_avatar.xml | 66 ---------- .../res/layout/voip_contact_avatar_alt.xml | 70 ----------- .../res/layout/voip_single_call_fragment.xml | 12 +- app/src/main/res/values/dimen.xml | 6 +- 39 files changed, 504 insertions(+), 736 deletions(-) delete mode 100644 app/src/main/java/org/linphone/contact/BigContactAvatarView.kt create mode 100644 app/src/main/java/org/linphone/contact/ContactAvatarGenerator.kt delete mode 100644 app/src/main/java/org/linphone/contact/ContactAvatarView.kt delete mode 100644 app/src/main/res/layout/contact_avatar.xml delete mode 100644 app/src/main/res/layout/contact_avatar_big.xml delete mode 100644 app/src/main/res/layout/voip_contact_avatar.xml delete mode 100644 app/src/main/res/layout/voip_contact_avatar_alt.xml diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/GroupInfoParticipantData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/GroupInfoParticipantData.kt index 65db33912..ffd9248a8 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/GroupInfoParticipantData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/GroupInfoParticipantData.kt @@ -20,8 +20,10 @@ package org.linphone.activities.main.chat.data import androidx.lifecycle.MutableLiveData +import org.linphone.R import org.linphone.activities.main.chat.GroupChatRoomMember import org.linphone.contact.GenericContactData +import org.linphone.core.ChatRoomSecurityLevel import org.linphone.utils.LinphoneUtils class GroupInfoParticipantData(val participant: GroupChatRoomMember) : GenericContactData(participant.address) { @@ -34,6 +36,22 @@ class GroupInfoParticipantData(val participant: GroupChatRoomMember) : GenericCo // A participant not yet added to a group can't be set admin at the same time it's added val canBeSetAdmin = MutableLiveData() + val securityLevelIcon: Int by lazy { + when (participant.securityLevel) { + ChatRoomSecurityLevel.Safe -> R.drawable.security_2_indicator + ChatRoomSecurityLevel.Encrypted -> R.drawable.security_1_indicator + else -> R.drawable.security_alert_indicator + } + } + + val securityLevelContentDescription: Int by lazy { + when (participant.securityLevel) { + ChatRoomSecurityLevel.Safe -> R.string.content_description_security_level_safe + ChatRoomSecurityLevel.Encrypted -> R.string.content_description_security_level_encrypted + else -> R.string.content_description_security_level_unsafe + } + } + init { securityLevel.value = participant.securityLevel isAdmin.value = participant.isAdmin @@ -41,10 +59,6 @@ class GroupInfoParticipantData(val participant: GroupChatRoomMember) : GenericCo canBeSetAdmin.value = participant.canBeSetAdmin } - override fun destroy() { - super.destroy() - } - fun setAdmin() { isAdmin.value = true participant.isAdmin = true diff --git a/app/src/main/java/org/linphone/contact/BigContactAvatarView.kt b/app/src/main/java/org/linphone/contact/BigContactAvatarView.kt deleted file mode 100644 index 8b0041585..000000000 --- a/app/src/main/java/org/linphone/contact/BigContactAvatarView.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2010-2020 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 . - */ -package org.linphone.contact - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.View -import android.widget.LinearLayout -import androidx.databinding.DataBindingUtil -import org.linphone.LinphoneApplication.Companion.corePreferences -import org.linphone.R -import org.linphone.databinding.ContactAvatarBigBinding -import org.linphone.utils.AppUtils - -class BigContactAvatarView : LinearLayout { - lateinit var binding: ContactAvatarBigBinding - - constructor(context: Context) : super(context) { - init(context) - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - init(context) - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - init(context) - } - - fun init(context: Context) { - binding = DataBindingUtil.inflate( - LayoutInflater.from(context), R.layout.contact_avatar_big, this, true - ) - } - - fun setViewModel(viewModel: ContactDataInterface?) { - if (viewModel == null) { - binding.root.visibility = View.GONE - return - } - binding.root.visibility = View.VISIBLE - - val contact = viewModel.contact.value - val initials = if (contact != null) { - AppUtils.getInitials(contact.name ?: "") - } else { - AppUtils.getInitials(viewModel.displayName.value ?: "") - } - - binding.initials = initials - binding.generatedAvatarVisibility = initials.isNotEmpty() && initials != "+" - binding.imagePath = contact?.getPictureUri() - binding.thumbnailPath = contact?.getThumbnailUri() - binding.borderVisibility = corePreferences.showBorderOnBigContactAvatar - } -} diff --git a/app/src/main/java/org/linphone/contact/ContactAvatarGenerator.kt b/app/src/main/java/org/linphone/contact/ContactAvatarGenerator.kt new file mode 100644 index 000000000..2cb3b17b9 --- /dev/null +++ b/app/src/main/java/org/linphone/contact/ContactAvatarGenerator.kt @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010-2022 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 . + */ +package org.linphone.contact + +import android.content.Context +import android.graphics.* +import android.graphics.drawable.BitmapDrawable +import android.text.TextPaint +import android.util.TypedValue +import androidx.core.content.ContextCompat +import org.linphone.R +import org.linphone.utils.AppUtils + +class ContactAvatarGenerator(private val context: Context) { + private var textSize: Float + private var textColor: Int + private var avatarSize: Int + private var name = " " + private var backgroundColor: Int + + init { + val theme = context.theme + + val backgroundColorTypedValue = TypedValue() + theme.resolveAttribute(R.attr.primaryTextColor, backgroundColorTypedValue, true) + backgroundColor = ContextCompat.getColor(context, backgroundColorTypedValue.resourceId) + + val textColorTypedValue = TypedValue() + theme.resolveAttribute(R.attr.secondaryTextColor, textColorTypedValue, true) + textColor = ContextCompat.getColor(context, textColorTypedValue.resourceId) + + textSize = AppUtils.getDimension(R.dimen.contact_avatar_text_size) + + avatarSize = AppUtils.getDimension(R.dimen.contact_avatar_size).toInt() + } + + fun setTextSize(size: Float) = apply { + textSize = size + } + + fun setTextColorResource(resource: Int) = apply { + textColor = ContextCompat.getColor(context, resource) + } + + fun setAvatarSize(size: Int) = apply { + avatarSize = size + } + + fun setLabel(label: String) = apply { + name = label + } + + fun setBackgroundColorAttribute(attribute: Int) = apply { + val theme = context.theme + val backgroundColorTypedValue = TypedValue() + theme.resolveAttribute(attribute, backgroundColorTypedValue, true) + backgroundColor = ContextCompat.getColor(context, backgroundColorTypedValue.resourceId) + } + + fun build(): BitmapDrawable { + val label = AppUtils.getInitials(name) + val textPainter = getTextPainter() + val painter = getPainter() + + val bitmap = Bitmap.createBitmap(avatarSize, avatarSize, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + val areaRect = Rect(0, 0, avatarSize, avatarSize) + val bounds = RectF(areaRect) + bounds.right = textPainter.measureText(label, 0, label.length) + bounds.bottom = textPainter.descent() - textPainter.ascent() + bounds.left += (areaRect.width() - bounds.right) / 2.0f + bounds.top += (areaRect.height() - bounds.bottom) / 2.0f + + val halfSize = (avatarSize / 2).toFloat() + canvas.drawCircle(halfSize, halfSize, halfSize, painter) + canvas.drawText(label, bounds.left, bounds.top - textPainter.ascent(), textPainter) + + return BitmapDrawable(context.resources, bitmap) + } + + private fun getTextPainter(): TextPaint { + val textPainter = TextPaint() + textPainter.isAntiAlias = true + textPainter.textSize = textSize + textPainter.color = textColor + textPainter.typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) + return textPainter + } + + private fun getPainter(): Paint { + val painter = Paint() + painter.isAntiAlias = true + painter.color = backgroundColor + return painter + } +} diff --git a/app/src/main/java/org/linphone/contact/ContactAvatarView.kt b/app/src/main/java/org/linphone/contact/ContactAvatarView.kt deleted file mode 100644 index 1360f4f25..000000000 --- a/app/src/main/java/org/linphone/contact/ContactAvatarView.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2010-2020 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 . - */ -package org.linphone.contact - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.LinearLayout -import androidx.databinding.DataBindingUtil -import org.linphone.LinphoneApplication.Companion.corePreferences -import org.linphone.R -import org.linphone.core.ChatRoomSecurityLevel -import org.linphone.databinding.ContactAvatarBinding -import org.linphone.utils.AppUtils - -class ContactAvatarView : LinearLayout { - lateinit var binding: ContactAvatarBinding - - constructor(context: Context) : super(context) { - init(context) - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - init(context) - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - init(context) - } - - fun init(context: Context) { - binding = DataBindingUtil.inflate( - LayoutInflater.from(context), R.layout.contact_avatar, this, true - ) - } - - fun setData(data: ContactDataInterface?) { - // From Crashlytics it seems this function can be called with null parameter... - data ?: return - - val contact = data.contact.value - val initials = if (contact != null) { - AppUtils.getInitials(contact.name ?: "") - } else { - AppUtils.getInitials(data.displayName.value ?: "") - } - - binding.initials = initials - binding.generatedAvatarVisibility = initials.isNotEmpty() && initials != "+" - binding.groupChatAvatarVisibility = data.showGroupChatAvatar - - binding.imagePath = contact?.getThumbnailUri() - binding.borderVisibility = corePreferences.showBorderOnContactAvatar - - binding.securityIcon = when (data.securityLevel.value) { - ChatRoomSecurityLevel.Safe -> R.drawable.security_2_indicator - ChatRoomSecurityLevel.Encrypted -> R.drawable.security_1_indicator - else -> R.drawable.security_alert_indicator - } - binding.securityContentDescription = when (data.securityLevel.value) { - ChatRoomSecurityLevel.Safe -> R.string.content_description_security_level_safe - ChatRoomSecurityLevel.Encrypted -> R.string.content_description_security_level_encrypted - else -> R.string.content_description_security_level_unsafe - } - } -} diff --git a/app/src/main/java/org/linphone/contact/ContactDataInterface.kt b/app/src/main/java/org/linphone/contact/ContactDataInterface.kt index 9edbb78a6..879f398ee 100644 --- a/app/src/main/java/org/linphone/contact/ContactDataInterface.kt +++ b/app/src/main/java/org/linphone/contact/ContactDataInterface.kt @@ -38,6 +38,12 @@ interface ContactDataInterface { val showGroupChatAvatar: Boolean get() = false + + val thumbnailUri: Uri? + get() = contact.value?.getThumbnailUri() + + val pictureUri: Uri? + get() = contact.value?.getPictureUri() } open class GenericContactData(private val sipAddress: Address) : ContactDataInterface { @@ -48,12 +54,6 @@ open class GenericContactData(private val sipAddress: Address) : ContactDataInte val initials = MutableLiveData() val displayInitials = MutableLiveData() - val thumbnailUri: Uri? - get() = contact.value?.getThumbnailUri() - - val pictureUri: Uri? - get() = contact.value?.getPictureUri() - private val contactsUpdatedListener = object : ContactsUpdatedListenerStub() { override fun onContactUpdated(friend: Friend) { contactLookup() @@ -90,12 +90,6 @@ abstract class GenericContactViewModel(private val sipAddress: Address) : Messag final override val displayName: MutableLiveData = MutableLiveData() final override val securityLevel: MutableLiveData = MutableLiveData() - val thumbnailUri: Uri? - get() = contact.value?.getThumbnailUri() - - val pictureUri: Uri? - get() = contact.value?.getPictureUri() - private val contactsUpdatedListener = object : ContactsUpdatedListenerStub() { override fun onContactUpdated(friend: Friend) { contactLookup() diff --git a/app/src/main/java/org/linphone/core/CorePreferences.kt b/app/src/main/java/org/linphone/core/CorePreferences.kt index 6b2e2e945..dd95ff748 100644 --- a/app/src/main/java/org/linphone/core/CorePreferences.kt +++ b/app/src/main/java/org/linphone/core/CorePreferences.kt @@ -402,18 +402,9 @@ class CorePreferences constructor(private val context: Context) { /* UI related */ - val hideContactsWithoutPresence: Boolean - get() = config.getBool("app", "hide_contacts_without_presence", false) - val contactOrganizationVisible: Boolean get() = config.getBool("app", "display_contact_organization", true) - val showBorderOnContactAvatar: Boolean - get() = config.getBool("app", "show_border_on_contact_avatar", false) - - val showBorderOnBigContactAvatar: Boolean - get() = config.getBool("app", "show_border_on_big_contact_avatar", true) - private val darkModeAllowed: Boolean get() = config.getBool("app", "dark_mode_allowed", true) diff --git a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt index 3ee1e9d2e..7142d10b4 100644 --- a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt +++ b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt @@ -23,7 +23,6 @@ import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.graphics.Bitmap -import android.net.Uri import android.text.Editable import android.text.TextWatcher import android.util.Patterns @@ -44,13 +43,15 @@ import coil.request.videoFrameMillis import coil.transform.CircleCropTransformation import com.google.android.material.switchmaterial.SwitchMaterial import org.linphone.BR +import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.activities.GenericActivity import org.linphone.activities.main.settings.SettingListener import org.linphone.activities.voip.data.ConferenceParticipantDeviceData import org.linphone.activities.voip.views.HorizontalScrollDotsView -import org.linphone.contact.ContactAvatarView +import org.linphone.contact.ContactAvatarGenerator +import org.linphone.contact.ContactDataInterface import org.linphone.core.tools.Log import org.linphone.views.VoiceRecordProgressBar @@ -305,19 +306,19 @@ fun setImageViewScaleType(imageView: ImageView, scaleType: ImageView.ScaleType) imageView.scaleType = scaleType } -@BindingAdapter("glideRoundPath") -fun loadRoundImageWithGlide(imageView: ImageView, path: String?) { +@BindingAdapter("coilRounded") +fun loadRoundImageWithCoil(imageView: ImageView, path: String?) { if (path != null && path.isNotEmpty() && FileUtils.isExtensionImage(path)) { imageView.load(path) { transformations(CircleCropTransformation()) } } else { - Log.w("[Data Binding] [Glide] Can't load $path") + Log.w("[Data Binding] [Coil] Can't load $path") } } -@BindingAdapter("glidePath") -fun loadImageWithGlide(imageView: ImageView, path: String?) { +@BindingAdapter("coil") +fun loadImageWithCoil(imageView: ImageView, path: String?) { if (path != null && path.isNotEmpty() && FileUtils.isExtensionImage(path)) { if (corePreferences.vfsEnabled && path.endsWith(FileUtils.VFS_PLAIN_FILE_EXTENSION)) { imageView.load(path) { @@ -327,17 +328,86 @@ fun loadImageWithGlide(imageView: ImageView, path: String?) { imageView.load(path) } } else { - Log.w("[Data Binding] [Glide] Can't load $path") + Log.w("[Data Binding] [Coil] Can't load $path") } } -@BindingAdapter("glideAvatar") -fun loadAvatarWithGlide(imageView: ImageView, path: Uri?) { - loadAvatarWithGlide(imageView, path?.toString()) +private fun loadContactPictureWithCoil( + imageView: ImageView, + contact: ContactDataInterface?, + useThumbnail: Boolean, + size: Int = 0, + textSize: Int = 0, + color: Int = 0, + textColor: Int = 0 +) { + if (contact != null) { + val displayName = contact.displayName.value.orEmpty() + val source = if (useThumbnail) contact.thumbnailUri else contact.pictureUri + imageView.load(source) { + transformations(CircleCropTransformation()) + error( + if (contact.showGroupChatAvatar) { + coreContext.contactsManager.groupAvatar.loadDrawable(imageView.context) + } else if (displayName.isEmpty() || displayName == "+") { + coreContext.contactsManager.contactAvatar.loadDrawable(imageView.context) + } else { + val builder = ContactAvatarGenerator(imageView.context) + builder.setLabel(displayName) + if (size > 0) { + builder.setAvatarSize(AppUtils.getDimension(size).toInt()) + } + if (textSize > 0) { + builder.setTextSize(AppUtils.getDimension(textSize)) + } + if (color > 0) { + builder.setBackgroundColorAttribute(color) + } + if (textColor > 0) { + builder.setTextColorResource(textColor) + } + builder.build() + } + ) + } + } else { + imageView.load(R.drawable.icon_single_contact_avatar) + } } -@BindingAdapter("glideAvatar") -fun loadAvatarWithGlide(imageView: ImageView, path: String?) { +@BindingAdapter("coilContact") +fun loadContactPictureWithCoil(imageView: ImageView, contact: ContactDataInterface?) { + loadContactPictureWithCoil(imageView, contact, true) +} + +@BindingAdapter("coilContactBig") +fun loadBigContactPictureWithCoil(imageView: ImageView, contact: ContactDataInterface?) { + loadContactPictureWithCoil( + imageView, contact, true, + R.dimen.contact_avatar_big_size, R.dimen.contact_avatar_text_big_size + ) +} + +@BindingAdapter("coilVoipContactAlt") +fun loadVoipContactPictureWithCoilAlt(imageView: ImageView, contact: ContactDataInterface?) { + loadContactPictureWithCoil( + imageView, contact, false, + R.dimen.voip_contact_avatar_max_size, R.dimen.voip_contact_avatar_text_size, + R.attr.voipParticipantBackgroundColor, R.color.white_color + ) +} + +@BindingAdapter("coilVoipContact") +fun loadVoipContactPictureWithCoil(imageView: ImageView, contact: ContactDataInterface?) { + loadContactPictureWithCoil( + imageView, contact, false, + R.dimen.voip_contact_avatar_max_size, R.dimen.voip_contact_avatar_text_size, + R.attr.voipBackgroundColor, R.color.white_color + ) +} + +@BindingAdapter("coilGoneIfError") +fun loadAvatarWithCoil(imageView: ImageView, path: String?) { if (path != null) { imageView.visibility = View.VISIBLE imageView.load(path) { @@ -366,16 +436,6 @@ fun loadVideoPreview(imageView: ImageView, path: String?) { } } -@BindingAdapter("showSecurityLevel") -fun ContactAvatarView.setShowAvatarSecurityLevel(visible: Boolean) { - this.binding.securityBadgeVisibility = visible -} - -@BindingAdapter("showLimeCapability") -fun ContactAvatarView.setShowLimeCapability(limeCapability: Boolean) { - this.binding.showLimeCapability = limeCapability -} - @BindingAdapter("assistantPhoneNumberValidation") fun addPhoneNumberEditTextValidation(editText: EditText, enabled: Boolean) { if (!enabled) return diff --git a/app/src/main/res/layout/chat_message_attachment_cell.xml b/app/src/main/res/layout/chat_message_attachment_cell.xml index 69101b9ca..f355f62ba 100644 --- a/app/src/main/res/layout/chat_message_attachment_cell.xml +++ b/app/src/main/res/layout/chat_message_attachment_cell.xml @@ -24,7 +24,7 @@ android:layout_alignParentLeft="true" android:adjustViewBounds="true" android:scaleType="centerCrop" - app:glidePath="@{data.path}"/> + coil="@{data.path}"/> + coilVideoPreview="@{data.path}"/> @@ -39,7 +39,7 @@ android:layout_height="wrap_content" android:maxHeight="@dimen/chat_message_bubble_image_height_big" android:layout_size="@{data.alone ? 0f : @dimen/chat_message_bubble_file_size}" - app:coilVideoPreview="@{data.filePath}" + coilVideoPreview="@{data.filePath}" android:visibility="@{!data.downloadable && data.video ? View.VISIBLE : View.GONE}" android:scaleType="@{data.alone ? ScaleType.FIT_CENTER : ScaleType.CENTER_CROP}" android:adjustViewBounds="true" /> diff --git a/app/src/main/res/layout/chat_message_list_cell.xml b/app/src/main/res/layout/chat_message_list_cell.xml index 0e7374f0d..fc4570fb2 100644 --- a/app/src/main/res/layout/chat_message_list_cell.xml +++ b/app/src/main/res/layout/chat_message_list_cell.xml @@ -60,17 +60,18 @@ android:src="@{data.imdnIcon, default=@drawable/chat_delivered}" android:visibility="@{data.chatMessage.outgoing ? (data.showImdn ? View.VISIBLE : View.INVISIBLE) : View.INVISIBLE}" /> - + android:visibility="@{data.chatMessage.outgoing || selectionListViewModel.isEditionEnabled ? View.GONE : (data.hideAvatar ? View.INVISIBLE : View.VISIBLE)}" /> @@ -32,7 +32,7 @@ android:layout_height="wrap_content" android:maxHeight="@dimen/chat_message_bubble_image_height_small" android:layout_size="@{data.alone ? 0f : @dimen/chat_message_small_bubble_file_size}" - app:coilVideoPreview="@{data.filePath}" + coilVideoPreview="@{data.filePath}" android:visibility="@{data.video ? View.VISIBLE : View.GONE}" android:scaleType="@{ScaleType.CENTER_CROP}" android:adjustViewBounds="true" /> diff --git a/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml b/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml index d083d517a..c0edc54cd 100644 --- a/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml +++ b/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml @@ -19,7 +19,7 @@ android:layout_width="@dimen/chat_message_small_bubble_file_size" android:layout_height="@dimen/chat_message_small_bubble_file_size" android:layout_margin="5dp" - app:glidePath="@{data.filePath}" + coil="@{data.filePath}" android:visibility="@{data.image ? View.VISIBLE : View.GONE}" android:scaleType="@{ScaleType.CENTER_CROP}" android:adjustViewBounds="true" /> @@ -29,7 +29,7 @@ android:layout_width="@dimen/chat_message_small_bubble_file_size" android:layout_height="@dimen/chat_message_small_bubble_file_size" android:layout_margin="5dp" - app:coilVideoPreview="@{data.filePath}" + coilVideoPreview="@{data.filePath}" android:visibility="@{data.video ? View.VISIBLE : View.GONE}" android:scaleType="@{ScaleType.CENTER_CROP}" android:adjustViewBounds="true" /> diff --git a/app/src/main/res/layout/chat_room_devices_group_cell.xml b/app/src/main/res/layout/chat_room_devices_group_cell.xml index 634f984c0..469431383 100644 --- a/app/src/main/res/layout/chat_room_devices_group_cell.xml +++ b/app/src/main/res/layout/chat_room_devices_group_cell.xml @@ -1,7 +1,6 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -23,16 +22,29 @@ android:layout_marginRight="10dp" android:gravity="center_vertical"> - + android:layout_width="45dp" + android:layout_height="wrap_content" + android:layout_centerVertical="true"> + + + + + + - + @@ -20,18 +18,41 @@ + android:layout_margin="5dp"> - + android:layout_width="45dp" + android:layout_height="wrap_content" + android:layout_centerVertical="true"> + + + + + + + + - + @@ -16,13 +14,14 @@ android:layout_margin="5dp" android:gravity="center_vertical"> - + android:layout_width="@dimen/contact_avatar_size" + android:layout_height="@dimen/contact_avatar_size" + android:layout_marginRight="10dp" + coilContact="@{data}" + android:contentDescription="@null" + android:layout_centerVertical="true"/> + android:singleLine="true" + android:text="@{data.contact.name ?? data.displayName}" /> + android:singleLine="true" + android:text="@{data.sipUri}" /> diff --git a/app/src/main/res/layout/chat_room_list_cell.xml b/app/src/main/res/layout/chat_room_list_cell.xml index 278a5d84b..05835b673 100644 --- a/app/src/main/res/layout/chat_room_list_cell.xml +++ b/app/src/main/res/layout/chat_room_list_cell.xml @@ -1,7 +1,5 @@ - + @@ -41,27 +39,42 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"> - + android:layout_width="45dp" + android:layout_height="wrap_content"> + + + + + + + android:layout_marginTop="5dp" + android:paddingRight="10dp" + android:singleLine="true" + android:text="@{viewModel.lastUpdate, default=`12:03`}" + android:textColor="?attr/accentColor" + android:textSize="16sp" /> @@ -69,7 +82,7 @@ android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:paddingLeft="10dp"> + android:paddingLeft="5dp"> - + - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/contact_avatar_big.xml b/app/src/main/res/layout/contact_avatar_big.xml deleted file mode 100644 index 57627de5b..000000000 --- a/app/src/main/res/layout/contact_avatar_big.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/contact_detail_fragment.xml b/app/src/main/res/layout/contact_detail_fragment.xml index 78d08ad9a..3709961ac 100644 --- a/app/src/main/res/layout/contact_detail_fragment.xml +++ b/app/src/main/res/layout/contact_detail_fragment.xml @@ -86,13 +86,12 @@ android:orientation="vertical" android:paddingTop="20dp"> - + android:layout_width="@dimen/contact_avatar_big_size" + android:layout_height="@dimen/contact_avatar_big_size" + coilContactBig="@{viewModel}" + android:contentDescription="@null" /> + xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -75,25 +74,22 @@ android:layout_marginRight="10dp"> + android:layout_width="@dimen/contact_avatar_big_size" + android:layout_height="@dimen/contact_avatar_big_size"> - + android:layout_height="match_parent" + coilContactBig="@{viewModel}" + android:contentDescription="@null" /> + coilGoneIfError="@{viewModel.tempPicturePath}"/> diff --git a/app/src/main/res/layout/contact_list_cell.xml b/app/src/main/res/layout/contact_list_cell.xml index 2fac68483..74181a0c6 100644 --- a/app/src/main/res/layout/contact_list_cell.xml +++ b/app/src/main/res/layout/contact_list_cell.xml @@ -1,7 +1,5 @@ - + @@ -34,13 +32,14 @@ android:background="?attr/backgroundColor" android:gravity="center_vertical"> - + android:layout_width="@dimen/contact_avatar_size" + android:layout_height="@dimen/contact_avatar_size" + coilContact="@{viewModel}" + android:layout_marginRight="10dp" + android:layout_centerVertical="true" + android:contentDescription="@null" /> - + @@ -26,14 +24,30 @@ android:orientation="vertical" android:padding="5dp"> - + android:layout_width="45dp" + android:layout_height="wrap_content" + android:layout_centerVertical="true"> + + + + + + + android:lines="1" + android:text="@{data.contact.name ?? data.displayName}" /> + android:lines="1" + android:text="@{data.sipUri}" /> diff --git a/app/src/main/res/layout/file_image_viewer_fragment.xml b/app/src/main/res/layout/file_image_viewer_fragment.xml index 85d012d13..d8d896db6 100644 --- a/app/src/main/res/layout/file_image_viewer_fragment.xml +++ b/app/src/main/res/layout/file_image_viewer_fragment.xml @@ -33,7 +33,7 @@ android:layout_height="match_parent" android:adjustViewBounds="true" android:scaleType="fitCenter" - glidePath="@{viewModel.filePath}"/> + coil="@{viewModel.filePath}"/> diff --git a/app/src/main/res/layout/history_detail_fragment.xml b/app/src/main/res/layout/history_detail_fragment.xml index ea4e18c00..c2ef639e7 100644 --- a/app/src/main/res/layout/history_detail_fragment.xml +++ b/app/src/main/res/layout/history_detail_fragment.xml @@ -87,14 +87,13 @@ android:paddingTop="10dp" android:paddingBottom="5dp"> - + android:layout_width="@dimen/contact_avatar_big_size" + android:layout_height="@dimen/contact_avatar_big_size" + coilContactBig="@{viewModel}" + android:contentDescription="@null" /> - + @@ -83,14 +81,14 @@ android:layout_toLeftOf="@id/right" android:gravity="center_vertical"> - + android:layout_marginRight="10dp" + android:contentDescription="@null" /> - + app:layout_constraintVertical_chainStyle="packed" + app:layout_constraintWidth_max="@dimen/voip_contact_avatar_max_size" /> - + app:layout_constraintVertical_chainStyle="packed" + app:layout_constraintWidth_max="@dimen/voip_contact_avatar_max_size" /> + + + app:layout_constraintTop_toBottomOf="@id/conference_avatar" /> - + @@ -27,14 +25,15 @@ android:layout_height="wrap_content" android:layout_marginRight="10dp"> - + android:layout_marginRight="10dp" + android:layout_centerVertical="true"/> - + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_max="@dimen/voip_contact_avatar_max_size" /> - + @@ -16,14 +14,15 @@ android:layout_margin="5dp" android:gravity="center_vertical"> - + android:layout_marginEnd="10dp" + android:layout_centerVertical="true"/> - - - + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_max="@dimen/voip_contact_avatar_max_size" /> - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/voip_contact_avatar_alt.xml b/app/src/main/res/layout/voip_contact_avatar_alt.xml deleted file mode 100644 index 0dc480e6a..000000000 --- a/app/src/main/res/layout/voip_contact_avatar_alt.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/voip_single_call_fragment.xml b/app/src/main/res/layout/voip_single_call_fragment.xml index 7e00ae5da..82be9e64c 100644 --- a/app/src/main/res/layout/voip_single_call_fragment.xml +++ b/app/src/main/res/layout/voip_single_call_fragment.xml @@ -108,17 +108,19 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/call_header_barrier" /> - + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_max="@dimen/voip_contact_avatar_max_size" /> 5dp 5dp 35dp + 21sp + 100dp + 60sp 20dp 3dp 60dp @@ -59,7 +62,8 @@ 30dp 25dp 137dp - 200dp + 200dp + 80sp 60dp 80dp 40dp