diff --git a/Mail/Views/Thread List/ThreadListView.swift b/Mail/Views/Thread List/ThreadListView.swift
index ba207ce29..c1e216d97 100644
--- a/Mail/Views/Thread List/ThreadListView.swift
+++ b/Mail/Views/Thread List/ThreadListView.swift
@@ -257,7 +257,10 @@ struct ThreadListView: View {
guard let folder = newFolder else { return }
viewModel.isLoadingPage = false
+
Task {
+ await viewModel.mailboxManager.cancelRefresh()
+
fetchingTask?.cancel()
_ = await fetchingTask?.result
fetchingTask = nil
diff --git a/Mail/Views/Thread List/ThreadListViewModel.swift b/Mail/Views/Thread List/ThreadListViewModel.swift
index 55385fafe..419e126b7 100644
--- a/Mail/Views/Thread List/ThreadListViewModel.swift
+++ b/Mail/Views/Thread List/ThreadListViewModel.swift
@@ -201,15 +201,8 @@ final class DateSection: Identifiable, Equatable {
isLoadingPage = true
}
- await tryOrDisplayError {
- try await mailboxManager.threads(folder: folder.freezeIfNeeded()) {
- Task {
- withAnimation {
- self.isLoadingPage = false
- }
- }
- }
- }
+ await mailboxManager.refresh(folder: folder.freezeIfNeeded())
+
withAnimation {
isLoadingPage = false
}
diff --git a/MailCore/Cache/DraftManager.swift b/MailCore/Cache/DraftManager.swift
index 9f142f9cc..c4fa34812 100644
--- a/MailCore/Cache/DraftManager.swift
+++ b/MailCore/Cache/DraftManager.swift
@@ -156,7 +156,7 @@ public class DraftManager {
private func refreshDraftFolder(latestSendDate: Date?, mailboxManager: MailboxManager) async throws {
if let draftFolder = mailboxManager.getFolder(with: .draft)?.freeze() {
- try await mailboxManager.threads(folder: draftFolder)
+ await mailboxManager.refresh(folder: draftFolder)
if let latestSendDate = latestSendDate {
/*
@@ -165,7 +165,7 @@ public class DraftManager {
*/
let delay = latestSendDate.timeIntervalSinceNow
try await Task.sleep(nanoseconds: UInt64(1_000_000_000 * max(Double(delay), 1.5)))
- try await mailboxManager.threads(folder: draftFolder)
+ await mailboxManager.refresh(folder: draftFolder)
}
await mailboxManager.deleteOrphanDrafts()
@@ -179,7 +179,7 @@ public class DraftManager {
try await mailboxManager.delete(draft: liveDraft.freeze())
await IKSnackBar.showSnackBar(message: MailResourcesStrings.Localizable.snackbarDraftDeleted)
if let draftFolder = mailboxManager.getFolder(with: .draft)?.freeze() {
- try await mailboxManager.threads(folder: draftFolder)
+ await mailboxManager.refresh(folder: draftFolder)
}
}
}
diff --git a/MailCore/Cache/MailboxManager.swift b/MailCore/Cache/MailboxManager.swift
index efabebae5..5d6c22211 100644
--- a/MailCore/Cache/MailboxManager.swift
+++ b/MailCore/Cache/MailboxManager.swift
@@ -66,6 +66,8 @@ public class MailboxManager: ObservableObject {
public private(set) var apiFetcher: MailApiFetcher
private let backgroundRealm: BackgroundRealm
+ private lazy var refreshActor = RefreshActor(mailboxManager: self)
+
public init(mailbox: Mailbox, apiFetcher: MailApiFetcher) {
self.mailbox = mailbox
self.apiFetcher = apiFetcher
@@ -222,7 +224,7 @@ public class MailboxManager: ObservableObject {
public func flushFolder(folder: Folder) async throws -> Bool {
let response = try await apiFetcher.flushFolder(mailbox: mailbox, folderId: folder.id)
- try await threads(folder: folder)
+ await refresh(folder: folder)
return response
}
@@ -236,7 +238,7 @@ public class MailboxManager: ObservableObject {
for folder in orderedSet {
guard let impactedFolder = folder as? Folder else { continue }
- try await threads(folder: impactedFolder)
+ await refresh(folder: impactedFolder)
}
}
@@ -637,7 +639,10 @@ public class MailboxManager: ObservableObject {
public func messages(folder: Folder) async throws {
guard !Task.isCancelled else { return }
- let previousCursor = folder.cursor
+ let realm = getRealm()
+ let freshFolder = folder.fresh(using: realm)
+
+ let previousCursor = freshFolder?.cursor
var messagesUids: MessagesUids
if previousCursor == nil {
@@ -892,7 +897,7 @@ public class MailboxManager: ObservableObject {
let folders = Set(threads.compactMap(\.folder))
for thread in threads {
do {
- try thread.recomputeOrFail()
+ try thread.recomputeOrFail()
} catch {
SentrySDK.capture(message: "Thread has nil lastMessageFromFolderDate") { scope in
scope.setContext(value: ["dates": "\(thread.messages.map { $0.date })",
@@ -1173,6 +1178,16 @@ public class MailboxManager: ObservableObject {
}
}
+ // MARK: - RefreshActor
+
+ public func refresh(folder: Folder) async {
+ await refreshActor.refresh(folder: folder)
+ }
+
+ public func cancelRefresh() async {
+ await refreshActor.cancelRefresh()
+ }
+
// MARK: - Utilities
struct MessagePropertiesOptions: OptionSet {
diff --git a/MailCore/Cache/RefreshActor.swift b/MailCore/Cache/RefreshActor.swift
new file mode 100644
index 000000000..ae30f9aa2
--- /dev/null
+++ b/MailCore/Cache/RefreshActor.swift
@@ -0,0 +1,47 @@
+/*
+ Infomaniak Mail - iOS App
+ Copyright (C) 2022 Infomaniak Network SA
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+
+import Foundation
+
+public actor RefreshActor {
+ weak var mailboxManager: MailboxManager?
+
+ private var refreshTask: Task?
+
+ public init(mailboxManager: MailboxManager) {
+ self.mailboxManager = mailboxManager
+ }
+
+ public func refresh(folder: Folder) async {
+ await cancelRefresh()
+
+ refreshTask = Task {
+ await tryOrDisplayError {
+ try await mailboxManager?.threads(folder: folder)
+ refreshTask = nil
+ }
+ }
+ _ = await refreshTask?.result
+ }
+
+ public func cancelRefresh() async {
+ refreshTask?.cancel()
+ _ = await refreshTask?.result
+ refreshTask = nil
+ }
+}
diff --git a/MailNotificationServiceExtension/NotificationService.swift b/MailNotificationServiceExtension/NotificationService.swift
index 35f3cce8a..b80bed709 100644
--- a/MailNotificationServiceExtension/NotificationService.swift
+++ b/MailNotificationServiceExtension/NotificationService.swift
@@ -57,7 +57,7 @@ class NotificationService: UNNotificationServiceExtension {
// We do nothing if we don't have an initial cursor
return nil
}
- try await mailboxManager.threads(folder: inboxFolder.freezeIfNeeded())
+ await mailboxManager.refresh(folder: inboxFolder.freezeIfNeeded())
@ThreadSafe var message = mailboxManager.getRealm().object(ofType: Message.self, forPrimaryKey: uid)