diff --git a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/message/Message.kt b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/message/Message.kt index bdba2e2482..ce3fb7550e 100644 --- a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/message/Message.kt +++ b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/message/Message.kt @@ -144,6 +144,10 @@ class Message : RealmObject, Snoozable { var reminder: ReminderMessageInfo? = null @SerialName("reminder_action") var reminderAction: String? = null + @SerialName("is_reminder") + var isReminder: Boolean = false + @SerialName("display_reminder") + var displayReminder: Boolean = false //endregion //region Local data (Transient) @@ -209,6 +213,8 @@ class Message : RealmObject, Snoozable { val isReaction get() = emojiReaction != null + val shouldHideReminder get() = isReminder && !displayReminder + val threads by backlinks(Thread::messages) val threadsDuplicatedIn by backlinks(Thread::duplicates) diff --git a/app/src/main/java/com/infomaniak/mail/data/api/ApiRepository.kt b/app/src/main/java/com/infomaniak/mail/data/api/ApiRepository.kt index 6cf9fbdf8e..acb9ee56ee 100644 --- a/app/src/main/java/com/infomaniak/mail/data/api/ApiRepository.kt +++ b/app/src/main/java/com/infomaniak/mail/data/api/ApiRepository.kt @@ -177,7 +177,10 @@ object ApiRepository : ApiRepositoryCore() { suspend fun getMessage(messageResource: String, okHttpClient: OkHttpClient? = null): ApiResponse { val encryptionWiths = "auto_uncrypt,recipient_provider_source" return callApi( - url = ApiRoutes.resource("$messageResource?name=prefered_format&value=html&with=$encryptionWiths,emoji_reactions_per_message"), + url = ApiRoutes.resource( + "$messageResource?name=prefered_format&value=html" + + "&with=$encryptionWiths,emoji_reactions_per_message,reminder_status_per_message", + ), method = GET, okHttpClient = okHttpClient ?: HttpClient.okHttpClientWithTokenInterceptor, ) diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/MessageController.kt b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/MessageController.kt index a3cb9a32d8..ad8e63ff99 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/MessageController.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/MessageController.kt @@ -185,9 +185,10 @@ class MessageController @Inject constructor( } else { "" } + val isNotHiddenReminder = "(${Message::isReminder.name} == false OR ${Message::displayReminder.name} == true)" query( - query = "$beginQuery ($containsSubject OR $containsPreview OR $containsBody) ${isNotAnEmoji}", + query = "$beginQuery ($containsSubject OR $containsPreview OR $containsBody) $isNotAnEmoji AND $isNotHiddenReminder", searchQuery ) } else { diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/refreshStrategies/ThreadRecomputations.kt b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/refreshStrategies/ThreadRecomputations.kt index 295a3bf1d6..7057545f71 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/refreshStrategies/ThreadRecomputations.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/refreshStrategies/ThreadRecomputations.kt @@ -43,7 +43,9 @@ object ThreadRecomputations { // avoid side effects and unnecessary coupling val allMessages = messages - val lastCurrentFolderMessage = allMessages.lastOrNull { it.folderId == folderId } + val lastCurrentFolderMessage = allMessages.lastOrNull { + it.folderId == folderId && !(it.shouldHideReminder && it.isScheduledDraft) + } val lastMessage = if (isFromSearch) { // In the search, some threads (such as threads from the snooze folder) won't have any messages with the same folderId // as the thread folderId. This is an expected behavior and we don't want to delete it in this case. We just need to @@ -127,7 +129,7 @@ object ThreadRecomputations { isAnswered = false } if (message.hasAttachable) hasAttachable = true - if (message.isScheduledDraft) numberOfScheduledDrafts++ + if (message.isScheduledDraft && !message.shouldHideReminder) numberOfScheduledDrafts++ updateSnoozeStatesBasedOn(message) } @@ -179,7 +181,9 @@ object ThreadRecomputations { val targetMessageIds = message.inReplyTo ?: "" val isHiddenEmojiReaction = message.isReaction && isTargetMessageInThread(targetMessageIds, threadMessageIds) - if (isHiddenEmojiReaction.not()) messagesWithContent += message + val isHiddenReminder = message.shouldHideReminder + && (isTargetMessageInThread(targetMessageIds, threadMessageIds) || message.isScheduledDraft) + if (isHiddenEmojiReaction.not() && isHiddenReminder.not()) messagesWithContent += message } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/MainActivity.kt b/app/src/main/java/com/infomaniak/mail/ui/MainActivity.kt index 963436da69..b82cfbe12e 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/MainActivity.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/MainActivity.kt @@ -362,8 +362,7 @@ class MainActivity : BaseActivity() { DraftAction.SEND, DraftAction.SEND_REACTION -> { val mailbox = mainViewModel.currentMailbox.value ?: return - // Waits 2s after cancel delay to guarantee the send action is committed - actionsViewModel.refreshFoldersAfterSendDelay(localSettings.cancelDelay + 2, mailbox) + actionsViewModel.refreshFoldersAfterSend(localSettings.cancelDelay, mailbox) val cancelResourceUrl = getString(DraftsActionsWorker.CANCEL_RESOURCE_URL_KEY) showSentDraftSnackbar(cancelResourceUrl) } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ActionsViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ActionsViewModel.kt index d6e3e3e096..38fd6ddc21 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ActionsViewModel.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/ActionsViewModel.kt @@ -845,8 +845,13 @@ class ActionsViewModel @Inject constructor( ) } - fun refreshFoldersAfterSendDelay(sendDelay: Int, mailbox: Mailbox) = viewModelScope.launch(ioCoroutineContext) { - delay((sendDelay * 1_000L).milliseconds) + fun refreshFoldersAfterSend(sendDelay: Int, mailbox: Mailbox) = viewModelScope.launch(ioCoroutineContext) { + // Wait for the send action to fully commit before refreshing folders: + // - If a send delay is set: wait for the delay plus 2 extra seconds to ensure + // the backend has finished sending the message. + // - If no delay: wait 4 seconds to ensure reminder objects are created on the backend. + val delayBeforeRefresh = if (sendDelay > 0) sendDelay + 2 else 4 + delay((delayBeforeRefresh * 1_000L).milliseconds) refreshFoldersAsync( mailbox, ImpactedFolders(mutableSetOf(FolderRole.DRAFT, FolderRole.SENT)), diff --git a/app/src/main/java/com/infomaniak/mail/utils/SearchUtils.kt b/app/src/main/java/com/infomaniak/mail/utils/SearchUtils.kt index ba703abbfc..0921a5ecc9 100644 --- a/app/src/main/java/com/infomaniak/mail/utils/SearchUtils.kt +++ b/app/src/main/java/com/infomaniak/mail/utils/SearchUtils.kt @@ -96,13 +96,14 @@ class SearchUtils @Inject constructor( fun convertLocalMessagesToSearchThreads(searchMessages: List, aliases: List?): List { val cachedNamedFolders = mutableMapOf() - return searchMessages.map { message -> + return searchMessages.mapNotNull { message -> message.toThread().apply { uid = "search-${message.uid}" isFromSearch = true + removeHiddenReminders() recomputeThread(aliases = aliases) sharedThreadProcessing(appContext, cachedNamedFolders, realm = mailboxContentRealm()) - } + }.takeIf { it.messagesWithContent.isNotEmpty() } } } @@ -126,11 +127,16 @@ class SearchUtils @Inject constructor( remoteThread.apply { isFromSearch = true setFolderId(filterFolder) + removeHiddenReminders() recomputeThread(aliases = aliases) keepOldMessagesData(filterFolder, mailboxContentRealm()) sharedThreadProcessing(appContext, cachedNamedFolders, realm = mailboxContentRealm()) } - } + }.filter { it.messagesWithContent.isNotEmpty() } + } + + private fun Thread.removeHiddenReminders() { + messages.removeAll { it.shouldHideReminder } } private fun Thread.setFolderId(filterFolder: Folder?) { diff --git a/app/src/main/java/com/infomaniak/mail/utils/ThreadListUtils.kt b/app/src/main/java/com/infomaniak/mail/utils/ThreadListUtils.kt index 361593546c..bee8afca70 100644 --- a/app/src/main/java/com/infomaniak/mail/utils/ThreadListUtils.kt +++ b/app/src/main/java/com/infomaniak/mail/utils/ThreadListUtils.kt @@ -56,5 +56,7 @@ object ThreadListUtils { } } - fun hasReminders(messages: List): Boolean = messages.any { message -> message.reminder != null } + fun hasReminders(messages: List): Boolean = messages.any { message -> + message.reminder != null && !message.shouldHideReminder + } }