Use DiffUtil at conversations screen

This commit is contained in:
Naveen 2022-11-13 00:38:11 +05:30
parent 3092253022
commit 9bdc8b6f7e
3 changed files with 68 additions and 38 deletions

View File

@ -299,7 +299,7 @@ class MainActivity : SimpleActivity() {
val currAdapter = conversations_list.adapter
if (currAdapter == null) {
hideKeyboard()
ConversationsAdapter(this, sortedConversations, conversations_list) {
ConversationsAdapter(this, conversations_list) {
Intent(this, ThreadActivity::class.java).apply {
val conversation = it as Conversation
putExtra(THREAD_ID, conversation.threadId)
@ -308,6 +308,7 @@ class MainActivity : SimpleActivity() {
}
}.apply {
conversations_list.adapter = this
updateConversations(sortedConversations)
}
if (areSystemAnimationsEnabled) {
@ -315,12 +316,13 @@ class MainActivity : SimpleActivity() {
}
} else {
try {
(currAdapter as ConversationsAdapter).updateConversations(sortedConversations)
if (currAdapter.conversations.isEmpty()) {
conversations_fastscroller.beGone()
no_conversations_placeholder.text = getString(R.string.no_conversations_found)
no_conversations_placeholder.beVisible()
no_conversations_placeholder_2.beVisible()
(currAdapter as ConversationsAdapter).updateConversations(sortedConversations) {
if (currAdapter.currentList.isEmpty()) {
conversations_fastscroller.beGone()
no_conversations_placeholder.text = getString(R.string.no_conversations_found)
no_conversations_placeholder.beVisible()
no_conversations_placeholder_2.beVisible()
}
}
} catch (ignored: Exception) {
}

View File

@ -2,15 +2,18 @@ package com.simplemobiletools.smsmessenger.adapters
import android.content.Intent
import android.graphics.Typeface
import android.os.Parcelable
import android.text.TextUtils
import android.util.TypedValue
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.adapters.MyRecyclerViewListAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.KEY_PHONE
@ -26,14 +29,23 @@ import com.simplemobiletools.smsmessenger.models.Conversation
import kotlinx.android.synthetic.main.item_conversation.view.*
class ConversationsAdapter(
activity: SimpleActivity, var conversations: ArrayList<Conversation>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
activity: SimpleActivity, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
) : MyRecyclerViewListAdapter<Conversation>(activity, recyclerView, ConversationDiffCallback(), itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
private var fontSize = activity.getTextSize()
private var drafts = HashMap<Long, String?>()
private var recyclerViewState: Parcelable? = null
init {
setupDragListener(true)
fetchDrafts(drafts)
setHasStableIds(true)
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() = restoreRecyclerViewState()
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) = restoreRecyclerViewState()
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) = restoreRecyclerViewState()
})
}
override fun getActionMenuId() = R.menu.cab_conversations
@ -71,13 +83,13 @@ class ConversationsAdapter(
}
}
override fun getSelectableItemCount() = conversations.size
override fun getSelectableItemCount() = itemCount
override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = conversations.getOrNull(position)?.hashCode()
override fun getItemSelectionKey(position: Int) = currentList.getOrNull(position)?.hashCode()
override fun getItemKeyPosition(key: Int) = conversations.indexOfFirst { it.hashCode() == key }
override fun getItemKeyPosition(key: Int) = currentList.indexOfFirst { it.hashCode() == key }
override fun onActionModeCreated() {}
@ -86,14 +98,14 @@ class ConversationsAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conversation, parent)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val conversation = conversations[position]
holder.bindView(conversation, true, true) { itemView, layoutPosition ->
val conversation = getItem(position)
holder.bindView(conversation, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
setupView(itemView, conversation)
}
bindViewHolder(holder)
}
override fun getItemCount() = conversations.size
override fun getItemId(position: Int) = getItem(position).threadId
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
@ -118,8 +130,7 @@ class ConversationsAdapter(
}
val numbersToBlock = getSelectedItems()
val positions = getSelectedItemPositions()
conversations.removeAll(numbersToBlock)
val newList = currentList.toMutableList().apply { removeAll(numbersToBlock) }
ensureBackgroundThread {
numbersToBlock.map { it.phoneNumber }.forEach { number ->
@ -127,7 +138,7 @@ class ConversationsAdapter(
}
activity.runOnUiThread {
removeSelectedItems(positions)
submitList(newList)
finishActMode()
}
}
@ -165,25 +176,25 @@ class ConversationsAdapter(
return
}
val conversationsToRemove = conversations.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
val positions = getSelectedItemPositions()
val conversationsToRemove = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
conversationsToRemove.forEach {
activity.deleteConversation(it.threadId)
activity.notificationManager.cancel(it.hashCode())
}
try {
conversations.removeAll(conversationsToRemove.toSet())
val newList = try {
currentList.toMutableList().apply { removeAll(conversationsToRemove) }
} catch (ignored: Exception) {
currentList.toMutableList()
}
activity.runOnUiThread {
if (conversationsToRemove.isEmpty()) {
if (newList.none { selectedKeys.contains(it.hashCode()) }) {
refreshMessages()
finishActMode()
} else {
removeSelectedItems(positions)
if (conversations.isEmpty()) {
submitList(newList)
if (newList.isEmpty()) {
refreshMessages()
}
}
@ -195,7 +206,7 @@ class ConversationsAdapter(
return
}
val conversationsMarkedAsRead = conversations.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
val conversationsMarkedAsRead = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
ensureBackgroundThread {
conversationsMarkedAsRead.filter { conversation -> !conversation.read }.forEach {
activity.markThreadMessagesRead(it.threadId)
@ -213,7 +224,7 @@ class ConversationsAdapter(
return
}
val conversationsMarkedAsUnread = conversations.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
val conversationsMarkedAsUnread = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
ensureBackgroundThread {
conversationsMarkedAsUnread.filter { conversation -> conversation.read }.forEach {
activity.markThreadMessagesUnread(it.threadId)
@ -236,7 +247,7 @@ class ConversationsAdapter(
}
}
private fun getSelectedItems() = conversations.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
private fun getSelectedItems() = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
private fun pinConversation(pin: Boolean) {
val conversations = getSelectedItems()
@ -275,14 +286,9 @@ class ConversationsAdapter(
notifyDataSetChanged()
}
fun updateConversations(newConversations: ArrayList<Conversation>) {
val latestConversations = newConversations.clone() as ArrayList<Conversation>
val oldHashCode = conversations.hashCode()
val newHashCode = latestConversations.hashCode()
if (newHashCode != oldHashCode) {
conversations = latestConversations
notifyDataSetChanged()
}
fun updateConversations(newConversations: ArrayList<Conversation>, commitCallback: (() -> Unit)? = null) {
saveRecyclerViewState()
submitList(newConversations.toList(), commitCallback)
}
fun updateDrafts() {
@ -346,5 +352,23 @@ class ConversationsAdapter(
}
}
override fun onChange(position: Int) = conversations.getOrNull(position)?.title ?: ""
override fun onChange(position: Int) = currentList.getOrNull(position)?.title ?: ""
private fun saveRecyclerViewState() {
recyclerViewState = recyclerView.layoutManager?.onSaveInstanceState()
}
private fun restoreRecyclerViewState() {
recyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
private class ConversationDiffCallback : DiffUtil.ItemCallback<Conversation>() {
override fun areItemsTheSame(oldItem: Conversation, newItem: Conversation): Boolean {
return oldItem.areItemsTheSame(newItem)
}
override fun areContentsTheSame(oldItem: Conversation, newItem: Conversation): Boolean {
return oldItem.areContentsTheSame(newItem)
}
}
}

View File

@ -18,6 +18,10 @@ data class Conversation(
@ColumnInfo(name = "is_scheduled") var isScheduled: Boolean = false
) {
fun areItemsTheSame(other: Conversation): Boolean {
return threadId == other.threadId
}
fun areContentsTheSame(other: Conversation): Boolean {
return snippet == other.snippet &&
date == other.date &&