@@ -46,9 +46,7 @@ import io.realm.kotlin.Realm
46
46
import io.realm.kotlin.TypedRealm
47
47
import io.realm.kotlin.ext.copyFromRealm
48
48
import io.realm.kotlin.ext.toRealmList
49
- import io.realm.kotlin.query.RealmResults
50
49
import io.realm.kotlin.types.RealmList
51
- import io.realm.kotlin.types.RealmSet
52
50
import io.sentry.Sentry
53
51
import kotlinx.coroutines.*
54
52
import okhttp3.OkHttpClient
@@ -518,20 +516,8 @@ class RefreshController @Inject constructor(
518
516
scope.ensureActive()
519
517
520
518
initMessageLocalValues(remoteMessage, folder)
521
-
522
519
addedMessagesUids.add(remoteMessage.shortUid)
523
-
524
- refreshStrategy.updateExistingMessageWhenAdded(remoteMessage, realm = this )
525
-
526
- val newThread = if (isConversationMode) {
527
- val (thread, impactThreads) = handleAddedMessage(scope, remoteMessage)
528
- impactedThreadsManaged + = impactThreads
529
- thread
530
- } else {
531
- remoteMessage.toThread()
532
- }
533
-
534
- newThread?.let { impactedThreadsManaged + = putNewThreadInRealm(it) }
520
+ impactedThreadsManaged + = refreshStrategy.handleAddedMessages(scope, remoteMessage, isConversationMode, realm = this )
535
521
}
536
522
537
523
addSentryBreadcrumbForAddedUidsInFolder(addedMessagesUids)
@@ -547,11 +533,6 @@ class RefreshController @Inject constructor(
547
533
return impactedThreadsUnmanaged
548
534
}
549
535
550
- private fun MutableRealm.updateExistingMessage (remoteMessage : Message ) {
551
- val isMessageAlreadyInRealm = MessageController .getMessage(remoteMessage.uid, realm = this ) != null
552
- if (isMessageAlreadyInRealm) MessageController .upsertMessage(remoteMessage, realm = this )
553
- }
554
-
555
536
private fun initMessageLocalValues (remoteMessage : Message , folder : Folder ) {
556
537
remoteMessage.initLocalValues(
557
538
MessageInitialState (
@@ -564,129 +545,6 @@ class RefreshController @Inject constructor(
564
545
latestCalendarEventResponse = null ,
565
546
)
566
547
}
567
-
568
- private fun MutableRealm.handleAddedMessage (scope : CoroutineScope , remoteMessage : Message ): Pair <Thread ?, Set <Thread >> {
569
-
570
- // Other pre-existing Threads that will also require this Message and will provide the prior Messages for this new Thread.
571
- val existingThreads = ThreadController .getThreadsByMessageIds(remoteMessage.messageIds, realm = this )
572
- val existingMessages = getExistingMessages(existingThreads)
573
-
574
- val thread = createNewThreadIfRequired(scope, remoteMessage, existingThreads, existingMessages)
575
- val impactedThreads = updateExistingThreads(scope, remoteMessage, existingThreads, existingMessages)
576
-
577
- return thread to impactedThreads
578
- }
579
-
580
- private fun TypedRealm.createNewThreadIfRequired (
581
- scope : CoroutineScope ,
582
- newMessage : Message ,
583
- existingThreads : List <Thread >,
584
- existingMessages : Set <Message >,
585
- ): Thread ? {
586
- var newThread: Thread ? = null
587
-
588
- if (existingThreads.none { it.folderId == newMessage.folderId }) {
589
-
590
- newThread = newMessage.toThread()
591
-
592
- addPreviousMessagesToThread(scope, newThread, existingMessages)
593
- }
594
-
595
- return newThread
596
- }
597
-
598
- private fun MutableRealm.updateExistingThreads (
599
- scope : CoroutineScope ,
600
- remoteMessage : Message ,
601
- existingThreads : RealmResults <Thread >,
602
- existingMessages : Set <Message >,
603
- ): Set <Thread > {
604
-
605
- val impactedThreads = mutableSetOf<Thread >()
606
-
607
- // Update already existing Threads (i.e. in other Folders, or specific cases like Snoozed)
608
- impactedThreads + = addAllMessagesToAllThreads(scope, remoteMessage, existingThreads, existingMessages)
609
-
610
- // Some Messages don't have references to all previous Messages of the Thread (ex: these from the iOS Mail app).
611
- // Because we are missing the links between Messages, it will create multiple Threads for the same Folder.
612
- // Hence, we need to find these duplicates, and remove them.
613
- val duplicatedThreads = identifyExtraDuplicatedThreads(remoteMessage.messageIds)
614
- impactedThreads - = duplicatedThreads
615
- duplicatedThreads.forEach(::delete) // Delete the other Threads. Sorry bro, you won't be missed.
616
-
617
- return impactedThreads
618
- }
619
-
620
- private fun MutableRealm.addAllMessagesToAllThreads (
621
- scope : CoroutineScope ,
622
- remoteMessage : Message ,
623
- existingThreads : RealmResults <Thread >,
624
- existingMessages : Set <Message >,
625
- ): Set <Thread > {
626
-
627
- if (existingThreads.isEmpty()) return emptySet()
628
-
629
- val allExistingMessages = buildSet {
630
- addAll(existingMessages)
631
- add(remoteMessage)
632
- }
633
-
634
- return buildSet {
635
- existingThreads.forEach { thread ->
636
- scope.ensureActive()
637
-
638
- allExistingMessages.forEach { existingMessage ->
639
- scope.ensureActive()
640
-
641
- if (! thread.messages.contains(existingMessage)) {
642
- thread.messagesIds + = existingMessage.messageIds
643
- thread.addMessageWithConditions(existingMessage, realm = this @addAllMessagesToAllThreads)
644
- }
645
- }
646
-
647
- add(thread)
648
- }
649
- }
650
- }
651
-
652
- private fun MutableRealm.identifyExtraDuplicatedThreads (messageIds : RealmSet <String >): Set <Thread > {
653
-
654
- // Create a map with all duplicated Threads of the same Thread in a list.
655
- val map = mutableMapOf<String , MutableList <Thread >>()
656
- ThreadController .getThreadsByMessageIds(messageIds, realm = this ).forEach {
657
- map.getOrPut(it.folderId) { mutableListOf () }.add(it)
658
- }
659
-
660
- return buildSet {
661
- map.values.forEach { threads ->
662
- // We want to keep only 1 duplicated Thread, so we skip the 1st one. (He's the chosen one!)
663
- addAll(threads.subList(1 , threads.count()))
664
- }
665
- }
666
- }
667
-
668
- private fun MutableRealm.putNewThreadInRealm (newThread : Thread ): Thread {
669
- return ThreadController .upsertThread(newThread, realm = this )
670
- }
671
-
672
- private fun getExistingMessages (existingThreads : List <Thread >): Set <Message > {
673
- return existingThreads.flatMapTo(mutableSetOf ()) { it.messages }
674
- }
675
-
676
- private fun TypedRealm.addPreviousMessagesToThread (
677
- scope : CoroutineScope ,
678
- newThread : Thread ,
679
- referenceMessages : Set <Message >,
680
- ) {
681
- referenceMessages.forEach { message ->
682
- scope.ensureActive()
683
-
684
- newThread.apply {
685
- messagesIds + = message.computeMessageIds()
686
- addMessageWithConditions(message, realm = this @addPreviousMessagesToThread)
687
- }
688
- }
689
- }
690
548
// endregion
691
549
692
550
// region API calls
0 commit comments