Archiving messages currently acts like recycle bin in Simple Gallery, meaning that after 30 days, conversations will be deleted permanently. Any updates to the conversation (new messages) removes it from archive. This closes #177
183 lines
7.1 KiB
Kotlin
183 lines
7.1 KiB
Kotlin
package com.simplemobiletools.smsmessenger.adapters
|
|
|
|
import android.graphics.Typeface
|
|
import android.os.Parcelable
|
|
import android.util.TypedValue
|
|
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.MyRecyclerViewListAdapter
|
|
import com.simplemobiletools.commons.extensions.*
|
|
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
|
import com.simplemobiletools.commons.views.MyRecyclerView
|
|
import com.simplemobiletools.smsmessenger.R
|
|
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
|
import com.simplemobiletools.smsmessenger.extensions.*
|
|
import com.simplemobiletools.smsmessenger.models.Conversation
|
|
import kotlinx.android.synthetic.main.item_conversation.view.*
|
|
|
|
@Suppress("LeakingThis")
|
|
abstract class BaseConversationsAdapter(
|
|
activity: SimpleActivity, recyclerView: MyRecyclerView, onRefresh: () -> Unit, itemClick: (Any) -> Unit
|
|
) : MyRecyclerViewListAdapter<Conversation>(activity, recyclerView, ConversationDiffCallback(), itemClick, onRefresh),
|
|
RecyclerViewFastScroller.OnPopupTextUpdate {
|
|
private var fontSize = activity.getTextSize()
|
|
private var drafts = HashMap<Long, String?>()
|
|
|
|
private var recyclerViewState: Parcelable? = null
|
|
|
|
init {
|
|
setupDragListener(true)
|
|
ensureBackgroundThread {
|
|
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()
|
|
})
|
|
}
|
|
|
|
fun updateFontSize() {
|
|
fontSize = activity.getTextSize()
|
|
notifyDataSetChanged()
|
|
}
|
|
|
|
fun updateConversations(newConversations: ArrayList<Conversation>, commitCallback: (() -> Unit)? = null) {
|
|
saveRecyclerViewState()
|
|
submitList(newConversations.toList(), commitCallback)
|
|
}
|
|
|
|
fun updateDrafts() {
|
|
ensureBackgroundThread {
|
|
val newDrafts = HashMap<Long, String?>()
|
|
fetchDrafts(newDrafts)
|
|
if (drafts.hashCode() != newDrafts.hashCode()) {
|
|
drafts = newDrafts
|
|
activity.runOnUiThread {
|
|
notifyDataSetChanged()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun getSelectableItemCount() = itemCount
|
|
|
|
protected fun getSelectedItems() = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
|
|
|
|
override fun getIsItemSelectable(position: Int) = true
|
|
|
|
override fun getItemSelectionKey(position: Int) = currentList.getOrNull(position)?.hashCode()
|
|
|
|
override fun getItemKeyPosition(key: Int) = currentList.indexOfFirst { it.hashCode() == key }
|
|
|
|
override fun onActionModeCreated() {}
|
|
|
|
override fun onActionModeDestroyed() {}
|
|
|
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conversation, parent)
|
|
|
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
val conversation = getItem(position)
|
|
holder.bindView(conversation, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
|
|
setupView(itemView, conversation)
|
|
}
|
|
bindViewHolder(holder)
|
|
}
|
|
|
|
override fun getItemId(position: Int) = getItem(position).threadId
|
|
|
|
override fun onViewRecycled(holder: ViewHolder) {
|
|
super.onViewRecycled(holder)
|
|
if (!activity.isDestroyed && !activity.isFinishing) {
|
|
Glide.with(activity).clear(holder.itemView.conversation_image)
|
|
}
|
|
}
|
|
|
|
private fun fetchDrafts(drafts: HashMap<Long, String?>) {
|
|
drafts.clear()
|
|
for ((threadId, draft) in activity.getAllDrafts()) {
|
|
drafts[threadId] = draft
|
|
}
|
|
}
|
|
|
|
private fun setupView(view: View, conversation: Conversation) {
|
|
view.apply {
|
|
setupViewBackground(activity)
|
|
val smsDraft = drafts[conversation.threadId]
|
|
draft_indicator.beVisibleIf(smsDraft != null)
|
|
draft_indicator.setTextColor(properPrimaryColor)
|
|
|
|
pin_indicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString()))
|
|
pin_indicator.applyColorFilter(textColor)
|
|
|
|
conversation_frame.isSelected = selectedKeys.contains(conversation.hashCode())
|
|
|
|
conversation_address.apply {
|
|
text = conversation.title
|
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
|
|
}
|
|
|
|
conversation_body_short.apply {
|
|
text = smsDraft ?: conversation.snippet
|
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f)
|
|
}
|
|
|
|
conversation_date.apply {
|
|
text = conversation.date.formatDateOrTime(context, true, false)
|
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
|
|
}
|
|
|
|
val style = if (conversation.read) {
|
|
conversation_body_short.alpha = 0.7f
|
|
if (conversation.isScheduled) Typeface.ITALIC else Typeface.NORMAL
|
|
} else {
|
|
conversation_body_short.alpha = 1f
|
|
if (conversation.isScheduled) Typeface.BOLD_ITALIC else Typeface.BOLD
|
|
|
|
}
|
|
conversation_address.setTypeface(null, style)
|
|
conversation_body_short.setTypeface(null, style)
|
|
|
|
arrayListOf<TextView>(conversation_address, conversation_body_short, conversation_date).forEach {
|
|
it.setTextColor(textColor)
|
|
}
|
|
|
|
// at group conversations we use an icon as the placeholder, not any letter
|
|
val placeholder = if (conversation.isGroupConversation) {
|
|
SimpleContactsHelper(context).getColoredGroupIcon(conversation.title)
|
|
} else {
|
|
null
|
|
}
|
|
|
|
SimpleContactsHelper(context).loadContactImage(conversation.photoUri, conversation_image, conversation.title, placeholder)
|
|
}
|
|
}
|
|
|
|
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 Conversation.areItemsTheSame(oldItem, newItem)
|
|
}
|
|
|
|
override fun areContentsTheSame(oldItem: Conversation, newItem: Conversation): Boolean {
|
|
return Conversation.areContentsTheSame(oldItem, newItem)
|
|
}
|
|
}
|
|
}
|