Using recyclerview to improve delivery status list performances

This commit is contained in:
Sylvain Berfini 2023-10-20 08:35:33 +02:00
parent b9e4fcf1a6
commit 76ba9e5e35
5 changed files with 86 additions and 13 deletions

View file

@ -0,0 +1,65 @@
package org.linphone.ui.main.chat.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.UiThread
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.linphone.R
import org.linphone.databinding.ChatMessageDeliveryListCellBinding
import org.linphone.ui.main.chat.model.ChatMessageParticipantDeliveryModel
class ChatMessageDeliveryAdapter(
private val viewLifecycleOwner: LifecycleOwner
) : ListAdapter<ChatMessageParticipantDeliveryModel, RecyclerView.ViewHolder>(
ChatDeliveryDiffCallback()
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val binding: ChatMessageDeliveryListCellBinding = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.chat_message_delivery_list_cell,
parent,
false
)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ViewHolder).bind(getItem(position))
}
inner class ViewHolder(
val binding: ChatMessageDeliveryListCellBinding
) : RecyclerView.ViewHolder(binding.root) {
@UiThread
fun bind(deliveryModel: ChatMessageParticipantDeliveryModel) {
with(binding) {
model = deliveryModel
lifecycleOwner = viewLifecycleOwner
executePendingBindings()
}
}
}
private class ChatDeliveryDiffCallback : DiffUtil.ItemCallback<ChatMessageParticipantDeliveryModel>() {
override fun areItemsTheSame(
oldItem: ChatMessageParticipantDeliveryModel,
newItem: ChatMessageParticipantDeliveryModel
): Boolean {
return oldItem.sipUri == newItem.sipUri
}
override fun areContentsTheSame(
oldItem: ChatMessageParticipantDeliveryModel,
newItem: ChatMessageParticipantDeliveryModel
): Boolean {
return oldItem.time == newItem.time
}
}
}

View file

@ -52,6 +52,7 @@ import org.linphone.core.ChatMessage
import org.linphone.core.tools.Log
import org.linphone.databinding.ChatConversationFragmentBinding
import org.linphone.databinding.ChatConversationLongPressMenuBinding
import org.linphone.ui.main.chat.adapter.ChatMessageDeliveryAdapter
import org.linphone.ui.main.chat.adapter.ConversationEventAdapter
import org.linphone.ui.main.chat.model.ChatMessageDeliveryModel
import org.linphone.ui.main.chat.model.ChatMessageModel
@ -78,6 +79,8 @@ class ConversationFragment : GenericFragment() {
private lateinit var adapter: ConversationEventAdapter
private lateinit var deliveryAdapter: ChatMessageDeliveryAdapter
private val pickMedia = registerForActivityResult(
ActivityResultContracts.PickMultipleVisualMedia()
) { list ->
@ -151,9 +154,16 @@ class ConversationFragment : GenericFragment() {
binding.eventsList.setHasFixedSize(true)
binding.eventsList.adapter = adapter
deliveryAdapter = ChatMessageDeliveryAdapter(viewLifecycleOwner)
binding.messageDelivery.deliveryList.setHasFixedSize(true)
binding.messageDelivery.deliveryList.adapter = deliveryAdapter
val layoutManager = LinearLayoutManager(requireContext())
binding.eventsList.layoutManager = layoutManager
val deliveryLayoutManager = LinearLayoutManager(requireContext())
binding.messageDelivery.deliveryList.layoutManager = deliveryLayoutManager
adapter.chatMessageLongPressEvent.observe(viewLifecycleOwner) {
it.consume { model ->
showChatMessageLongPressMenu(model)
@ -323,6 +333,10 @@ class ConversationFragment : GenericFragment() {
val model = ChatMessageDeliveryModel(chatMessageModel.chatMessage)
coreContext.postOnMainThread {
model.deliveryModels.observe(viewLifecycleOwner) {
deliveryAdapter.submitList(it)
}
binding.messageDelivery.tabs.removeAllTabs()
binding.messageDelivery.tabs.addTab(
binding.messageDelivery.tabs.newTab().setText(model.readLabel.value).setId(

View file

@ -9,6 +9,8 @@ class ChatMessageParticipantDeliveryModel @WorkerThread constructor(
address: Address,
timestamp: Long
) {
val sipUri = address.asStringUriOnly()
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(address)
val time = TimestampUtils.toString(timestamp)

View file

@ -40,7 +40,7 @@
android:background="@color/transparent_color"
android:layout_marginBottom="16dp"
app:layout_constraintTop_toBottomOf="@id/handle"
app:layout_constraintBottom_toTopOf="@id/scrollview"
app:layout_constraintBottom_toTopOf="@id/deliveryList"
app:tabMode="fixed"
app:tabUnboundedRipple="true"
app:tabRippleColor="@color/orange_main_100"
@ -51,21 +51,13 @@
app:tabTextColor="@color/gray_main2_400"
app:tabSelectedTextColor="@color/gray_main2_600" />
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollview"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/deliveryList"
android:layout_width="match_parent"
android:layout_height="250dp"
android:nestedScrollingEnabled="true"
app:layout_constraintHeight_min="50dp"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
entries="@{model.deliveryModels}"
layout="@{@layout/chat_delivery_list_cell}" />
</androidx.core.widget.NestedScrollView>
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>