Skip to content

Commit a7e3f12

Browse files
committed
MessagesListFragment. Restored seelction functionality.| #1806
1 parent 1e04bdf commit a7e3f12

File tree

3 files changed

+66
-50
lines changed

3 files changed

+66
-50
lines changed

FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MessagesListFragment.kt

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,27 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
124124

125125
private var footerProgressView: View? = null
126126
private var tracker: SelectionTracker<Long>? = null
127-
private var keyProvider: CustomStableIdKeyProvider? = null
128127
private var actionMode: ActionMode? = null
129128
private var activeMsgEntity: MessageEntity? = null
130129
private val currentFolder: LocalFolder?
131130
get() = labelsViewModel.activeFolderLiveData.value
132131

133132
private val adapter by lazy {
134-
MsgsPagedListAdapter(null, object : MsgsPagedListAdapter.OnMessageClickListener {
133+
MsgsPagedListAdapter(object : MsgsPagedListAdapter.OnMessagesActionListener {
135134
override fun onMsgClick(msgEntity: MessageEntity) {
136135
onMsgClicked(msgEntity)
137136
}
138-
})
137+
138+
override fun onExistingMsgsChanged(snapshotOfExistingIds: Set<Long>) {
139+
val selectedIds = tracker?.selection?.mapNotNull { it }?.toSet() ?: emptySet()
140+
val irrelevantSelectedIds = selectedIds - snapshotOfExistingIds
141+
tracker?.setItemsSelected(irrelevantSelectedIds, false)
142+
}
143+
}) { key -> tracker?.isSelected(key) ?: false }
139144
}
140145

146+
private val keyProvider by lazy { CustomStableIdKeyProvider(adapter) }
147+
141148
private var keepSelectionInMemory = false
142149
private var isForceSendingEnabled: Boolean = true
143150

@@ -471,9 +478,6 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
471478
}
472479
}
473480

474-
/**
475-
* Try to load a next messages from an IMAP server.
476-
*/
477481
private fun loadNextMsgs() {
478482
if (isOutboxFolder) {
479483
return
@@ -485,8 +489,7 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
485489
if (currentFolder == null) {
486490
labelsViewModel.loadLabels()
487491
} else {
488-
//adapter.changeProgress(true)
489-
//msgsViewModel.loadMsgsFromRemoteServer()
492+
adapter.refresh()
490493
}
491494
} else {
492495
footerProgressView?.visibility = View.GONE
@@ -529,33 +532,28 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
529532
)
530533
binding?.recyclerViewMsgs?.adapter = adapter.withLoadStateFooter(MsgsLoadStateAdapter())
531534
setupItemTouchHelper()
532-
//setupSelectionTracker()
535+
setupSelectionTracker()
533536
setupBottomOverScroll()
534537
}
535538

536539
private fun setupSelectionTracker() {
537-
//adapter.tracker = null
538540
binding?.recyclerViewMsgs?.let { recyclerView ->
539-
keyProvider = CustomStableIdKeyProvider(recyclerView)
540-
keyProvider?.let {
541-
tracker = SelectionTracker.Builder(
542-
MessagesListFragment::class.java.simpleName,
543-
recyclerView,
544-
it,
545-
MsgItemDetailsLookup(recyclerView),
546-
StorageStrategy.createLongStorage()
547-
).withSelectionPredicate(object : SelectionTracker.SelectionPredicate<Long>() {
548-
override fun canSetStateForKey(key: Long, nextState: Boolean): Boolean =
549-
currentFolder?.searchQuery == null
550-
551-
override fun canSetStateAtPosition(position: Int, nextState: Boolean): Boolean =
552-
currentFolder?.searchQuery == null
553-
554-
override fun canSelectMultiple(): Boolean = true
555-
}).build()
556-
tracker?.addObserver(selectionObserver)
557-
//adapter.tracker = tracker
558-
}
541+
tracker = SelectionTracker.Builder(
542+
MessagesListFragment::class.java.simpleName,
543+
recyclerView,
544+
keyProvider,
545+
MsgItemDetailsLookup(recyclerView),
546+
StorageStrategy.createLongStorage()
547+
).withSelectionPredicate(object : SelectionTracker.SelectionPredicate<Long>() {
548+
override fun canSetStateForKey(key: Long, nextState: Boolean): Boolean =
549+
currentFolder?.searchQuery == null
550+
551+
override fun canSetStateAtPosition(position: Int, nextState: Boolean): Boolean =
552+
currentFolder?.searchQuery == null
553+
554+
override fun canSelectMultiple(): Boolean = true
555+
}).build()
556+
tracker?.addObserver(selectionObserver)
559557
}
560558
}
561559

@@ -729,7 +727,7 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
729727
&& System.currentTimeMillis() - lastCallTime >= TIMEOUT_BETWEEN_ACTIONS
730728
) {
731729
if (msgsViewModel.loadMsgsFromRemoteServerLiveData.value?.status != Result.Status.LOADING) {
732-
//msgsViewModel.loadMsgsFromRemoteServer()
730+
adapter.refresh()
733731
}
734732
}
735733
}
@@ -807,10 +805,10 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
807805

808806
if (isChangeSeenStateActionEnabled()) {
809807
val id = tracker?.selection?.first() ?: return true
810-
/*val msgEntity = adapter.getMsgEntity(keyProvider?.getPosition(id))
808+
val msgEntity = adapter.getMessageEntity(keyProvider.getPosition(id))
811809

812810
menuActionMarkUnread?.isVisible = msgEntity?.isSeen == true
813-
menuActionMarkRead?.isVisible = msgEntity?.isSeen != true*/
811+
menuActionMarkRead?.isVisible = msgEntity?.isSeen != true
814812
}
815813

816814
return true
@@ -1220,7 +1218,7 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
12201218
tracker?.clearSelection()
12211219

12221220
val newFolder = currentFolder
1223-
adapter.currentFolder = newFolder
1221+
adapter.switchFolder(newFolder)
12241222

12251223
val isFolderNameEmpty = newFolder?.fullName?.isEmpty()
12261224
val isItSyncOrOutboxFolder = isItSyncOrOutboxFolder(newFolder)
@@ -1246,7 +1244,6 @@ class MessagesListFragment : BaseFragment<FragmentMessagesListBinding>(),
12461244
getString(R.string.progress_message, progress, message)
12471245
} else {
12481246
binding?.textViewActionProgress?.text = null
1249-
//adapter.changeProgress(false)
12501247
}
12511248
}
12521249

FlowCrypt/src/main/java/com/flowcrypt/email/ui/adapter/MsgsPagedListAdapter.kt

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,24 @@ import javax.mail.internet.InternetAddress
4545
4646
*/
4747
class MsgsPagedListAdapter(
48-
var currentFolder: LocalFolder? = null,
49-
private val onMessageClickListener: OnMessageClickListener? = null
48+
private val onMessagesActionListener: OnMessagesActionListener? = null,
49+
private val selectionChecker: (key: Long) -> Boolean
5050
) : PagingDataAdapter<MessageEntity, MsgsPagedListAdapter.MessageViewHolder>(ITEM_CALLBACK) {
5151
private val senderNamePattern: Pattern = prepareSenderNamePattern()
52+
private val keyPositionsMap = mutableMapOf<Long, Int>()
53+
var currentFolder: LocalFolder? = null
54+
private set
55+
56+
init {
57+
addOnPagesUpdatedListener {
58+
val ids = snapshot().items.mapNotNull { it.id }.toSet()
59+
onMessagesActionListener?.onExistingMsgsChanged(ids)
60+
}
61+
}
5262

5363
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
5464
val msgEntity = getItem(position) ?: return
65+
msgEntity.id?.let { keyPositionsMap[msgEntity.id] = holder.absoluteAdapterPosition }
5566
holder.bind(msgEntity)
5667
}
5768

@@ -65,6 +76,15 @@ class MsgsPagedListAdapter(
6576
return getItem(position)
6677
}
6778

79+
fun getPositionByIds(ids: Long): Int? {
80+
return keyPositionsMap[ids]
81+
}
82+
83+
fun switchFolder(newFolder: LocalFolder?) {
84+
keyPositionsMap.clear()
85+
currentFolder = newFolder
86+
}
87+
6888
/**
6989
* Prepare a [Pattern] which will be used for finding some information in the sender name.
7090
* This pattern is case insensitive.
@@ -229,18 +249,21 @@ class MsgsPagedListAdapter(
229249

230250
inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
231251
val binding: MessagesListItemBinding = MessagesListItemBinding.bind(itemView)
252+
private var messageEntity: MessageEntity? = null
232253

233254
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
234255
object : ItemDetailsLookup.ItemDetails<Long>() {
235-
override fun getPosition(): Int = bindingAdapterPosition
236-
override fun getSelectionKey(): Long = itemId
256+
override fun getPosition(): Int = absoluteAdapterPosition
257+
override fun getSelectionKey(): Long? = messageEntity?.id
237258
}
238259

239260
fun bind(value: MessageEntity) {
261+
messageEntity = value
240262
val context = itemView.context
241263

264+
itemView.isActivated = value.id?.let { selectionChecker.invoke(it) } ?: false
242265
itemView.setOnClickListener {
243-
onMessageClickListener?.onMsgClick(value)
266+
onMessagesActionListener?.onMsgClick(value)
244267
}
245268

246269
val subject = if (TextUtils.isEmpty(value.subject)) {
@@ -325,8 +348,9 @@ class MsgsPagedListAdapter(
325348
}
326349
}
327350

328-
interface OnMessageClickListener {
351+
interface OnMessagesActionListener {
329352
fun onMsgClick(msgEntity: MessageEntity)
353+
fun onExistingMsgsChanged(snapshotOfExistingIds: Set<Long>)
330354
}
331355

332356
companion object {

FlowCrypt/src/main/java/com/flowcrypt/email/ui/adapter/selection/CustomStableIdKeyProvider.kt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,22 @@ package com.flowcrypt.email.ui.adapter.selection
77

88
import androidx.recyclerview.selection.ItemKeyProvider
99
import androidx.recyclerview.widget.RecyclerView
10+
import com.flowcrypt.email.ui.adapter.MsgsPagedListAdapter
1011

1112
/**
1213
* @author Denis Bondarenko
1314
* Date: 1/8/20
1415
* Time: 4:44 PM
1516
1617
*/
17-
class CustomStableIdKeyProvider(private val recyclerView: RecyclerView) :
18+
class CustomStableIdKeyProvider(private val adapter: MsgsPagedListAdapter) :
1819
ItemKeyProvider<Long>(SCOPE_CACHED) {
19-
init {
20-
requireNotNull(recyclerView.adapter)
21-
require(recyclerView.adapter?.hasStableIds() == true) {
22-
"Adapter should have stable ids"
23-
}
24-
}
2520

2621
override fun getKey(position: Int): Long? {
27-
return recyclerView.adapter?.getItemId(position)
22+
return adapter.getMessageEntity(position)?.id
2823
}
2924

3025
override fun getPosition(key: Long): Int {
31-
return recyclerView.findViewHolderForItemId(key)?.adapterPosition ?: RecyclerView.NO_POSITION
26+
return adapter.getPositionByIds(key) ?: RecyclerView.NO_POSITION
3227
}
3328
}

0 commit comments

Comments
 (0)