120 lines
4.3 KiB
Kotlin
120 lines
4.3 KiB
Kotlin
package org.thoughtcrime.securesms.home
|
|
|
|
import android.content.Context
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import androidx.recyclerview.widget.DiffUtil
|
|
import androidx.recyclerview.widget.ListUpdateCallback
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
|
import network.loki.messenger.R
|
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
|
|
|
class HomeAdapter(
|
|
private val context: Context,
|
|
private val listener: ConversationClickListener
|
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), ListUpdateCallback {
|
|
|
|
companion object {
|
|
private const val HEADER = 0
|
|
private const val ITEM = 1
|
|
}
|
|
|
|
var header: View? = null
|
|
|
|
private var _data: List<ThreadRecord> = emptyList()
|
|
var data: List<ThreadRecord>
|
|
get() = _data.toList()
|
|
set(newData) {
|
|
val previousData = _data.toList()
|
|
val diff = HomeDiffUtil(previousData, newData, context)
|
|
val diffResult = DiffUtil.calculateDiff(diff)
|
|
_data = newData
|
|
diffResult.dispatchUpdatesTo(this as ListUpdateCallback)
|
|
}
|
|
|
|
fun hasHeaderView(): Boolean = header != null
|
|
|
|
private val headerCount: Int
|
|
get() = if (header == null) 0 else 1
|
|
|
|
override fun onInserted(position: Int, count: Int) {
|
|
notifyItemRangeInserted(position + headerCount, count)
|
|
}
|
|
|
|
override fun onRemoved(position: Int, count: Int) {
|
|
notifyItemRangeRemoved(position + headerCount, count)
|
|
}
|
|
|
|
override fun onMoved(fromPosition: Int, toPosition: Int) {
|
|
notifyItemMoved(fromPosition + headerCount, toPosition + headerCount)
|
|
}
|
|
|
|
override fun onChanged(position: Int, count: Int, payload: Any?) {
|
|
notifyItemRangeChanged(position + headerCount, count, payload)
|
|
}
|
|
|
|
override fun getItemId(position: Int): Long {
|
|
if (hasHeaderView() && position == 0) return NO_ID
|
|
val offsetPosition = if (hasHeaderView()) position-1 else position
|
|
return _data[offsetPosition].threadId
|
|
}
|
|
|
|
lateinit var glide: GlideRequests
|
|
var typingThreadIDs = setOf<Long>()
|
|
set(value) {
|
|
if (field == value) { return }
|
|
|
|
field = value
|
|
// TODO: replace this with a diffed update or a partial change set with payloads
|
|
notifyDataSetChanged()
|
|
}
|
|
|
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
|
when (viewType) {
|
|
HEADER -> {
|
|
HeaderFooterViewHolder(header!!)
|
|
}
|
|
ITEM -> {
|
|
val conversationView = LayoutInflater.from(parent.context).inflate(R.layout.view_conversation, parent, false) as ConversationView
|
|
val viewHolder = ConversationViewHolder(conversationView)
|
|
viewHolder.view.setOnClickListener { viewHolder.view.thread?.let { listener.onConversationClick(it) } }
|
|
viewHolder.view.setOnLongClickListener {
|
|
viewHolder.view.thread?.let { listener.onLongConversationClick(it) }
|
|
true
|
|
}
|
|
viewHolder
|
|
}
|
|
else -> throw Exception("viewType $viewType isn't valid")
|
|
}
|
|
|
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
|
if (holder is ConversationViewHolder) {
|
|
val offset = if (hasHeaderView()) position - 1 else position
|
|
val thread = data[offset]
|
|
val isTyping = typingThreadIDs.contains(thread.threadId)
|
|
holder.view.bind(thread, isTyping, glide)
|
|
}
|
|
}
|
|
|
|
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
|
if (holder is ConversationViewHolder) {
|
|
holder.view.recycle()
|
|
} else {
|
|
super.onViewRecycled(holder)
|
|
}
|
|
}
|
|
|
|
override fun getItemViewType(position: Int): Int =
|
|
if (hasHeaderView() && position == 0) HEADER
|
|
else ITEM
|
|
|
|
override fun getItemCount(): Int = data.size + if (hasHeaderView()) 1 else 0
|
|
|
|
class ConversationViewHolder(val view: ConversationView) : RecyclerView.ViewHolder(view)
|
|
|
|
class HeaderFooterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
|
|
|
|
} |