Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
Elouan1411 marked this conversation as resolved.
//endregion

//region Local data (Transient)
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ object ApiRepository : ApiRepositoryCore() {
suspend fun getMessage(messageResource: String, okHttpClient: OkHttpClient? = null): ApiResponse<Message> {
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,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ class MessageController @Inject constructor(
} else {
""
}
val isNotHiddenReminder = "(${Message::isReminder.name} == false OR ${Message::displayReminder.name} == true)"

query<Message>(
query = "$beginQuery ($containsSubject OR $containsPreview OR $containsBody) ${isNotAnEmoji}",
query = "$beginQuery ($containsSubject OR $containsPreview OR $containsBody) $isNotAnEmoji AND $isNotHiddenReminder",
searchQuery
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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
}
}

Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/com/infomaniak/mail/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down
12 changes: 9 additions & 3 deletions app/src/main/java/com/infomaniak/mail/utils/SearchUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,14 @@ class SearchUtils @Inject constructor(

fun convertLocalMessagesToSearchThreads(searchMessages: List<Message>, aliases: List<String>?): List<Thread> {
val cachedNamedFolders = mutableMapOf<String, NamedFolder>()
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() }
}
}

Expand All @@ -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?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,7 @@ object ThreadListUtils {
}
}

fun hasReminders(messages: List<Message>): Boolean = messages.any { message -> message.reminder != null }
fun hasReminders(messages: List<Message>): Boolean = messages.any { message ->
message.reminder != null && !message.shouldHideReminder
}
}
Loading