Switch to ListAdapter (replacing RecyclerView.Adapter) (#321)
This commit is contained in:
@@ -14,6 +14,8 @@ import android.widget.ImageView
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.github.gotify.MarkwonFactory
|
import com.github.gotify.MarkwonFactory
|
||||||
@@ -34,9 +36,8 @@ internal class ListMessageAdapter(
|
|||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val settings: Settings,
|
private val settings: Settings,
|
||||||
private val picasso: Picasso,
|
private val picasso: Picasso,
|
||||||
var items: List<MessageWithImage>,
|
|
||||||
private val delete: Delete
|
private val delete: Delete
|
||||||
) : RecyclerView.Adapter<ListMessageAdapter.ViewHolder>() {
|
) : ListAdapter<MessageWithImage, ListMessageAdapter.ViewHolder>(DiffCallback) {
|
||||||
private val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
private val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
private val markwon: Markwon = MarkwonFactory.createForMessage(context, picasso)
|
private val markwon: Markwon = MarkwonFactory.createForMessage(context, picasso)
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ internal class ListMessageAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val message = items[position]
|
val message = currentList[position]
|
||||||
if (Extras.useMarkdown(message.message)) {
|
if (Extras.useMarkdown(message.message)) {
|
||||||
holder.message.autoLinkMask = 0
|
holder.message.autoLinkMask = 0
|
||||||
markwon.setMarkdown(holder.message, message.message.message)
|
markwon.setMarkdown(holder.message, message.message.message)
|
||||||
@@ -92,14 +93,12 @@ internal class ListMessageAdapter(
|
|||||||
holder.date.setOnClickListener { holder.switchTimeFormat() }
|
holder.date.setOnClickListener { holder.switchTimeFormat() }
|
||||||
|
|
||||||
holder.delete.setOnClickListener {
|
holder.delete.setOnClickListener {
|
||||||
delete.delete(holder.adapterPosition, message.message, false)
|
delete.delete(message.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = items.size
|
|
||||||
|
|
||||||
override fun getItemId(position: Int): Long {
|
override fun getItemId(position: Int): Long {
|
||||||
val currentItem = items[position]
|
val currentItem = currentList[position]
|
||||||
return currentItem.message.id
|
return currentItem.message.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +183,23 @@ internal class ListMessageAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object DiffCallback : DiffUtil.ItemCallback<MessageWithImage>() {
|
||||||
|
override fun areItemsTheSame(
|
||||||
|
oldItem: MessageWithImage,
|
||||||
|
newItem: MessageWithImage
|
||||||
|
): Boolean {
|
||||||
|
return oldItem.message.id == newItem.message.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(
|
||||||
|
oldItem: MessageWithImage,
|
||||||
|
newItem: MessageWithImage
|
||||||
|
): Boolean {
|
||||||
|
return oldItem == newItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun interface Delete {
|
fun interface Delete {
|
||||||
fun delete(position: Int, message: Message, listAnimation: Boolean)
|
fun delete(message: Message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,14 +101,9 @@ internal class MessagesActivity :
|
|||||||
listMessageAdapter = ListMessageAdapter(
|
listMessageAdapter = ListMessageAdapter(
|
||||||
this,
|
this,
|
||||||
viewModel.settings,
|
viewModel.settings,
|
||||||
viewModel.picassoHandler.get(),
|
viewModel.picassoHandler.get()
|
||||||
emptyList()
|
) { message ->
|
||||||
) { position, message, listAnimation ->
|
scheduleDeletion(message)
|
||||||
scheduleDeletion(
|
|
||||||
position,
|
|
||||||
message,
|
|
||||||
listAnimation
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
addBackPressCallback()
|
addBackPressCallback()
|
||||||
|
|
||||||
@@ -329,7 +324,6 @@ internal class MessagesActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listMessageAdapter.notifyDataSetChanged()
|
|
||||||
selectAppInMenu(binding.navView.menu.findItem(selectedIndex))
|
selectAppInMenu(binding.navView.menu.findItem(selectedIndex))
|
||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
@@ -348,20 +342,11 @@ internal class MessagesActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun scheduleDeletion(
|
private fun scheduleDeletion(message: Message) {
|
||||||
position: Int,
|
|
||||||
message: Message,
|
|
||||||
listAnimation: Boolean
|
|
||||||
) {
|
|
||||||
val adapter = binding.messagesView.adapter as ListMessageAdapter
|
val adapter = binding.messagesView.adapter as ListMessageAdapter
|
||||||
val messages = viewModel.messages
|
val messages = viewModel.messages
|
||||||
messages.deleteLocal(message)
|
messages.deleteLocal(message)
|
||||||
adapter.items = messages[viewModel.appId]
|
adapter.updateList(messages[viewModel.appId])
|
||||||
if (listAnimation) {
|
|
||||||
adapter.notifyItemRemoved(position)
|
|
||||||
} else {
|
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
showDeletionSnackbar()
|
showDeletionSnackbar()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,13 +356,7 @@ internal class MessagesActivity :
|
|||||||
if (deletion != null) {
|
if (deletion != null) {
|
||||||
val adapter = binding.messagesView.adapter as ListMessageAdapter
|
val adapter = binding.messagesView.adapter as ListMessageAdapter
|
||||||
val appId = viewModel.appId
|
val appId = viewModel.appId
|
||||||
adapter.items = messages[appId]
|
adapter.updateList(messages[appId])
|
||||||
val insertPosition = if (appId == MessageState.ALL_MESSAGES) {
|
|
||||||
deletion.allPosition
|
|
||||||
} else {
|
|
||||||
deletion.appPosition
|
|
||||||
}
|
|
||||||
adapter.notifyItemInserted(insertPosition)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,8 +411,8 @@ internal class MessagesActivity :
|
|||||||
|
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
val position = viewHolder.adapterPosition
|
val position = viewHolder.adapterPosition
|
||||||
val message = adapter.items[position]
|
val message = adapter.currentList[position]
|
||||||
scheduleDeletion(position, message.message, true)
|
scheduleDeletion(message.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onChildDraw(
|
override fun onChildDraw(
|
||||||
@@ -649,8 +628,16 @@ internal class MessagesActivity :
|
|||||||
binding.flipper.displayedChild = 0
|
binding.flipper.displayedChild = 0
|
||||||
}
|
}
|
||||||
val adapter = binding.messagesView.adapter as ListMessageAdapter
|
val adapter = binding.messagesView.adapter as ListMessageAdapter
|
||||||
adapter.items = messageWithImages
|
adapter.updateList(messageWithImages)
|
||||||
adapter.notifyDataSetChanged()
|
}
|
||||||
|
|
||||||
|
private fun ListMessageAdapter.updateList(list: List<MessageWithImage>) {
|
||||||
|
this.submitList(if (this.currentList == list) list.toList() else list) {
|
||||||
|
val topChild = binding.messagesView.getChildAt(0)
|
||||||
|
if (topChild != null && topChild.top == 0) {
|
||||||
|
binding.messagesView.scrollToPosition(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
Reference in New Issue
Block a user