@@ -47,7 +47,7 @@ import com.infomaniak.mail.data.models.calendar.Attendee.AttendanceState
47
47
import com.infomaniak.mail.data.models.correspondent.Recipient
48
48
import com.infomaniak.mail.data.models.message.Message
49
49
import com.infomaniak.mail.databinding.ItemMessageBinding
50
- import com.infomaniak.mail.ui.main.thread.ThreadAdapter.ThreadViewHolder
50
+ import com.infomaniak.mail.ui.main.thread.ThreadAdapter.MessageViewHolder
51
51
import com.infomaniak.mail.utils.*
52
52
import com.infomaniak.mail.utils.AttachmentIntentUtils.AttachmentIntentType
53
53
import com.infomaniak.mail.utils.AttachmentIntentUtils.createDownloadDialogNavArgs
@@ -71,19 +71,21 @@ class ThreadAdapter(
71
71
private val isForPrinting : Boolean = false ,
72
72
private val isCalendarEventExpandedMap : MutableMap <String , Boolean > = mutableMapOf(),
73
73
private var threadAdapterCallbacks : ThreadAdapterCallbacks ? = null ,
74
- ) : ListAdapter<Message, ThreadViewHolder >(MessageDiffCallback ()) {
74
+ ) : ListAdapter<Message, MessageViewHolder >(MessageDiffCallback ()) {
75
75
76
76
inline val messages: MutableList <Message > get() = currentList
77
77
78
78
var isExpandedMap = mutableMapOf<String , Boolean >()
79
+
80
+ // region Auto-scroll at Thread opening
79
81
var initialSetOfExpandedMessagesUids = setOf<String >()
80
82
private val currentSetOfLoadedExpandedMessagesUids = mutableSetOf<String >()
81
83
private var hasNotScrolledYet = true
84
+ // endregion
82
85
83
86
private val manuallyAllowedMessageUids = mutableSetOf<String >()
84
87
var isThemeTheSameMap = mutableMapOf<String , Boolean >()
85
88
86
-
87
89
private lateinit var recyclerView: RecyclerView
88
90
private val webViewUtils by lazy { WebViewUtils (recyclerView.context) }
89
91
@@ -106,21 +108,21 @@ class ThreadAdapter(
106
108
107
109
override fun getItemCount (): Int = runCatchingRealm { messages.count() }.getOrDefault(0 )
108
110
109
- override fun onCreateViewHolder (parent : ViewGroup , viewType : Int ): ThreadViewHolder {
110
- return ThreadViewHolder (
111
+ override fun onCreateViewHolder (parent : ViewGroup , viewType : Int ): MessageViewHolder {
112
+ return MessageViewHolder (
111
113
ItemMessageBinding .inflate(LayoutInflater .from(parent.context), parent, false ),
112
114
shouldLoadDistantResources,
113
115
threadAdapterCallbacks?.onContactClicked,
114
116
threadAdapterCallbacks?.onAttachmentClicked,
115
117
)
116
118
}
117
119
118
- override fun onBindViewHolder (holder : ThreadViewHolder , position : Int , payloads : MutableList <Any >) = runCatchingRealm {
120
+ override fun onBindViewHolder (holder : MessageViewHolder , position : Int , payloads : MutableList <Any >) = runCatchingRealm {
119
121
with (holder.binding) {
120
122
val payload = payloads.firstOrNull()
121
123
if (payload !is NotifyType ) {
122
124
super .onBindViewHolder(holder, position, payloads)
123
- return
125
+ return @runCatchingRealm
124
126
}
125
127
126
128
val message = messages[position]
@@ -144,7 +146,7 @@ class ThreadAdapter(
144
146
}
145
147
}.getOrDefault(Unit )
146
148
147
- override fun onBindViewHolder (holder : ThreadViewHolder , position : Int ) = with (holder) {
149
+ override fun onBindViewHolder (holder : MessageViewHolder , position : Int ) = with (holder) {
148
150
val message = messages[position]
149
151
150
152
initMapForNewMessage(message, position)
@@ -158,7 +160,7 @@ class ThreadAdapter(
158
160
onExpandOrCollapseMessage(message, shouldTrack = false )
159
161
}
160
162
161
- private fun ThreadViewHolder .bindCalendarEvent (message : Message ) {
163
+ private fun MessageViewHolder .bindCalendarEvent (message : Message ) {
162
164
val attachment = message.calendarAttachment ? : return
163
165
val calendarEvent = message.latestCalendarEventResponse?.calendarEvent
164
166
@@ -204,14 +206,14 @@ class ThreadAdapter(
204
206
if (isThemeTheSameMap[message.uid] == null ) isThemeTheSameMap[message.uid] = true
205
207
}
206
208
207
- private fun ThreadViewHolder .toggleContentAndQuoteTheme (messageUid : String ) = with (binding) {
209
+ private fun MessageViewHolder .toggleContentAndQuoteTheme (messageUid : String ) = with (binding) {
208
210
val isThemeTheSame = isThemeTheSameMap[messageUid]!!
209
211
bodyWebView.toggleWebViewTheme(isThemeTheSame)
210
212
fullMessageWebView.toggleWebViewTheme(isThemeTheSame)
211
213
toggleFrameLayoutsTheme(isThemeTheSame)
212
214
}
213
215
214
- private fun ThreadViewHolder .loadContentAndQuote (message : Message ) {
216
+ private fun MessageViewHolder .loadContentAndQuote (message : Message ) {
215
217
val body = message.body
216
218
val splitBody = message.splitBody
217
219
@@ -225,16 +227,16 @@ class ThreadAdapter(
225
227
}
226
228
}
227
229
228
- private fun ThreadViewHolder .loadBodyInWebView (uid : String , body : String , type : String ) = with (binding) {
230
+ private fun MessageViewHolder .loadBodyInWebView (uid : String , body : String , type : String ) = with (binding) {
229
231
bodyWebView.applyWebViewContent(uid, body, type)
230
232
}
231
233
232
- private fun ThreadViewHolder .loadQuoteInWebView (uid : String , quote : String? , type : String ) = with (binding) {
234
+ private fun MessageViewHolder .loadQuoteInWebView (uid : String , quote : String? , type : String ) = with (binding) {
233
235
if (quote == null ) return @with
234
236
fullMessageWebView.applyWebViewContent(uid, quote, type)
235
237
}
236
238
237
- private fun ThreadViewHolder .toggleWebViews (message : Message ) = with (binding) {
239
+ private fun MessageViewHolder .toggleWebViews (message : Message ) = with (binding) {
238
240
isQuoteCollapsed = ! isQuoteCollapsed
239
241
loadContentAndQuote(message)
240
242
}
@@ -283,7 +285,7 @@ class ThreadAdapter(
283
285
}
284
286
}
285
287
286
- private fun ThreadViewHolder .bindHeader (message : Message ) = with (binding) {
288
+ private fun MessageViewHolder .bindHeader (message : Message ) = with (binding) {
287
289
val messageDate = message.date.toDate()
288
290
289
291
if (message.isDraft) {
@@ -325,7 +327,7 @@ class ThreadAdapter(
325
327
bccGroup.isVisible = message.bcc.isNotEmpty()
326
328
}
327
329
328
- private fun ThreadViewHolder .handleHeaderClick (message : Message ) = with (binding) {
330
+ private fun MessageViewHolder .handleHeaderClick (message : Message ) = with (binding) {
329
331
messageHeader.setOnClickListener {
330
332
if (isExpandedMap[message.uid] == true ) {
331
333
isExpandedMap[message.uid] = false
@@ -351,7 +353,7 @@ class ThreadAdapter(
351
353
}
352
354
}
353
355
354
- private fun ThreadViewHolder .bindRecipientDetails (message : Message , messageDate : Date ) = with (binding) {
356
+ private fun MessageViewHolder .bindRecipientDetails (message : Message , messageDate : Date ) = with (binding) {
355
357
356
358
fromAdapter.updateList(message.from.toList())
357
359
toAdapter.updateList(message.to.toList())
@@ -367,7 +369,7 @@ class ThreadAdapter(
367
369
detailedMessageDate.text = mostDetailedDate(context, messageDate)
368
370
}
369
371
370
- private fun ThreadViewHolder .bindAlerts (messageUid : String ) = with (binding) {
372
+ private fun MessageViewHolder .bindAlerts (messageUid : String ) = with (binding) {
371
373
distantImagesAlert.onAction1 {
372
374
bodyWebViewClient.unblockDistantResources()
373
375
fullMessageWebViewClient.unblockDistantResources()
@@ -392,7 +394,7 @@ class ThreadAdapter(
392
394
private fun ItemMessageBinding.areOneOrMoreAlertsVisible () = alerts.children.any { it.isVisible }
393
395
394
396
@SuppressLint(" SetTextI18n" )
395
- private fun ThreadViewHolder .bindAttachment (message : Message ) = with (binding) {
397
+ private fun MessageViewHolder .bindAttachment (message : Message ) = with (binding) {
396
398
val attachments = message.attachments
397
399
val fileSize = formatAttachmentFileSize(attachments)
398
400
attachmentLayout.attachmentsSizeText.text = context.resources.getQuantityString(
@@ -417,12 +419,12 @@ class ThreadAdapter(
417
419
return Formatter .formatShortFileSize(context, totalAttachmentsFileSizeInBytes)
418
420
}
419
421
420
- private fun ThreadViewHolder .bindContent (message : Message ) {
422
+ private fun MessageViewHolder .bindContent (message : Message ) {
421
423
binding.messageLoader.isVisible = message.splitBody == null
422
424
message.splitBody?.let { splitBody -> bindBody(message, hasQuote = splitBody.quote != null ) }
423
425
}
424
426
425
- private fun ThreadViewHolder .bindBody (message : Message , hasQuote : Boolean ) = with (binding) {
427
+ private fun MessageViewHolder .bindBody (message : Message , hasQuote : Boolean ) = with (binding) {
426
428
bodyWebView.setupLinkContextualMenu { data, type ->
427
429
threadAdapterCallbacks?.promptLink?.invoke(data, type)
428
430
}
@@ -499,7 +501,7 @@ class ThreadAdapter(
499
501
}
500
502
}
501
503
502
- private fun ThreadViewHolder .onExpandOrCollapseMessage (message : Message , shouldTrack : Boolean = true) = with (binding) {
504
+ private fun MessageViewHolder .onExpandOrCollapseMessage (message : Message , shouldTrack : Boolean = true) = with (binding) {
503
505
val isExpanded = isExpandedMap[message.uid]!!
504
506
505
507
if (shouldTrack) context.trackMessageEvent(" openMessage" , isExpanded)
@@ -604,7 +606,24 @@ class ThreadAdapter(
604
606
}
605
607
}
606
608
607
- class ThreadViewHolder (
609
+ data class ThreadAdapterCallbacks (
610
+ var onBodyWebViewFinishedLoading : (() -> Unit )? = null ,
611
+ var onContactClicked : ((contact: Recipient ) -> Unit )? = null ,
612
+ var onDeleteDraftClicked : ((message: Message ) -> Unit )? = null ,
613
+ var onDraftClicked : ((message: Message ) -> Unit )? = null ,
614
+ var onAttachmentClicked : ((attachment: Attachment ) -> Unit )? = null ,
615
+ var onDownloadAllClicked : ((message: Message ) -> Unit )? = null ,
616
+ var onReplyClicked : ((Message ) -> Unit )? = null ,
617
+ var onMenuClicked : ((Message ) -> Unit )? = null ,
618
+ var onAllExpandedMessagesLoaded : (() -> Unit )? = null ,
619
+ var navigateToNewMessageActivity : ((Uri ) -> Unit )? = null ,
620
+ var navigateToAttendeeBottomSheet : ((List <Attendee >) -> Unit )? = null ,
621
+ var navigateToDownloadProgressDialog : ((Int , Bundle ) -> Unit )? = null ,
622
+ var replyToCalendarEvent : ((AttendanceState , Message ) -> Unit )? = null ,
623
+ var promptLink : ((String , ContextMenuType ) -> Unit )? = null ,
624
+ )
625
+
626
+ class MessageViewHolder (
608
627
val binding : ItemMessageBinding ,
609
628
private val shouldLoadDistantResources : Boolean ,
610
629
onContactClicked : ((contact: Recipient ) -> Unit )? ,
@@ -674,23 +693,6 @@ class ThreadAdapter(
674
693
}
675
694
}
676
695
677
- data class ThreadAdapterCallbacks (
678
- var onBodyWebViewFinishedLoading : (() -> Unit )? = null ,
679
- var onContactClicked : ((contact: Recipient ) -> Unit )? = null ,
680
- var onDeleteDraftClicked : ((message: Message ) -> Unit )? = null ,
681
- var onDraftClicked : ((message: Message ) -> Unit )? = null ,
682
- var onAttachmentClicked : ((attachment: Attachment ) -> Unit )? = null ,
683
- var onDownloadAllClicked : ((message: Message ) -> Unit )? = null ,
684
- var onReplyClicked : ((Message ) -> Unit )? = null ,
685
- var onMenuClicked : ((Message ) -> Unit )? = null ,
686
- var onAllExpandedMessagesLoaded : (() -> Unit )? = null ,
687
- var navigateToNewMessageActivity : ((Uri ) -> Unit )? = null ,
688
- var navigateToAttendeeBottomSheet : ((List <Attendee >) -> Unit )? = null ,
689
- var navigateToDownloadProgressDialog : ((Int , Bundle ) -> Unit )? = null ,
690
- var replyToCalendarEvent : ((AttendanceState , Message ) -> Unit )? = null ,
691
- var promptLink : ((String , ContextMenuType ) -> Unit )? = null ,
692
- )
693
-
694
696
companion object {
695
697
696
698
private val contextMenuTypeForHitTestResultType = mapOf (
0 commit comments