2020-04-16 15:44:53 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2020 Proton Technologies AG
|
2021-03-18 09:46:25 +00:00
|
|
|
*
|
2020-04-16 15:44:53 +00:00
|
|
|
* This file is part of ProtonMail.
|
2021-03-18 09:46:25 +00:00
|
|
|
*
|
2020-04-16 15:44:53 +00:00
|
|
|
* ProtonMail is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2021-03-18 09:46:25 +00:00
|
|
|
*
|
2020-04-16 15:44:53 +00:00
|
|
|
* ProtonMail is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2021-03-18 09:46:25 +00:00
|
|
|
*
|
2020-04-16 15:44:53 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
|
|
|
*/
|
|
|
|
package ch.protonmail.android.adapters.messages
|
|
|
|
|
|
|
|
import android.content.Context
|
2021-03-18 09:46:25 +00:00
|
|
|
import androidx.recyclerview.widget.RecyclerView
|
2021-03-17 14:36:07 +00:00
|
|
|
import android.view.ViewGroup
|
2021-03-18 09:46:26 +00:00
|
|
|
import ch.protonmail.android.api.models.room.contacts.ContactEmail
|
|
|
|
import ch.protonmail.android.api.models.room.messages.Label
|
|
|
|
import ch.protonmail.android.api.models.room.messages.Message
|
|
|
|
import ch.protonmail.android.api.models.room.pendingActions.PendingSend
|
|
|
|
import ch.protonmail.android.api.models.room.pendingActions.PendingUpload
|
2020-04-16 15:44:53 +00:00
|
|
|
import ch.protonmail.android.core.Constants
|
2021-04-16 20:20:48 +00:00
|
|
|
import ch.protonmail.android.data.local.model.ContactEmail
|
|
|
|
import ch.protonmail.android.data.local.model.Label
|
|
|
|
import ch.protonmail.android.data.local.model.Message
|
|
|
|
import ch.protonmail.android.data.local.model.PendingSend
|
|
|
|
import ch.protonmail.android.data.local.model.PendingUpload
|
2020-04-16 15:44:53 +00:00
|
|
|
import ch.protonmail.android.utils.ui.selection.SelectionModeEnum
|
|
|
|
import ch.protonmail.android.views.messagesList.MessagesListFooterView
|
|
|
|
import ch.protonmail.android.views.messagesList.MessagesListItemView
|
2021-04-16 20:20:48 +00:00
|
|
|
import kotlinx.android.synthetic.main.layout_sender_initial.view.*
|
|
|
|
import kotlinx.android.synthetic.main.list_item_mailbox.view.*
|
2020-04-16 15:44:53 +00:00
|
|
|
|
2020-09-04 07:27:23 +00:00
|
|
|
class MessagesRecyclerViewAdapter(
|
|
|
|
private val context: Context,
|
|
|
|
private val onSelectionModeChange: ((SelectionModeEnum) -> Unit)?
|
|
|
|
) : RecyclerView.Adapter<MessagesListViewHolder>() {
|
2020-04-16 15:44:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
private var mMailboxLocation = Constants.MessageLocationType.INVALID
|
|
|
|
|
|
|
|
private var labels = mapOf<String, Label>()
|
|
|
|
private val messages = mutableListOf<Message>()
|
|
|
|
private val selectedMessageIds: MutableSet<String> = mutableSetOf()
|
|
|
|
|
|
|
|
private var pendingUploadList: List<PendingUpload>? = null
|
|
|
|
private var pendingSendList: List<PendingSend>? = null
|
|
|
|
private var contactsList: List<ContactEmail>? = null
|
|
|
|
|
|
|
|
private var onItemClick: ((Message) -> Unit)? = null
|
2021-04-16 20:20:48 +00:00
|
|
|
private var onItemSelectionChangedListener: (() -> Unit)? = null
|
2020-04-16 15:44:53 +00:00
|
|
|
|
|
|
|
var includeFooter: Boolean = false
|
|
|
|
set(value) {
|
|
|
|
if (field == value) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
field = value
|
|
|
|
if (value) {
|
|
|
|
notifyItemInserted(messages.size)
|
|
|
|
} else {
|
|
|
|
notifyItemRemoved(messages.size)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val checkedMessages get() = selectedMessageIds.mapNotNull { messages.find { message -> message.messageId == it } }
|
|
|
|
|
2021-03-15 01:13:04 +00:00
|
|
|
fun getItem(position: Int) = messages[position]
|
|
|
|
|
2020-04-16 15:44:53 +00:00
|
|
|
fun addAll(messages: List<Message>) {
|
2021-03-15 01:13:04 +00:00
|
|
|
this.messages.addAll(
|
|
|
|
messages.filter {
|
|
|
|
!it.deleted
|
|
|
|
}
|
|
|
|
)
|
2020-04-16 15:44:53 +00:00
|
|
|
notifyDataSetChanged()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun clear() {
|
|
|
|
messages.clear()
|
|
|
|
notifyDataSetChanged()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setItemClick(onItemClick: ((Message) -> Unit)?) {
|
|
|
|
this.onItemClick = onItemClick
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:20:48 +00:00
|
|
|
fun setOnItemSelectionChangedListener(onItemSelectionChangedListener: () -> Unit) {
|
|
|
|
this.onItemSelectionChangedListener = onItemSelectionChangedListener
|
|
|
|
}
|
|
|
|
|
2020-04-16 15:44:53 +00:00
|
|
|
private enum class ElementType {
|
|
|
|
MESSAGE, FOOTER
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun getItemViewType(position: Int): Int {
|
2020-09-04 07:27:23 +00:00
|
|
|
val itemViewType = if (position == messages.size) ElementType.FOOTER else ElementType.MESSAGE
|
|
|
|
return itemViewType.ordinal
|
2020-04-16 15:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessagesListViewHolder {
|
|
|
|
return when (ElementType.values()[viewType]) {
|
2021-03-17 14:36:07 +00:00
|
|
|
ElementType.MESSAGE -> MessagesListViewHolder.MessageViewHolder(MessagesListItemView(context))
|
2020-04-16 15:44:53 +00:00
|
|
|
ElementType.FOOTER -> MessagesListViewHolder.FooterViewHolder(MessagesListFooterView(context))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-15 01:13:04 +00:00
|
|
|
override fun getItemCount(): Int = messages.size + if (includeFooter) 1 else 0
|
2020-04-16 15:44:53 +00:00
|
|
|
|
|
|
|
override fun onBindViewHolder(holder: MessagesListViewHolder, position: Int) {
|
|
|
|
when (ElementType.values()[getItemViewType(position)]) {
|
2021-03-15 01:13:04 +00:00
|
|
|
ElementType.MESSAGE -> {
|
2021-03-17 14:36:07 +00:00
|
|
|
(holder as MessagesListViewHolder.MessageViewHolder).bindMessage(position)
|
2021-03-15 01:13:04 +00:00
|
|
|
}
|
2020-04-16 15:44:53 +00:00
|
|
|
ElementType.FOOTER -> {
|
2020-09-04 07:27:23 +00:00
|
|
|
// NOOP
|
2020-04-16 15:44:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:20:48 +00:00
|
|
|
private fun selectMessage(messageId: String, position: Int) {
|
|
|
|
if (selectedMessageIds.isEmpty()) {
|
|
|
|
onSelectionModeChange?.invoke(SelectionModeEnum.STARTED)
|
|
|
|
notifyDataSetChanged()
|
|
|
|
}
|
|
|
|
selectedMessageIds.add(messageId)
|
|
|
|
onItemSelectionChangedListener?.invoke()
|
|
|
|
notifyItemChanged(position)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun deselectMessage(messageId: String, position: Int) {
|
|
|
|
selectedMessageIds.remove(messageId)
|
|
|
|
if (selectedMessageIds.isEmpty()) {
|
|
|
|
onSelectionModeChange?.invoke(SelectionModeEnum.ENDED)
|
|
|
|
notifyDataSetChanged()
|
|
|
|
} else {
|
|
|
|
onItemSelectionChangedListener?.invoke()
|
|
|
|
notifyItemChanged(position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun selectOrDeselectMessage(messageId: String, position: Int): Boolean {
|
|
|
|
if (onSelectionModeChange == null || onItemSelectionChangedListener == null) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selectedMessageIds.contains(messageId)) {
|
|
|
|
deselectMessage(messageId, position)
|
|
|
|
} else {
|
|
|
|
selectMessage(messageId, position)
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-04-16 15:44:53 +00:00
|
|
|
private fun MessagesListViewHolder.MessageViewHolder.bindMessage(position: Int) {
|
|
|
|
val message = messages[position]
|
|
|
|
val messageLabels = message.allLabelIDs.mapNotNull { labels[it] }
|
|
|
|
|
2021-03-18 09:46:26 +00:00
|
|
|
val pendingSend = pendingSendList?.find { it.messageId == message.messageId }
|
|
|
|
// under these conditions the message is in sending process
|
|
|
|
message.isBeingSent = pendingSend != null && pendingSend.sent == null
|
|
|
|
message.isAttachmentsBeingUploaded = pendingUploadList?.find { it.messageId == message.messageId } != null
|
|
|
|
message.senderDisplayName = contactsList?.find { message.senderEmail == it.email }?.name
|
|
|
|
?: message.senderName
|
2020-04-16 15:44:53 +00:00
|
|
|
|
2021-04-16 20:20:48 +00:00
|
|
|
this.view.bind(message, messageLabels, selectedMessageIds.isNotEmpty(), mMailboxLocation)
|
2020-04-16 15:44:53 +00:00
|
|
|
|
|
|
|
val isSelected = selectedMessageIds.contains(message.messageId)
|
2021-04-16 20:20:48 +00:00
|
|
|
this.view.checkImageView.isActivated = isSelected
|
|
|
|
|
2020-04-16 15:44:53 +00:00
|
|
|
this.view.tag = message.messageId
|
2021-04-16 20:20:48 +00:00
|
|
|
this.view.senderInitialView.tag = message.messageId
|
2020-04-16 15:44:53 +00:00
|
|
|
|
2021-04-16 20:20:48 +00:00
|
|
|
this.view.senderInitialView.setOnClickListener {
|
2020-04-16 15:44:53 +00:00
|
|
|
val messageId = it.tag as String
|
2021-04-16 20:20:48 +00:00
|
|
|
selectOrDeselectMessage(messageId, position)
|
|
|
|
}
|
|
|
|
|
|
|
|
this.view.setOnClickListener {
|
2020-04-16 15:44:53 +00:00
|
|
|
if (selectedMessageIds.isNotEmpty()) {
|
2021-04-16 20:20:48 +00:00
|
|
|
val messageId = it.tag as String
|
|
|
|
selectOrDeselectMessage(messageId, position)
|
2020-04-16 15:44:53 +00:00
|
|
|
} else {
|
|
|
|
onItemClick?.invoke(message)
|
|
|
|
}
|
|
|
|
}
|
2021-04-16 20:20:48 +00:00
|
|
|
this.view.setOnLongClickListener {
|
|
|
|
if (selectedMessageIds.isEmpty()) {
|
|
|
|
val messageId = it.tag as String
|
|
|
|
return@setOnLongClickListener selectOrDeselectMessage(messageId, position)
|
|
|
|
}
|
|
|
|
return@setOnLongClickListener true
|
|
|
|
}
|
2021-03-15 01:13:04 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 15:44:53 +00:00
|
|
|
fun endSelectionMode() {
|
|
|
|
selectedMessageIds.clear()
|
|
|
|
notifyDataSetChanged()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setLabels(labels: List<Label>) {
|
|
|
|
this.labels = labels.map { it.id to it }.toMap()
|
|
|
|
notifyDataSetChanged()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setPendingUploadsList(pendingUploadList: List<PendingUpload>) {
|
|
|
|
this.pendingUploadList = pendingUploadList
|
2021-03-18 09:46:26 +00:00
|
|
|
notifyDataSetChanged()
|
2020-04-16 15:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fun setPendingForSendingList(pendingSendList: List<PendingSend>) {
|
|
|
|
this.pendingSendList = pendingSendList
|
2021-03-18 09:46:26 +00:00
|
|
|
notifyDataSetChanged()
|
2020-04-16 15:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fun setContactsList(contactsList: List<ContactEmail>?) {
|
|
|
|
this.contactsList = contactsList
|
2021-03-18 09:46:26 +00:00
|
|
|
notifyDataSetChanged()
|
2020-04-16 15:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fun setNewLocation(mailboxLocation: Constants.MessageLocationType) {
|
|
|
|
mMailboxLocation = mailboxLocation
|
|
|
|
}
|
|
|
|
}
|