Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Ensure frozen MailboxManager + ActionsManager #1358

Closed
wants to merge 7 commits into from
8 changes: 6 additions & 2 deletions MailCore/Cache/Actions/ActionsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public class ActionsManager: ObservableObject {
self.mainViewState = mainViewState
}

public func performAction(target messages: [Message], action: Action, origin: ActionOrigin) async throws {
public func performAction(@EnsureFrozen target messages: [Message], action: Action, origin: ActionOrigin) async throws {
let messagesWithDuplicates = messages.addingDuplicates()

switch action {
Expand Down Expand Up @@ -203,7 +203,11 @@ public class ActionsManager: ObservableObject {
}
}

public func performMove(messages: [Message], from originFolder: Folder?, to destinationFolder: Folder) async throws {
public func performMove(
@EnsureFrozen messages: [Message],
@EnsureFrozen from originFolder: Folder?,
@EnsureFrozen to destinationFolder: Folder
) async throws {
let messagesFromFolder = messages.filter { $0.folderId == originFolder?.remoteId }

let originalThreads = messagesFromFolder.flatMap { $0.threads.filter { $0.folder == originFolder } }
Expand Down
11 changes: 6 additions & 5 deletions MailCore/Cache/MailboxManager/MailboxManager+Draft.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import Foundation
import InfomaniakCore
import RealmSwift

// MARK: - Draft
Expand All @@ -42,7 +43,7 @@ public extension MailboxManager {
return realm.objects(Draft.self).where { $0.remoteUUID == remoteUuid }.first
}

func send(draft: Draft) async throws -> SendResponse {
func send(@EnsureFrozen draft: Draft) async throws -> SendResponse {
do {
let cancelableResponse = try await apiFetcher.send(mailbox: mailbox, draft: draft)
// Once the draft has been sent, we can delete it from Realm
Expand All @@ -64,7 +65,7 @@ public extension MailboxManager {
}
}

func save(draft: Draft) async throws {
func save(@EnsureFrozen draft: Draft) async throws {
do {
let saveResponse = try await apiFetcher.save(mailbox: mailbox, draft: draft)
await backgroundRealm.execute { realm in
Expand All @@ -91,12 +92,12 @@ public extension MailboxManager {
}
}

func delete(draft: Draft) async throws {
func delete(@EnsureFrozen draft: Draft) async throws {
try await deleteLocally(draft: draft)
try await apiFetcher.deleteDraft(mailbox: mailbox, draftId: draft.remoteUUID)
}

func delete(draftMessage: Message) async throws {
func delete(@EnsureFrozen draftMessage: Message) async throws {
guard let draftResource = draftMessage.draftResource else {
throw MailError.resourceError
}
Expand All @@ -109,7 +110,7 @@ public extension MailboxManager {
try await refreshFolder(from: [draftMessage], additionalFolder: nil)
}

func deleteLocally(draft: Draft) async throws {
func deleteLocally(@EnsureFrozen draft: Draft) async throws {
await backgroundRealm.execute { realm in
guard let liveDraft = realm.object(ofType: Draft.self, forPrimaryKey: draft.localUUID) else {
self.logError(.missingDraft)
Expand Down
8 changes: 4 additions & 4 deletions MailCore/Cache/MailboxManager/MailboxManager+Folders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public extension MailboxManager {
return frozenFolders
}

func createFolder(name: String, parent: Folder?) async throws -> Folder {
func createFolder(name: String, @EnsureFrozen parent: Folder?) async throws -> Folder {
var folder = try await apiFetcher.create(mailbox: mailbox, folder: NewFolder(name: name, path: parent?.path))

await backgroundRealm.execute { realm in
Expand All @@ -109,15 +109,15 @@ public extension MailboxManager {

// MARK: RefreshActor

func flushFolder(folder: Folder) async throws -> Bool {
func flushFolder(@EnsureFrozen folder: Folder) async throws -> Bool {
return try await refreshActor.flushFolder(folder: folder, mailbox: mailbox, apiFetcher: apiFetcher)
}

func refreshFolder(from messages: [Message], additionalFolder: Folder?) async throws {
func refreshFolder(@EnsureFrozen from messages: [Message], @EnsureFrozen additionalFolder: Folder?) async throws {
try await refreshActor.refreshFolder(from: messages, additionalFolder: additionalFolder)
}

func refreshFolderContent(_ folder: Folder) async {
func refreshFolderContent(@EnsureFrozen _ folder: Folder) async {
await refreshActor.refreshFolderContent(folder)
}

Expand Down
23 changes: 12 additions & 11 deletions MailCore/Cache/MailboxManager/MailboxManager+Message.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import Foundation
import InfomaniakCore
import InfomaniakCoreUI
import InfomaniakDI
import MailResources
Expand All @@ -25,7 +26,7 @@ import RealmSwift
// MARK: - Message

public extension MailboxManager {
func message(message: Message) async throws {
func message(@EnsureFrozen message: Message) async throws {
// Get from API
let completedMessage = try await apiFetcher.message(message: message)
completedMessage.fullyDownloaded = true
Expand All @@ -38,7 +39,7 @@ public extension MailboxManager {
}
}

func attachmentData(_ attachment: Attachment) async throws -> Data {
func attachmentData(@EnsureFrozen _ attachment: Attachment) async throws -> Data {
guard !Task.isCancelled else {
throw CancellationError()
}
Expand All @@ -57,7 +58,7 @@ public extension MailboxManager {
return data
}

func saveAttachmentLocally(attachment: Attachment) async {
func saveAttachmentLocally(@EnsureFrozen attachment: Attachment) async {
do {
let data = try await attachmentData(attachment)
let url = attachment.getLocalURL(userId: account.userId, mailboxId: mailbox.mailboxId)
Expand All @@ -72,7 +73,7 @@ public extension MailboxManager {
}
}

func markAsSeen(message: Message, seen: Bool = true) async throws {
func markAsSeen(@EnsureFrozen message: Message, seen: Bool = true) async throws {
if seen {
var messages = [message]
messages.append(contentsOf: message.duplicates)
Expand All @@ -82,12 +83,12 @@ public extension MailboxManager {
}
}

func move(messages: [Message], to folderRole: FolderRole) async throws -> UndoAction {
func move(@EnsureFrozen messages: [Message], to folderRole: FolderRole) async throws -> UndoAction {
guard let folder = getFolder(with: folderRole)?.freeze() else { throw MailError.folderNotFound }
return try await move(messages: messages, to: folder)
}

func move(messages: [Message], to folder: Folder) async throws -> UndoAction {
func move(@EnsureFrozen messages: [Message], @EnsureFrozen to folder: Folder) async throws -> UndoAction {
let response = try await apiFetcher.move(mailbox: mailbox, messages: messages, destinationId: folder.remoteId)
Task {
try await refreshFolder(from: messages, additionalFolder: folder)
Expand All @@ -104,7 +105,7 @@ public extension MailboxManager {

// MARK: Private

func markAsSeen(messages: [Message], seen: Bool) async throws {
func markAsSeen(@EnsureFrozen messages: [Message], seen: Bool) async throws {
if seen {
try await apiFetcher.markAsSeen(mailbox: mailbox, messages: messages)
} else {
Expand All @@ -118,27 +119,27 @@ public extension MailboxManager {

/// Set starred the given messages.
/// - Important: This methods stars only the messages you passes, no processing is done to add duplicates or remove drafts
func star(messages: [Message], starred: Bool) async throws {
func star(@EnsureFrozen messages: [Message], starred: Bool) async throws {
if starred {
_ = try await star(messages: messages)
} else {
_ = try await unstar(messages: messages)
}
}

private func star(messages: [Message]) async throws -> MessageActionResult {
private func star(@EnsureFrozen messages: [Message]) async throws -> MessageActionResult {
let response = try await apiFetcher.star(mailbox: mailbox, messages: messages)
try await refreshFolder(from: messages, additionalFolder: nil)
return response
}

private func unstar(messages: [Message]) async throws -> MessageActionResult {
private func unstar(@EnsureFrozen messages: [Message]) async throws -> MessageActionResult {
let response = try await apiFetcher.unstar(mailbox: mailbox, messages: messages)
try await refreshFolder(from: messages, additionalFolder: nil)
return response
}

private func undoAction(for cancellableResponse: UndoResponse, and messages: [Message]) -> UndoAction {
private func undoAction(for cancellableResponse: UndoResponse, @EnsureFrozen and messages: [Message]) -> UndoAction {
let undoBlock = {
try await self.refreshFolder(from: messages, additionalFolder: nil)
}
Expand Down
12 changes: 8 additions & 4 deletions MailCore/Cache/MailboxManager/MailboxManager+Search.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ public extension MailboxManager {
}
}

func searchThreads(searchFolder: Folder?, filterFolderId: String, filter: Filter = .all,
func searchThreads(@EnsureFrozen searchFolder: Folder?,
filterFolderId: String,
filter: Filter = .all,
searchFilter: [URLQueryItem] = []) async throws -> ThreadResult {
let threadResult = try await apiFetcher.threads(
mailbox: mailbox,
Expand All @@ -74,7 +76,8 @@ public extension MailboxManager {
return threadResult
}

func searchThreads(searchFolder: Folder?, from resource: String,
func searchThreads(@EnsureFrozen searchFolder: Folder?,
from resource: String,
searchFilter: [URLQueryItem] = []) async throws -> ThreadResult {
let threadResult = try await apiFetcher.threads(from: resource, searchFilter: searchFilter)

Expand All @@ -83,7 +86,7 @@ public extension MailboxManager {
return threadResult
}

private func prepareAndSaveSearchThreads(threadResult: ThreadResult, searchFolder: Folder?) async {
private func prepareAndSaveSearchThreads(threadResult: ThreadResult, @EnsureFrozen searchFolder: Folder?) async {
await backgroundRealm.execute { realm in
for thread in threadResult.threads ?? [] {
thread.makeFromSearch(using: realm)
Expand All @@ -99,7 +102,8 @@ public extension MailboxManager {
}
}

func searchThreadsOffline(searchFolder: Folder?, filterFolderId: String,
func searchThreadsOffline(@EnsureFrozen searchFolder: Folder?,
filterFolderId: String,
searchFilters: [SearchCondition]) async {
await backgroundRealm.execute { realm in
guard let searchFolder = searchFolder?.fresh(using: realm) else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import Foundation
import InfomaniakCore
import MailResources
import RealmSwift

Expand All @@ -27,7 +28,7 @@ public extension MailboxManager {
try await refreshActor.refreshAllSignatures()
}

func updateSignature(signature: Signature) async throws {
func updateSignature(@EnsureFrozen signature: Signature) async throws {
try await apiFetcher.updateSignature(mailbox: mailbox, signature: signature)
try await refreshAllSignatures()
}
Expand Down
24 changes: 14 additions & 10 deletions MailCore/Cache/MailboxManager/MailboxManager+Thread.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public extension MailboxManager {
/// - Parameters:
/// - folder: Folder to fetch messages from
/// - fetchCurrentFolderCompleted: Completion once the messages have been fetched
func threads(folder: Folder, fetchCurrentFolderCompleted: (() -> Void) = {}) async throws {
func threads(@EnsureFrozen folder: Folder, fetchCurrentFolderCompleted: (() -> Void) = {}) async throws {
try await messages(folder: folder.freezeIfNeeded())
fetchCurrentFolderCompleted()

Expand Down Expand Up @@ -60,7 +60,7 @@ public extension MailboxManager {
/// - Parameters:
/// - folder: Folder to fetch
/// - isRetrying: is function called from a retry ?
func messages(folder: Folder, isRetrying: Bool = false) async throws {
func messages(@EnsureFrozen folder: Folder, isRetrying: Bool = false) async throws {
guard !Task.isCancelled else { return }

let realm = getRealm()
Expand Down Expand Up @@ -179,7 +179,7 @@ public extension MailboxManager {
/// - direction: Following or previous page to get
/// - backoffIndex: index used in case the offset of the last call doesn't exist
/// - Returns: MessageUidsResult
func messageUidsWithBackOff(folder: Folder,
func messageUidsWithBackOff(@EnsureFrozen folder: Folder,
direction: NewMessagesDirection? = nil,
backoffIndex: Int = 0) async throws -> MessageUidsResult {
let backoffSequence = [1, 1, 2, 8, 34, 144]
Expand Down Expand Up @@ -244,7 +244,7 @@ public extension MailboxManager {
/// - folder: Given folder
/// - direction: Following or previous page to fetch
/// - Returns: Returns if there are other pages to fetch
func fetchOnePage(folder: Folder, direction: NewMessagesDirection? = nil) async throws -> Bool {
func fetchOnePage(@EnsureFrozen folder: Folder, direction: NewMessagesDirection? = nil) async throws -> Bool {
let messageUidsResult = try await messageUidsWithBackOff(folder: folder, direction: direction)

let messagesUids = MessagesUids(
Expand Down Expand Up @@ -294,7 +294,7 @@ public extension MailboxManager {
/// - Parameters:
/// - messageUids: Given MessagesUids
/// - folder: Given folder
private func handleMessagesUids(messageUids: MessagesUids, folder: Folder) async throws {
private func handleMessagesUids(messageUids: MessagesUids, @EnsureFrozen folder: Folder) async throws {
let startDate = Date(timeIntervalSinceNow: -5 * 60)
let ignoredIds = folder.fresh(using: getRealm())?.threads
.where { $0.date > startDate }
Expand Down Expand Up @@ -388,7 +388,7 @@ public extension MailboxManager {
await backgroundTracker.end()
}

private func updateMessages(updates: [MessageFlags], folder: Folder) async {
private func updateMessages(updates: [MessageFlags], @EnsureFrozen folder: Folder) async {
guard !Task.isCancelled else { return }

let backgroundTracker = await ApplicationBackgroundTaskTracker(identifier: #function + UUID().uuidString)
Expand All @@ -415,7 +415,7 @@ public extension MailboxManager {
await backgroundTracker.end()
}

private func addMessages(shortUids: [String], folder: Folder, newCursor: String?) async throws {
private func addMessages(shortUids: [String], @EnsureFrozen folder: Folder, newCursor: String?) async throws {
guard !shortUids.isEmpty && !Task.isCancelled else { return }

let uniqueUids: [String] = getUniqueUids(folder: folder, remoteUids: shortUids)
Expand Down Expand Up @@ -575,7 +575,11 @@ public extension MailboxManager {
/// - folder: Given folder
/// - isRetrying: is function already called from a retry
/// - block: Block to execute
private func catchLostOffsetMessageError(folder: Folder, isRetrying: Bool, block: () async throws -> Void) async throws {
private func catchLostOffsetMessageError(
@EnsureFrozen folder: Folder,
isRetrying: Bool,
block: () async throws -> Void
) async throws {
do {
try await block()
} catch let error as MailError where error == MailApiError.lostOffsetMessage {
Expand Down Expand Up @@ -679,7 +683,7 @@ public extension MailboxManager {

// MARK: - Other

func saveSearchThreads(result: ThreadResult, searchFolder: Folder) async {
func saveSearchThreads(result: ThreadResult, @EnsureFrozen searchFolder: Folder) async {
await backgroundRealm.execute { realm in
guard let searchFolder = searchFolder.fresh(using: realm) else {
self.logError(.missingFolder)
Expand Down Expand Up @@ -711,7 +715,7 @@ public extension MailboxManager {
}
}

func markMovedLocally(_ movedLocally: Bool, threads: [Thread]) async {
func markMovedLocally(_ movedLocally: Bool, @EnsureFrozen threads: [Thread]) async {
await backgroundRealm.execute { realm in
try? realm.write {
for thread in threads {
Expand Down
Loading