@@ -46,7 +46,7 @@ import com.infomaniak.mail.data.models.calendar.Attendee.AttendanceState
46
46
import com.infomaniak.mail.data.models.correspondent.Recipient
47
47
import com.infomaniak.mail.data.models.message.Message
48
48
import com.infomaniak.mail.databinding.ItemMessageBinding
49
- import com.infomaniak.mail.ui.main.thread.ThreadAdapter.ThreadViewHolder
49
+ import com.infomaniak.mail.ui.main.thread.ThreadAdapter.MessageViewHolder
50
50
import com.infomaniak.mail.utils.*
51
51
import com.infomaniak.mail.utils.AttachmentIntentUtils.AttachmentIntentType
52
52
import com.infomaniak.mail.utils.MailDateFormatUtils.mailFormattedDate
@@ -69,19 +69,21 @@ class ThreadAdapter(
69
69
private val isForPrinting : Boolean = false ,
70
70
private val isCalendarEventExpandedMap : MutableMap <String , Boolean > = mutableMapOf(),
71
71
private var threadAdapterCallbacks : ThreadAdapterCallbacks ? = null ,
72
- ) : ListAdapter<Message, ThreadViewHolder >(MessageDiffCallback ()) {
72
+ ) : ListAdapter<Message, MessageViewHolder >(MessageDiffCallback ()) {
73
73
74
74
inline val messages: MutableList <Message > get() = currentList
75
75
76
76
var isExpandedMap = mutableMapOf<String , Boolean >()
77
+
78
+ // region Auto-scroll at Thread opening
77
79
var initialSetOfExpandedMessagesUids = setOf<String >()
78
80
private val currentSetOfLoadedExpandedMessagesUids = mutableSetOf<String >()
79
81
private var hasNotScrolledYet = true
82
+ // endregion
80
83
81
84
private val manuallyAllowedMessageUids = mutableSetOf<String >()
82
85
var isThemeTheSameMap = mutableMapOf<String , Boolean >()
83
86
84
-
85
87
private lateinit var recyclerView: RecyclerView
86
88
private val webViewUtils by lazy { WebViewUtils (recyclerView.context) }
87
89
@@ -104,8 +106,8 @@ class ThreadAdapter(
104
106
105
107
override fun getItemCount (): Int = runCatchingRealm { messages.count() }.getOrDefault(0 )
106
108
107
- override fun onCreateViewHolder (parent : ViewGroup , viewType : Int ): ThreadViewHolder {
108
- return ThreadViewHolder (
109
+ override fun onCreateViewHolder (parent : ViewGroup , viewType : Int ): MessageViewHolder {
110
+ return MessageViewHolder (
109
111
ItemMessageBinding .inflate(LayoutInflater .from(parent.context), parent, false ),
110
112
shouldLoadDistantResources,
111
113
threadAdapterCallbacks?.onContactClicked,
@@ -114,12 +116,12 @@ class ThreadAdapter(
114
116
)
115
117
}
116
118
117
- override fun onBindViewHolder (holder : ThreadViewHolder , position : Int , payloads : MutableList <Any >) = runCatchingRealm {
119
+ override fun onBindViewHolder (holder : MessageViewHolder , position : Int , payloads : MutableList <Any >) = runCatchingRealm {
118
120
with (holder.binding) {
119
121
val payload = payloads.firstOrNull()
120
122
if (payload !is NotifyType ) {
121
123
super .onBindViewHolder(holder, position, payloads)
122
- return
124
+ return @runCatchingRealm
123
125
}
124
126
125
127
val message = messages[position]
@@ -143,7 +145,7 @@ class ThreadAdapter(
143
145
}
144
146
}.getOrDefault(Unit )
145
147
146
- override fun onBindViewHolder (holder : ThreadViewHolder , position : Int ) = with (holder) {
148
+ override fun onBindViewHolder (holder : MessageViewHolder , position : Int ) = with (holder) {
147
149
val message = messages[position]
148
150
149
151
initMapForNewMessage(message, position)
@@ -157,7 +159,7 @@ class ThreadAdapter(
157
159
onExpandOrCollapseMessage(message, shouldTrack = false )
158
160
}
159
161
160
- private fun ThreadViewHolder .bindCalendarEvent (message : Message ) {
162
+ private fun MessageViewHolder .bindCalendarEvent (message : Message ) {
161
163
val calendarAttachment = message.calendarAttachment ? : return
162
164
val calendarEvent = message.latestCalendarEventResponse?.calendarEvent
163
165
@@ -200,14 +202,14 @@ class ThreadAdapter(
200
202
if (isThemeTheSameMap[message.uid] == null ) isThemeTheSameMap[message.uid] = true
201
203
}
202
204
203
- private fun ThreadViewHolder .toggleContentAndQuoteTheme (messageUid : String ) = with (binding) {
205
+ private fun MessageViewHolder .toggleContentAndQuoteTheme (messageUid : String ) = with (binding) {
204
206
val isThemeTheSame = isThemeTheSameMap[messageUid]!!
205
207
bodyWebView.toggleWebViewTheme(isThemeTheSame)
206
208
fullMessageWebView.toggleWebViewTheme(isThemeTheSame)
207
209
toggleFrameLayoutsTheme(isThemeTheSame)
208
210
}
209
211
210
- private fun ThreadViewHolder .loadContentAndQuote (message : Message ) {
212
+ private fun MessageViewHolder .loadContentAndQuote (message : Message ) {
211
213
val body = message.body
212
214
val splitBody = message.splitBody
213
215
@@ -221,16 +223,16 @@ class ThreadAdapter(
221
223
}
222
224
}
223
225
224
- private fun ThreadViewHolder .loadBodyInWebView (uid : String , body : String , type : String ) = with (binding) {
226
+ private fun MessageViewHolder .loadBodyInWebView (uid : String , body : String , type : String ) = with (binding) {
225
227
bodyWebView.applyWebViewContent(uid, body, type)
226
228
}
227
229
228
- private fun ThreadViewHolder .loadQuoteInWebView (uid : String , quote : String? , type : String ) = with (binding) {
230
+ private fun MessageViewHolder .loadQuoteInWebView (uid : String , quote : String? , type : String ) = with (binding) {
229
231
if (quote == null ) return @with
230
232
fullMessageWebView.applyWebViewContent(uid, quote, type)
231
233
}
232
234
233
- private fun ThreadViewHolder .toggleWebViews (message : Message ) = with (binding) {
235
+ private fun MessageViewHolder .toggleWebViews (message : Message ) = with (binding) {
234
236
isQuoteCollapsed = ! isQuoteCollapsed
235
237
loadContentAndQuote(message)
236
238
}
@@ -279,7 +281,7 @@ class ThreadAdapter(
279
281
}
280
282
}
281
283
282
- private fun ThreadViewHolder .bindHeader (message : Message ) = with (binding) {
284
+ private fun MessageViewHolder .bindHeader (message : Message ) = with (binding) {
283
285
val messageDate = message.date.toDate()
284
286
285
287
if (message.isDraft) {
@@ -321,7 +323,7 @@ class ThreadAdapter(
321
323
bccGroup.isVisible = message.bcc.isNotEmpty()
322
324
}
323
325
324
- private fun ThreadViewHolder .handleHeaderClick (message : Message ) = with (binding) {
326
+ private fun MessageViewHolder .handleHeaderClick (message : Message ) = with (binding) {
325
327
messageHeader.setOnClickListener {
326
328
if (isExpandedMap[message.uid] == true ) {
327
329
isExpandedMap[message.uid] = false
@@ -347,7 +349,7 @@ class ThreadAdapter(
347
349
}
348
350
}
349
351
350
- private fun ThreadViewHolder .bindRecipientDetails (message : Message , messageDate : Date ) = with (binding) {
352
+ private fun MessageViewHolder .bindRecipientDetails (message : Message , messageDate : Date ) = with (binding) {
351
353
352
354
fromAdapter.updateList(message.from.toList())
353
355
toAdapter.updateList(message.to.toList())
@@ -363,7 +365,7 @@ class ThreadAdapter(
363
365
detailedMessageDate.text = mostDetailedDate(context, messageDate)
364
366
}
365
367
366
- private fun ThreadViewHolder .bindAlerts (messageUid : String ) = with (binding) {
368
+ private fun MessageViewHolder .bindAlerts (messageUid : String ) = with (binding) {
367
369
distantImagesAlert.onAction1 {
368
370
bodyWebViewClient.unblockDistantResources()
369
371
fullMessageWebViewClient.unblockDistantResources()
@@ -388,7 +390,7 @@ class ThreadAdapter(
388
390
private fun ItemMessageBinding.areOneOrMoreAlertsVisible () = alerts.children.any { it.isVisible }
389
391
390
392
@SuppressLint(" SetTextI18n" )
391
- private fun ThreadViewHolder .bindAttachment (message : Message ) = with (binding) {
393
+ private fun MessageViewHolder .bindAttachment (message : Message ) = with (binding) {
392
394
val attachments = message.attachments
393
395
val fileSize = formatAttachmentFileSize(attachments)
394
396
attachmentLayout.attachmentsSizeText.text = context.resources.getQuantityString(
@@ -413,12 +415,12 @@ class ThreadAdapter(
413
415
return Formatter .formatShortFileSize(context, totalAttachmentsFileSizeInBytes)
414
416
}
415
417
416
- private fun ThreadViewHolder .bindContent (message : Message ) {
418
+ private fun MessageViewHolder .bindContent (message : Message ) {
417
419
binding.messageLoader.isVisible = message.splitBody == null
418
420
message.splitBody?.let { splitBody -> bindBody(message, hasQuote = splitBody.quote != null ) }
419
421
}
420
422
421
- private fun ThreadViewHolder .bindBody (message : Message , hasQuote : Boolean ) = with (binding) {
423
+ private fun MessageViewHolder .bindBody (message : Message , hasQuote : Boolean ) = with (binding) {
422
424
bodyWebView.setupLinkContextualMenu { data, type ->
423
425
threadAdapterCallbacks?.promptLink?.invoke(data, type)
424
426
}
@@ -495,7 +497,7 @@ class ThreadAdapter(
495
497
}
496
498
}
497
499
498
- private fun ThreadViewHolder .onExpandOrCollapseMessage (message : Message , shouldTrack : Boolean = true) = with (binding) {
500
+ private fun MessageViewHolder .onExpandOrCollapseMessage (message : Message , shouldTrack : Boolean = true) = with (binding) {
499
501
val isExpanded = isExpandedMap[message.uid]!!
500
502
501
503
if (shouldTrack) context.trackMessageEvent(" openMessage" , isExpanded)
@@ -579,7 +581,7 @@ class ThreadAdapter(
579
581
}
580
582
581
583
override fun getChangePayload (oldItem : Message , newItem : Message ): Any? {
582
- // If everything but attendees is the same, then we know the only thing that could've changed is attendees
584
+ // If everything but Attendees is the same, then we know the only thing that could've changed is Attendees.
583
585
return if (everythingButAttendeesIsTheSame(oldItem, newItem)) NotifyType .ONLY_REBIND_CALENDAR_ATTENDANCE else null
584
586
}
585
587
@@ -600,7 +602,25 @@ class ThreadAdapter(
600
602
}
601
603
}
602
604
603
- class ThreadViewHolder (
605
+ data class ThreadAdapterCallbacks (
606
+ var onBodyWebViewFinishedLoading : (() -> Unit )? = null ,
607
+ var onContactClicked : ((contact: Recipient ) -> Unit )? = null ,
608
+ var onDeleteDraftClicked : ((message: Message ) -> Unit )? = null ,
609
+ var onDraftClicked : ((message: Message ) -> Unit )? = null ,
610
+ var onAttachmentClicked : ((attachment: Attachment ) -> Unit )? = null ,
611
+ var onAttachmentOptionsClicked : ((attachment: Attachment ) -> Unit )? = null ,
612
+ var onDownloadAllClicked : ((message: Message ) -> Unit )? = null ,
613
+ var onReplyClicked : ((Message ) -> Unit )? = null ,
614
+ var onMenuClicked : ((Message ) -> Unit )? = null ,
615
+ var onAllExpandedMessagesLoaded : (() -> Unit )? = null ,
616
+ var navigateToNewMessageActivity : ((Uri ) -> Unit )? = null ,
617
+ var navigateToAttendeeBottomSheet : ((List <Attendee >) -> Unit )? = null ,
618
+ var navigateToDownloadProgressDialog : ((Attachment , AttachmentIntentType ) -> Unit )? = null ,
619
+ var replyToCalendarEvent : ((AttendanceState , Message ) -> Unit )? = null ,
620
+ var promptLink : ((String , ContextMenuType ) -> Unit )? = null ,
621
+ )
622
+
623
+ class MessageViewHolder (
604
624
val binding : ItemMessageBinding ,
605
625
private val shouldLoadDistantResources : Boolean ,
606
626
onContactClicked : ((contact: Recipient ) -> Unit )? ,
@@ -674,24 +694,6 @@ class ThreadAdapter(
674
694
}
675
695
}
676
696
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 onAttachmentOptionsClicked : ((attachment: Attachment ) -> Unit )? = null ,
684
- var onDownloadAllClicked : ((message: Message ) -> Unit )? = null ,
685
- var onReplyClicked : ((Message ) -> Unit )? = null ,
686
- var onMenuClicked : ((Message ) -> Unit )? = null ,
687
- var onAllExpandedMessagesLoaded : (() -> Unit )? = null ,
688
- var navigateToNewMessageActivity : ((Uri ) -> Unit )? = null ,
689
- var navigateToAttendeeBottomSheet : ((List <Attendee >) -> Unit )? = null ,
690
- var navigateToDownloadProgressDialog : ((Attachment , AttachmentIntentType ) -> Unit )? = null ,
691
- var replyToCalendarEvent : ((AttendanceState , Message ) -> Unit )? = null ,
692
- var promptLink : ((String , ContextMenuType ) -> Unit )? = null ,
693
- )
694
-
695
697
companion object {
696
698
697
699
private val contextMenuTypeForHitTestResultType = mapOf (
0 commit comments