From 9c02eeba73850edb6c9e95cf22789ba90f9e4d96 Mon Sep 17 00:00:00 2001 From: Tom J <6306961+tomholub@users.noreply.github.com> Date: Mon, 22 Nov 2021 17:11:55 +0000 Subject: [PATCH] Revert "issue #997 Use @MainActor instead of DispatchQueue.main.async (#1055)" This reverts commit 6f6ec0359424fdab2534e5a01210cba09da4ac7b. --- FlowCrypt/Common UI/AttachmentManager.swift | 13 +-- FlowCrypt/Common UI/Refreshable.swift | 8 +- .../Compose/ComposeViewController.swift | 2 + .../InboxViewContainerController.swift | 4 +- .../Inbox/InboxViewController+Factory.swift | 1 - .../Inbox/InboxViewController.swift | 1 - .../MsgListViewController.swift | 9 +- .../BackupOptionsViewController.swift | 1 - .../Backups Scene/BackupViewController.swift | 1 - .../BackupSelectKeyViewController.swift | 1 - .../Key List/KeySettingsViewController.swift | 1 + .../Setup/PassPhraseSaveable.swift | 1 - .../SetupGenerateKeyViewController.swift | 1 + ...SetupManuallyImportKeyViewController.swift | 4 +- .../SetupImap/SetupImapViewController.swift | 8 +- .../Main/SideMenuNavigationController.swift | 1 - .../SideMenu/Menu/MyMenuViewController.swift | 9 +- .../NavigationChildController.swift | 1 - .../Threads/MessageActionsHandler.swift | 27 +++--- .../Extensions/UIViewController+Spinner.swift | 55 ++++++----- .../UIViewControllerExtensions.swift | 59 ++++++------ .../Error Handling/ErrorHandler.swift | 1 - .../UserMailSessionProvider.swift | 4 +- .../Functionality/Services/GlobalRouter.swift | 95 ++++++++++--------- FlowCryptUI/Nodes/TableViewController.swift | 1 - 25 files changed, 162 insertions(+), 147 deletions(-) diff --git a/FlowCrypt/Common UI/AttachmentManager.swift b/FlowCrypt/Common UI/AttachmentManager.swift index 92908597d..e32027cff 100644 --- a/FlowCrypt/Common UI/AttachmentManager.swift +++ b/FlowCrypt/Common UI/AttachmentManager.swift @@ -9,7 +9,6 @@ import UIKit import Combine -@MainActor protocol AttachmentManagerType { func open(_ attachment: MessageAttachment) } @@ -50,19 +49,13 @@ extension AttachmentManager: AttachmentManagerType { .sinkFuture( receiveValue: {}, receiveError: { [weak self] error in - self?.handle(error) + self?.controller?.showToast( + "\("message_attachment_saved_with_error".localized) \(error.localizedDescription)" + ) } ) .store(in: &self.cancellable) } - - private func handle(_ error: Error) { - Task { - await controller?.showToast( - "\("message_attachment_saved_with_error".localized) \(error.localizedDescription)" - ) - } - } } // MARK: - FilesManagerPresenter diff --git a/FlowCrypt/Common UI/Refreshable.swift b/FlowCrypt/Common UI/Refreshable.swift index 0f3d07269..a633b10de 100644 --- a/FlowCrypt/Common UI/Refreshable.swift +++ b/FlowCrypt/Common UI/Refreshable.swift @@ -8,7 +8,7 @@ import Foundation -@MainActor -protocol Refreshable { - func startRefreshing() -} + protocol Refreshable { + + func startRefreshing() + } diff --git a/FlowCrypt/Controllers/Compose/ComposeViewController.swift b/FlowCrypt/Controllers/Compose/ComposeViewController.swift index 92d9cb2ec..339644693 100644 --- a/FlowCrypt/Controllers/Compose/ComposeViewController.swift +++ b/FlowCrypt/Controllers/Compose/ComposeViewController.swift @@ -21,6 +21,7 @@ private struct ComposedDraft: Equatable { * - User can be redirected here from *InboxViewController* by tapping on *+* * - Or from *ThreadDetailsViewController* controller by tapping on *reply* **/ +@MainActor final class ComposeViewController: TableNodeViewController { private lazy var logger = Logger.nested(Self.self) @@ -931,6 +932,7 @@ extension ComposeViewController: PHPickerViewControllerDelegate { }) } } + } } diff --git a/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift b/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift index 9e7c26a6f..c2f877cc8 100644 --- a/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift +++ b/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift @@ -32,7 +32,7 @@ final class InboxViewContainerController: TableNodeViewController { let folderService: FoldersServiceType let decorator: InboxViewControllerContainerDecorator - private var state: State = .loading { + @MainActor private var state: State = .loading { didSet { handleNewState() } } @@ -68,7 +68,7 @@ final class InboxViewContainerController: TableNodeViewController { } } - private func handleFetched(folders: [FolderViewModel]) { + @MainActor private func handleFetched(folders: [FolderViewModel]) { guard folders.isNotEmpty else { state = .empty return diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift b/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift index 8abf182ac..fb14c4967 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift @@ -10,7 +10,6 @@ import Foundation import UIKit class InboxViewControllerFactory { - @MainActor static func make(with viewModel: InboxViewModel) -> InboxViewController { guard let currentAuthType = DataService.shared.currentAuthType else { fatalError("Internal inconsistency") diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index d1e173e79..b3fa24a47 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -7,7 +7,6 @@ import FlowCryptCommon import FlowCryptUI import Foundation -@MainActor final class InboxViewController: ASDKViewController { private lazy var logger = Logger.nested(Self.self) diff --git a/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift b/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift index c768d426c..2866b2622 100644 --- a/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift +++ b/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift @@ -8,7 +8,6 @@ import UIKit -@MainActor protocol MsgListViewController { func open(with message: InboxRenderable, path: String) @@ -31,9 +30,11 @@ extension MsgListViewController where Self: UIViewController { private func openDraft(with message: Message) { guard let email = DataService.shared.email else { return } - let controller = ComposeViewController(email: email) - controller.updateWithMessage(message: message) - navigationController?.pushViewController(controller, animated: true) + Task { + let controller = await ComposeViewController(email: email) + await controller.updateWithMessage(message: message) + await navigationController?.pushViewController(controller, animated: true) + } } private func openMsg(with message: Message, path: String) { diff --git a/FlowCrypt/Controllers/Settings/Backup/Backups Option Scene/BackupOptionsViewController.swift b/FlowCrypt/Controllers/Settings/Backup/Backups Option Scene/BackupOptionsViewController.swift index 8c8644223..388107fab 100644 --- a/FlowCrypt/Controllers/Settings/Backup/Backups Option Scene/BackupOptionsViewController.swift +++ b/FlowCrypt/Controllers/Settings/Backup/Backups Option Scene/BackupOptionsViewController.swift @@ -21,7 +21,6 @@ enum BackupOption: Int, CaseIterable, Equatable { } } -@MainActor final class BackupOptionsViewController: ASDKViewController { enum Parts: Int, CaseIterable { case email, download, action, info diff --git a/FlowCrypt/Controllers/Settings/Backup/Backups Scene/BackupViewController.swift b/FlowCrypt/Controllers/Settings/Backup/Backups Scene/BackupViewController.swift index a77747db9..75eb944b3 100644 --- a/FlowCrypt/Controllers/Settings/Backup/Backups Scene/BackupViewController.swift +++ b/FlowCrypt/Controllers/Settings/Backup/Backups Scene/BackupViewController.swift @@ -9,7 +9,6 @@ import AsyncDisplayKit import FlowCryptUI -@MainActor final class BackupViewController: ASDKViewController { private enum Parts: Int, CaseIterable { case info, action diff --git a/FlowCrypt/Controllers/Settings/Backup/Backups Seleckt Key Scene/BackupSelectKeyViewController.swift b/FlowCrypt/Controllers/Settings/Backup/Backups Seleckt Key Scene/BackupSelectKeyViewController.swift index 5aca0a769..0c3d7c680 100644 --- a/FlowCrypt/Controllers/Settings/Backup/Backups Seleckt Key Scene/BackupSelectKeyViewController.swift +++ b/FlowCrypt/Controllers/Settings/Backup/Backups Seleckt Key Scene/BackupSelectKeyViewController.swift @@ -10,7 +10,6 @@ import AsyncDisplayKit import FlowCryptUI import Foundation -@MainActor final class BackupSelectKeyViewController: ASDKViewController { private let backupService: BackupServiceType private let service: ServiceActor diff --git a/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift b/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift index 8fae926bf..b6bb36ae1 100644 --- a/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift +++ b/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift @@ -15,6 +15,7 @@ import FlowCryptUI * - User can proceed to importing keys *SetupManuallyImportKeyViewController* * - User can see detail information for the key in *KeyDetailViewController* */ +@MainActor final class KeySettingsViewController: TableNodeViewController { private var keys: [KeyDetails] = [] private let decorator: KeySettingsViewDecorator diff --git a/FlowCrypt/Controllers/Setup/PassPhraseSaveable.swift b/FlowCrypt/Controllers/Setup/PassPhraseSaveable.swift index 2c054724f..d8772e9d6 100644 --- a/FlowCrypt/Controllers/Setup/PassPhraseSaveable.swift +++ b/FlowCrypt/Controllers/Setup/PassPhraseSaveable.swift @@ -8,7 +8,6 @@ import FlowCryptUI -@MainActor protocol PassPhraseSaveable { var storageMethod: StorageMethod { get set } var passPhraseIndexes: [IndexPath] { get } diff --git a/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift b/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift index d4aaf7b85..9dcef28a2 100644 --- a/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift @@ -28,6 +28,7 @@ enum CreateKeyError: Error { * - Here user can enter a pass phrase (can be saved in memory or in encrypted storage) and generate a key * - After key is generated, user will be redirected to **main flow** (inbox view) */ +@MainActor final class SetupGenerateKeyViewController: SetupCreatePassphraseAbstractViewController { private let backupService: BackupServiceType diff --git a/FlowCrypt/Controllers/Setup/SetupManuallyImportKeyViewController.swift b/FlowCrypt/Controllers/Setup/SetupManuallyImportKeyViewController.swift index 3f6d31dd0..fcba07ec9 100644 --- a/FlowCrypt/Controllers/Setup/SetupManuallyImportKeyViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupManuallyImportKeyViewController.swift @@ -78,7 +78,9 @@ final class SetupManuallyImportKeyViewController: TableNodeViewController { } private func updateSubtitle() { - node.reloadRows(at: [Parts.description.indexPath], with: .fade) + DispatchQueue.main.async { + self.node.reloadRows(at: [Parts.description.indexPath], with: .fade) + } } } diff --git a/FlowCrypt/Controllers/SetupImap/SetupImapViewController.swift b/FlowCrypt/Controllers/SetupImap/SetupImapViewController.swift index d59ea92f5..39e94247a 100644 --- a/FlowCrypt/Controllers/SetupImap/SetupImapViewController.swift +++ b/FlowCrypt/Controllers/SetupImap/SetupImapViewController.swift @@ -512,9 +512,13 @@ extension SetupImapViewController { do { try await self.imap.connectImap(session: imapSessionToCheck) try await self.imap.connectSmtp(session: smtpSession) - handleSuccessfulConnection() + DispatchQueue.main.async { + self.handleSuccessfulConnection() + } } catch { - handleConnection(error: error) + DispatchQueue.main.async { + self.handleConnection(error: error) + } } } } diff --git a/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift b/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift index c5579f0fb..2637f56a0 100644 --- a/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift +++ b/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift @@ -6,7 +6,6 @@ import ENSwiftSideMenu import FlowCryptUI import UIKit -@MainActor protocol SideMenuViewController { func didOpen() } diff --git a/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift b/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift index 499c80351..8bdd4a061 100644 --- a/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift +++ b/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift @@ -13,7 +13,6 @@ import FlowCryptUI * On tap on each folder user should be redirected to `InboxViewController` with selected folder * On settings tap user will be redirected to `SettingsViewController` */ -@MainActor final class MyMenuViewController: ASDKViewController { private enum Constants { static let allMail = "folder_all_mail".localized @@ -175,9 +174,13 @@ extension MyMenuViewController { Task { do { let folders = try await foldersProvider.fetchFolders(isForceReload: true) - handleNewFolders(with: folders) + DispatchQueue.main.async { + self.handleNewFolders(with: folders) + } } catch { - handleError(with: error) + DispatchQueue.main.async { + self.handleError(with: error) + } } } } diff --git a/FlowCrypt/Controllers/SideMenu/NavigationController/NavigationChildController.swift b/FlowCrypt/Controllers/SideMenu/NavigationController/NavigationChildController.swift index dd27c2bb3..4d4f4fd13 100644 --- a/FlowCrypt/Controllers/SideMenu/NavigationController/NavigationChildController.swift +++ b/FlowCrypt/Controllers/SideMenu/NavigationController/NavigationChildController.swift @@ -8,7 +8,6 @@ import UIKit -@MainActor protocol NavigationChildController { var navigationItem: UINavigationItem { get } var shouldShowBackButton: Bool { get } diff --git a/FlowCrypt/Controllers/Threads/MessageActionsHandler.swift b/FlowCrypt/Controllers/Threads/MessageActionsHandler.swift index f751229be..e1d20e543 100644 --- a/FlowCrypt/Controllers/Threads/MessageActionsHandler.swift +++ b/FlowCrypt/Controllers/Threads/MessageActionsHandler.swift @@ -10,7 +10,6 @@ import UIKit import FlowCryptUI import FlowCryptCommon -@MainActor protocol MessageActionsHandler: AnyObject { var currentFolderPath: String { get } var trashFolderProvider: TrashFolderProviderType { get } @@ -34,7 +33,9 @@ extension MessageActionsHandler where Self: UIViewController { Task { do { let path = try await trashFolderProvider.getTrashFolderPath() - setupNavigationBarItems(with: path) + DispatchQueue.main.async { + self.setupNavigationBarItems(with: path) + } } catch { // todo - handle? logger.logError("setupNavigationBar: \(error)") @@ -94,18 +95,22 @@ extension MessageActionsHandler where Self: UIViewController { Task { do { let trashPath = try await trashFolderProvider.getTrashFolderPath() - guard let trashPath = trashPath else { - return - } - if self.currentFolderPath.caseInsensitiveCompare(trashPath) == .orderedSame { - self.awaitUserConfirmation { [weak self] in - self?.permanentlyDelete() + DispatchQueue.main.async { + guard let trashPath = trashPath else { + return + } + if self.currentFolderPath.caseInsensitiveCompare(trashPath) == .orderedSame { + self.awaitUserConfirmation { [weak self] in + self?.permanentlyDelete() + } + } else { + self.moveToTrash(with: trashPath) } - } else { - self.moveToTrash(with: trashPath) } } catch { - showToast(error.localizedDescription) + DispatchQueue.main.async { + self.showToast(error.localizedDescription) + } } } } diff --git a/FlowCrypt/Extensions/UIViewController+Spinner.swift b/FlowCrypt/Extensions/UIViewController+Spinner.swift index 32f01b5ee..f8d3cdf8a 100644 --- a/FlowCrypt/Extensions/UIViewController+Spinner.swift +++ b/FlowCrypt/Extensions/UIViewController+Spinner.swift @@ -5,7 +5,7 @@ // Created by Roma Sosnovsky on 25/10/21 // Copyright © 2017-present FlowCrypt a. s. All rights reserved. // - + import MBProgressHUD import UIKit @@ -14,44 +14,47 @@ extension UIViewController { MBProgressHUD.forView(view) ?? MBProgressHUD.showAdded(to: view, animated: true) } - @MainActor func showSpinner(_ message: String = "loading_title".localized, isUserInteractionEnabled: Bool = false) { - guard self.view.subviews.first(where: { $0 is MBProgressHUD }) == nil else { - // hud is already shown - return - } - self.view.isUserInteractionEnabled = isUserInteractionEnabled + DispatchQueue.main.async { + guard self.view.subviews.first(where: { $0 is MBProgressHUD }) == nil else { + // hud is already shown + return + } + self.view.isUserInteractionEnabled = isUserInteractionEnabled - let spinner = MBProgressHUD.showAdded(to: self.view, animated: true) - spinner.label.text = message - spinner.isUserInteractionEnabled = isUserInteractionEnabled + let spinner = MBProgressHUD.showAdded(to: self.view, animated: true) + spinner.label.text = message + spinner.isUserInteractionEnabled = isUserInteractionEnabled + } } - @MainActor func updateSpinner(label: String = "compose_uploading".localized, progress: Float? = nil, systemImageName: String? = nil) { - if let progress = progress { - if progress >= 1, let imageName = systemImageName { - self.updateSpinner(label: "compose_sent".localized, - systemImageName: imageName) + DispatchQueue.main.async { + if let progress = progress { + if progress >= 1, let imageName = systemImageName { + self.updateSpinner(label: "compose_sent".localized, + systemImageName: imageName) + } else { + self.showProgressHUD(progress: progress, label: label) + } + } else if let imageName = systemImageName { + self.showProgressHUDWithCustomImage(imageName: imageName, label: label) } else { - self.showProgressHUD(progress: progress, label: label) + self.currentProgressHUD.mode = .indeterminate + self.currentProgressHUD.label.text = label } - } else if let imageName = systemImageName { - self.showProgressHUDWithCustomImage(imageName: imageName, label: label) - } else { - self.currentProgressHUD.mode = .indeterminate - self.currentProgressHUD.label.text = label } } - @MainActor func hideSpinner() { - self.view.subviews - .compactMap { $0 as? MBProgressHUD } - .forEach { $0.hide(animated: true) } - self.view.isUserInteractionEnabled = true + DispatchQueue.main.async { + self.view.subviews + .compactMap { $0 as? MBProgressHUD } + .forEach { $0.hide(animated: true) } + self.view.isUserInteractionEnabled = true + } } } diff --git a/FlowCrypt/Extensions/UIViewControllerExtensions.swift b/FlowCrypt/Extensions/UIViewControllerExtensions.swift index a09a8d9a8..49e4c7278 100644 --- a/FlowCrypt/Extensions/UIViewControllerExtensions.swift +++ b/FlowCrypt/Extensions/UIViewControllerExtensions.swift @@ -20,7 +20,6 @@ extension UIViewController { /// - duration: Toast presented duration. Default is 3.0 /// - position: Bottom by default. Can be top, center, bottom. /// - completion: Notify when toast dissapeared - @MainActor func showToast( _ message: String, title: String? = nil, @@ -28,22 +27,24 @@ extension UIViewController { position: ToastPosition = .bottom, completion: ShowToastCompletion? = nil ) { - guard let view = UIApplication.shared.keyWindow?.rootViewController?.view else { - assertionFailure("Key window hasn't rootViewController") - return - } - view.hideAllToasts() - view.endEditing(true) + DispatchQueue.main.async { + guard let view = UIApplication.shared.keyWindow?.rootViewController?.view else { + assertionFailure("Key window hasn't rootViewController") + return + } + view.hideAllToasts() + view.endEditing(true) - view.makeToast( - message, - duration: duration, - position: position, - title: title, - completion: completion - ) + view.makeToast( + message, + duration: duration, + position: position, + title: title, + completion: completion + ) - ToastManager.shared.isTapToDismissEnabled = true + ToastManager.shared.isTapToDismissEnabled = true + } } } @@ -71,28 +72,30 @@ extension UIViewController { showAlert(message: formatted, onOk: onOk) } - @MainActor func showAlert(title: String? = "Error", message: String, onOk: (() -> Void)? = nil) { - self.view.hideAllToasts() - hideSpinner() - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .destructive) { _ in onOk?() }) - self.present(alert, animated: true, completion: nil) + DispatchQueue.main.async { + self.view.hideAllToasts() + self.hideSpinner() + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .destructive) { _ in onOk?() }) + self.present(alert, animated: true, completion: nil) + } } - @MainActor func showRetryAlert( title: String? = "Error", message: String, onRetry: (() -> Void)? = nil, onOk: (() -> Void)? = nil ) { - self.view.hideAllToasts() - hideSpinner() - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "Retry", style: .cancel) { _ in onRetry?() }) - alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in onOk?() }) - present(alert, animated: true, completion: nil) + DispatchQueue.main.async { + self.view.hideAllToasts() + self.hideSpinner() + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "Retry", style: .cancel) { _ in onRetry?() }) + alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in onOk?() }) + self.present(alert, animated: true, completion: nil) + } } func keyboardHeight(from notification: Notification) -> CGFloat { diff --git a/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift b/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift index aa7cbcc17..518dccb49 100644 --- a/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift +++ b/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift @@ -24,7 +24,6 @@ extension UIViewController { } // MARK: - ErrorHandler -@MainActor protocol ErrorHandler { func handle(error: Error, for viewController: UIViewController) -> Bool } diff --git a/FlowCrypt/Functionality/Mail Provider/UsersMailSession Provider/UserMailSessionProvider.swift b/FlowCrypt/Functionality/Mail Provider/UsersMailSession Provider/UserMailSessionProvider.swift index e7fe7382d..a67f7cbdc 100644 --- a/FlowCrypt/Functionality/Mail Provider/UsersMailSession Provider/UserMailSessionProvider.swift +++ b/FlowCrypt/Functionality/Mail Provider/UsersMailSession Provider/UserMailSessionProvider.swift @@ -12,6 +12,7 @@ protocol UsersMailSessionProvider { // MARK: - GmailService extension GmailService: UsersMailSessionProvider { + @discardableResult func renewSession() async throws { try await userService.renewSession() } @@ -19,7 +20,8 @@ extension GmailService: UsersMailSessionProvider { // MARK: - Imap extension Imap: UsersMailSessionProvider { + @discardableResult func renewSession() async throws { - setupSession() + try await self.setupSession() } } diff --git a/FlowCrypt/Functionality/Services/GlobalRouter.swift b/FlowCrypt/Functionality/Services/GlobalRouter.swift index f3be6cf75..11657e79e 100644 --- a/FlowCrypt/Functionality/Services/GlobalRouter.swift +++ b/FlowCrypt/Functionality/Services/GlobalRouter.swift @@ -9,12 +9,11 @@ import FlowCryptCommon import UIKit -@MainActor protocol GlobalRouterType { - func proceed() - func signIn(with route: GlobalRoutingType) - func switchActive(user: User) - func signOut() + @MainActor func proceed() + @MainActor func signIn(with route: GlobalRoutingType) + @MainActor func switchActive(user: User) + @MainActor func signOut() } enum GlobalRoutingType { @@ -29,9 +28,9 @@ enum GlobalRoutingError: Error { } // MARK: - GlobalRouter -final class GlobalRouter { +final class GlobalRouter: GlobalRouterType { - private var keyWindow: UIWindow { + @MainActor private var keyWindow: UIWindow { let application = UIApplication.shared guard let delegate = (application.delegate as? AppDelegate) else { fatalError("missing AppDelegate in GlobalRouter.reset()") @@ -54,16 +53,55 @@ final class GlobalRouter { } // MARK: - Proceed -extension GlobalRouter: GlobalRouterType { +extension GlobalRouter { /// proceed to flow (signing/setup/app) depends on user status (isLoggedIn/isSetupFinished) - func proceed() { + @MainActor func proceed() { validateEncryptedStorage { userAccountService.cleanupSessions() proceed(with: nil) } } - func signIn(with route: GlobalRoutingType) { + @MainActor private func validateEncryptedStorage(_ completion: () -> Void) { + let storage = EncryptedStorage() + do { + try storage.validate() + completion() + } catch { + let controller = InvalidStorageViewController( + error: error, + encryptedStorage: storage, + router: self + ) + keyWindow.rootViewController = UINavigationController(rootViewController: controller) + keyWindow.makeKeyAndVisible() + } + } + + @MainActor private func proceed(with session: SessionType?) { + logger.logInfo("proceed for session \(session.debugDescription)") + + Task { + AppStartup().initializeApp(window: keyWindow, session: session) + } + } + + @MainActor private func handleGmailError(_ error: Error) { + logger.logInfo("gmail login failed with error \(error.localizedDescription)") + if let gmailUserError = error as? GoogleUserServiceError, + case .userNotAllowedAllNeededScopes(let missingScopes) = gmailUserError { + DispatchQueue.main.async { + let topNavigation = (self.keyWindow.rootViewController as? UINavigationController) + let checkAuthViewControlelr = CheckAuthScopesViewController(missingScopes: missingScopes) + topNavigation?.pushViewController(checkAuthViewControlelr, animated: true) + } + } + } +} + +// MARK: - +extension GlobalRouter { + @MainActor func signIn(with route: GlobalRoutingType) { logger.logInfo("Sign in with \(route)") switch route { @@ -83,7 +121,7 @@ extension GlobalRouter: GlobalRouterType { } } - func signOut() { + @MainActor func signOut() { if let session = userAccountService.startActiveSessionForNextUser() { logger.logInfo("Start session for another email user \(session)") proceed(with: session) @@ -94,7 +132,7 @@ extension GlobalRouter: GlobalRouterType { } } - func switchActive(user: User) { + @MainActor func switchActive(user: User) { logger.logInfo("Switching active user \(user)") guard let session = userAccountService.switchActiveSessionFor(user: user) else { logger.logWarning("Can't switch active user with \(user.email)") @@ -102,37 +140,4 @@ extension GlobalRouter: GlobalRouterType { } proceed(with: session) } - - private func validateEncryptedStorage(_ completion: () -> Void) { - let storage = EncryptedStorage() - do { - try storage.validate() - completion() - } catch { - let controller = InvalidStorageViewController( - error: error, - encryptedStorage: storage, - router: self - ) - keyWindow.rootViewController = UINavigationController(rootViewController: controller) - keyWindow.makeKeyAndVisible() - } - } - - @MainActor - private func proceed(with session: SessionType?) { - logger.logInfo("proceed for session \(session.debugDescription)") - AppStartup().initializeApp(window: keyWindow, session: session) - } - - @MainActor - private func handleGmailError(_ error: Error) { - logger.logInfo("gmail login failed with error \(error.localizedDescription)") - if let gmailUserError = error as? GoogleUserServiceError, - case .userNotAllowedAllNeededScopes(let missingScopes) = gmailUserError { - let topNavigation = (self.keyWindow.rootViewController as? UINavigationController) - let checkAuthViewControlelr = CheckAuthScopesViewController(missingScopes: missingScopes) - topNavigation?.pushViewController(checkAuthViewControlelr, animated: true) - } - } } diff --git a/FlowCryptUI/Nodes/TableViewController.swift b/FlowCryptUI/Nodes/TableViewController.swift index d6506df1e..2ea4c50a0 100644 --- a/FlowCryptUI/Nodes/TableViewController.swift +++ b/FlowCryptUI/Nodes/TableViewController.swift @@ -8,7 +8,6 @@ import AsyncDisplayKit -@MainActor open class TableNodeViewController: ASDKViewController { public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection)