diff --git a/FlowCrypt/App/AppContext.swift b/FlowCrypt/App/AppContext.swift index 4bf17221c..3d6ee84a2 100644 --- a/FlowCrypt/App/AppContext.swift +++ b/FlowCrypt/App/AppContext.swift @@ -21,7 +21,7 @@ class AppContext { let passPhraseService: PassPhraseServiceType let clientConfigurationService: ClientConfigurationServiceType - private init( + init( encryptedStorage: EncryptedStorageType, session: SessionType?, userAccountService: SessionServiceType, @@ -78,16 +78,18 @@ class AppContext { ) } - func withSession(_ session: SessionType?) -> AppContext { - return AppContext( - encryptedStorage: self.encryptedStorage, + func withSession(session: SessionType?, authType: AuthType, user: User) -> AppContextWithUser { + return AppContextWithUser( + encryptedStorage: encryptedStorage, session: session, - userAccountService: self.userAccountService, - dataService: self.dataService, - keyService: self.keyService, - passPhraseService: self.passPhraseService, - clientConfigurationService: self.clientConfigurationService, - globalRouter: globalRouter + userAccountService: userAccountService, + dataService: dataService, + keyService: keyService, + passPhraseService: passPhraseService, + clientConfigurationService: clientConfigurationService, + globalRouter: globalRouter, + authType: authType, + user: user ) } @@ -131,3 +133,35 @@ class AppContext { ) } } + +class AppContextWithUser: AppContext { + let authType: AuthType + let user: User + + init( + encryptedStorage: EncryptedStorageType, + session: SessionType?, + userAccountService: SessionServiceType, + dataService: DataServiceType, + keyService: KeyServiceType, + passPhraseService: PassPhraseServiceType, + clientConfigurationService: ClientConfigurationServiceType, + globalRouter: GlobalRouterType, + authType: AuthType, + user: User + ) { + self.authType = authType + self.user = user + + super.init( + encryptedStorage: encryptedStorage, + session: session, + userAccountService: userAccountService, + dataService: dataService, + keyService: keyService, + passPhraseService: passPhraseService, + clientConfigurationService: clientConfigurationService, + globalRouter: globalRouter + ) + } +} diff --git a/FlowCrypt/Controllers/Compose/ComposeViewController.swift b/FlowCrypt/Controllers/Compose/ComposeViewController.swift index 946636902..d94dab9d2 100644 --- a/FlowCrypt/Controllers/Compose/ComposeViewController.swift +++ b/FlowCrypt/Controllers/Compose/ComposeViewController.swift @@ -49,7 +49,7 @@ final class ComposeViewController: TableNodeViewController { case topDivider, subject, subjectDivider, text } - private let appContext: AppContext + private let appContext: AppContextWithUser private let composeMessageService: ComposeMessageService private let notificationCenter: NotificationCenter private let decorator: ComposeViewDecorator @@ -88,7 +88,7 @@ final class ComposeViewController: TableNodeViewController { } init( - appContext: AppContext, + appContext: AppContextWithUser, notificationCenter: NotificationCenter = .default, decorator: ComposeViewDecorator = ComposeViewDecorator(), input: ComposeMessageInput = .empty, @@ -100,14 +100,11 @@ final class ComposeViewController: TableNodeViewController { keyMethods: KeyMethodsType = KeyMethods() ) { self.appContext = appContext - guard let email = appContext.dataService.email else { - fatalError("missing current user email") // todo - need a more elegant solution - } - self.email = email + self.email = appContext.user.email self.notificationCenter = notificationCenter self.input = input self.decorator = decorator - let clientConfiguration = appContext.clientConfigurationService.getSaved(for: email) + let clientConfiguration = appContext.clientConfigurationService.getSaved(for: appContext.user.email) self.contactsService = contactsService ?? ContactsService( localContactsProvider: LocalContactsProvider( encryptedStorage: appContext.encryptedStorage @@ -116,7 +113,7 @@ final class ComposeViewController: TableNodeViewController { ) let cloudContactProvider = cloudContactProvider ?? UserContactsProvider( userService: GoogleUserService( - currentUserEmail: email, + currentUserEmail: appContext.user.email, appDelegateGoogleSessionContainer: UIApplication.shared.delegate as? AppDelegate ) ) @@ -126,7 +123,7 @@ final class ComposeViewController: TableNodeViewController { encryptedStorage: appContext.encryptedStorage, messageGateway: appContext.getRequiredMailProvider().messageSender, passPhraseService: appContext.passPhraseService, - sender: email + sender: appContext.user.email ) self.filesManager = filesManager self.photosManager = photosManager diff --git a/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift b/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift index 3d891625a..5daa408cc 100644 --- a/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift +++ b/FlowCrypt/Controllers/Inbox/Container/InboxViewContainerController.swift @@ -29,24 +29,19 @@ final class InboxViewContainerController: TableNodeViewController { case loadedFolders([FolderViewModel]) } - let appContext: AppContext + let appContext: AppContextWithUser let foldersService: FoldersServiceType let decorator: InboxViewControllerContainerDecorator - let currentUser: User private var state: State = .loading { didSet { handleNewState() } } init( - appContext: AppContext, + appContext: AppContextWithUser, foldersService: FoldersServiceType? = nil, decorator: InboxViewControllerContainerDecorator = InboxViewControllerContainerDecorator() ) { - guard let currentUser = appContext.dataService.currentUser else { - fatalError("missing current user") // todo - use DI - } - self.currentUser = currentUser self.appContext = appContext self.foldersService = foldersService ?? appContext.getFoldersService() self.decorator = decorator @@ -68,7 +63,7 @@ final class InboxViewContainerController: TableNodeViewController { private func fetchInboxFolder() { Task { do { - let folders = try await foldersService.fetchFolders(isForceReload: true, for: self.currentUser) + let folders = try await foldersService.fetchFolders(isForceReload: true, for: appContext.user) self.handleFetched(folders: folders) } catch { self.state = .error(error) @@ -107,7 +102,10 @@ final class InboxViewContainerController: TableNodeViewController { return } let input = InboxViewModel(inbox) - let inboxViewController = InboxViewControllerFactory.make(appContext: appContext, with: input) + let inboxViewController = InboxViewControllerFactory.make( + appContext: appContext, + viewModel: input + ) navigationController?.setViewControllers([inboxViewController], animated: false) } } diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift b/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift index c54e60963..caf2e8f57 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController+Factory.swift @@ -11,12 +11,8 @@ import UIKit class InboxViewControllerFactory { @MainActor - static func make(appContext: AppContext, with viewModel: InboxViewModel) -> InboxViewController { - guard let currentAuthType = appContext.dataService.currentAuthType else { - fatalError("Internal inconsistency") - } - - switch currentAuthType { + static func make(appContext: AppContextWithUser, viewModel: InboxViewModel) -> InboxViewController { + switch appContext.authType { case .oAuthGmail: // Inject threads provider - Gmail API guard let threadsProvider = appContext.getRequiredMailProvider().messagesThreadProvider else { @@ -25,7 +21,7 @@ class InboxViewControllerFactory { return InboxViewController( appContext: appContext, - viewModel, + viewModel: viewModel, numberOfInboxItemsToLoad: 20, // else timeouts happen provider: InboxMessageThreadsProvider(provider: threadsProvider) ) @@ -35,7 +31,7 @@ class InboxViewControllerFactory { return InboxViewController( appContext: appContext, - viewModel, + viewModel: viewModel, numberOfInboxItemsToLoad: 50, // safe to load 50, single call on IMAP provider: provider ) diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index 863065913..8e38f2ce5 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -13,8 +13,7 @@ final class InboxViewController: ViewController { private let numberOfInboxItemsToLoad: Int - private let appContext: AppContext - private let user: User + private let appContext: AppContextWithUser private let service: ServiceActor private let decorator: InboxViewDecorator private let draftsListProvider: DraftsListProvider? @@ -34,17 +33,13 @@ final class InboxViewController: ViewController { var path: String { viewModel.path } init( - appContext: AppContext, - _ viewModel: InboxViewModel, + appContext: AppContextWithUser, + viewModel: InboxViewModel, numberOfInboxItemsToLoad: Int = 50, provider: InboxDataProvider, draftsListProvider: DraftsListProvider? = nil, decorator: InboxViewDecorator = InboxViewDecorator() ) { - guard let user = appContext.dataService.currentUser else { - fatalError("missing current user") // todo - DI user - } - self.user = user self.appContext = appContext self.viewModel = viewModel self.numberOfInboxItemsToLoad = numberOfInboxItemsToLoad @@ -186,7 +181,7 @@ extension InboxViewController { folderPath: viewModel.path, count: numberOfInboxItemsToLoad, pagination: currentMessagesListPagination() - ), userEmail: user.email + ), userEmail: appContext.user.email ) handleEndFetching(with: context, context: batchContext) } catch { @@ -208,7 +203,7 @@ extension InboxViewController { folderPath: viewModel.path, count: messagesToLoad(), pagination: pagination - ), userEmail: user.email + ), userEmail: appContext.user.email ) state = .fetched(context.pagination) handleEndFetching(with: context, context: batchContext) diff --git a/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift b/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift index 3459ab670..28011a0d4 100644 --- a/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift +++ b/FlowCrypt/Controllers/MessageList Extension/MsgListViewController.swift @@ -10,7 +10,7 @@ import UIKit @MainActor protocol MsgListViewController { - func open(with message: InboxRenderable, path: String, appContext: AppContext) + func open(with message: InboxRenderable, path: String, appContext: AppContextWithUser) func getUpdatedIndex(for message: InboxRenderable) -> Int? func updateMessage(isRead: Bool, at index: Int) @@ -20,7 +20,7 @@ protocol MsgListViewController { extension MsgListViewController where Self: UIViewController { // todo - tom - don't know how to add AppContext into init of protocol/extension - func open(with message: InboxRenderable, path: String, appContext: AppContext) { + func open(with message: InboxRenderable, path: String, appContext: AppContextWithUser) { switch message.wrappedType { case .message(let message): openMsg(appContext: appContext, with: message, path: path) @@ -30,13 +30,13 @@ extension MsgListViewController where Self: UIViewController { } // TODO: uncomment in "sent message from draft" feature - private func openDraft(appContext: AppContext, with message: Message) { + private func openDraft(appContext: AppContextWithUser, with message: Message) { let controller = ComposeViewController(appContext: appContext) controller.update(with: message) navigationController?.pushViewController(controller, animated: true) } - private func openMsg(appContext: AppContext, with message: Message, path: String) { + private func openMsg(appContext: AppContextWithUser, with message: Message, path: String) { let thread = MessageThread( identifier: message.threadId, snippet: nil, @@ -46,7 +46,7 @@ extension MsgListViewController where Self: UIViewController { openThread(with: thread, appContext: appContext) } - private func openThread(with thread: MessageThread, appContext: AppContext) { + private func openThread(with thread: MessageThread, appContext: AppContextWithUser) { let viewController = ThreadDetailsViewController( appContext: appContext, thread: thread diff --git a/FlowCrypt/Controllers/Search/SearchViewController.swift b/FlowCrypt/Controllers/Search/SearchViewController.swift index 56de3d307..9b78efb10 100644 --- a/FlowCrypt/Controllers/Search/SearchViewController.swift +++ b/FlowCrypt/Controllers/Search/SearchViewController.swift @@ -41,21 +41,16 @@ final class SearchViewController: TableNodeViewController { // TODO: - https://github.com/FlowCrypt/flowcrypt-ios/issues/669 Adopt to gmail threads private let service: ServiceActor private var searchTask: DispatchWorkItem? - private let appContext: AppContext + private let appContext: AppContextWithUser private let searchController = UISearchController(searchResultsController: nil) private let folderPath: String private var searchedExpression: String = "" - private let currentUser: User init( - appContext: AppContext, + appContext: AppContextWithUser, searchProvider: MessageSearchProvider? = nil, folderPath: String ) { - guard let currentUser = appContext.dataService.currentUser else { - fatalError("no current user") // todo - use DI - } - self.currentUser = currentUser self.appContext = appContext self.service = ServiceActor( searchProvider: searchProvider ?? appContext.getRequiredMailProvider().messageSearchProvider diff --git a/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift b/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift index d13771f33..44b51a9b1 100644 --- a/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift +++ b/FlowCrypt/Controllers/Settings/KeySettings/Key List/KeySettingsViewController.swift @@ -17,21 +17,18 @@ import FlowCryptUI */ final class KeySettingsViewController: TableNodeViewController { - private let appContext: AppContext + private let appContext: AppContextWithUser private var keys: [KeyDetails] = [] private let decorator: KeySettingsViewDecorator private let isUsingKeyManager: Bool init( - appContext: AppContext, + appContext: AppContextWithUser, decorator: KeySettingsViewDecorator = KeySettingsViewDecorator() ) { self.appContext = appContext self.decorator = decorator - guard let currentUser = appContext.dataService.currentUser else { - fatalError("missing current user") // todo - need more elegant solution - } - self.isUsingKeyManager = appContext.clientConfigurationService.getSaved(for: currentUser.email).isUsingKeyManager + self.isUsingKeyManager = appContext.clientConfigurationService.getSaved(for: appContext.user.email).isUsingKeyManager super.init(node: TableNode()) } diff --git a/FlowCrypt/Controllers/Settings/Settings List/SettingsViewController.swift b/FlowCrypt/Controllers/Settings/Settings List/SettingsViewController.swift index a7526488c..ef8e4aa8b 100644 --- a/FlowCrypt/Controllers/Settings/Settings List/SettingsViewController.swift +++ b/FlowCrypt/Controllers/Settings/Settings List/SettingsViewController.swift @@ -43,22 +43,19 @@ final class SettingsViewController: TableNodeViewController { } } - private let appContext: AppContext + private let appContext: AppContextWithUser private let decorator: SettingsViewDecorator private let clientConfiguration: ClientConfiguration private let rows: [SettingsMenuItem] init( - appContext: AppContext, + appContext: AppContextWithUser, decorator: SettingsViewDecorator = SettingsViewDecorator() ) { self.appContext = appContext self.decorator = decorator - guard let currentUser = appContext.dataService.currentUser?.email else { - fatalError("missing current user") // todo - need more elegant solution - } - self.clientConfiguration = appContext.clientConfigurationService.getSaved(for: currentUser) - self.rows = SettingsMenuItem.filtered(with: self.clientConfiguration) + self.clientConfiguration = appContext.clientConfigurationService.getSaved(for: appContext.user.email) + self.rows = SettingsMenuItem.filtered(with: clientConfiguration) super.init(node: TableNode()) } @@ -116,22 +113,17 @@ extension SettingsViewController { switch setting { case .keys: - viewController = KeySettingsViewController( - appContext: appContext - ) + viewController = KeySettingsViewController(appContext: appContext) case .legal: viewController = LegalViewController() case .contacts: - viewController = ContactsListViewController( - appContext: appContext - ) + viewController = ContactsListViewController(appContext: appContext) case .backups: - guard let currentUser = appContext.dataService.currentUser, - clientConfiguration.canBackupKeys else { + guard clientConfiguration.canBackupKeys else { viewController = nil return } - let userId = UserId(email: currentUser.email, name: currentUser.email) + let userId = UserId(email: appContext.user.email, name: appContext.user.email) viewController = BackupViewController(appContext: appContext, userId: userId) default: viewController = nil diff --git a/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift b/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift index 06bf60d1f..00a157961 100644 --- a/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift +++ b/FlowCrypt/Controllers/SideMenu/Main/SideMenuNavigationController.swift @@ -48,7 +48,7 @@ final class SideMenuNavigationController: ENSideMenuNavigationController { private var menuViewContoller: SideMenuViewController? - convenience init(appContext: AppContext, contentViewController: UIViewController) { + convenience init(appContext: AppContextWithUser, contentViewController: UIViewController) { let menu = MyMenuViewController(appContext: appContext) self.init(menuViewController: menu, contentViewController: contentViewController) menuViewContoller = menu diff --git a/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift b/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift index 3eb21c0e1..be6711d01 100644 --- a/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift +++ b/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift @@ -43,16 +43,15 @@ final class MyMenuViewController: ViewController { } } - private let appContext: AppContext + private let appContext: AppContextWithUser private let foldersService: FoldersServiceType private let decorator: MyMenuViewDecorator private var folders: [FolderViewModel] = [] private var serviceItems: [FolderViewModel] { FolderViewModel.menuItems } private var accounts: [User] { - appContext.dataService.getFinishedSetupUsers(exceptUserEmail: currentUser.email) + appContext.dataService.getFinishedSetupUsers(exceptUserEmail: appContext.user.email) } - private let currentUser: User private let tableNode: ASTableNode @@ -66,14 +65,10 @@ final class MyMenuViewController: ViewController { private var isFirstLaunch = true init( - appContext: AppContext, + appContext: AppContextWithUser, decorator: MyMenuViewDecorator = MyMenuViewDecorator(), tableNode: ASTableNode = TableNode() ) { - guard let currentUser = appContext.dataService.currentUser else { - fatalError("no current user") // todo - dependency-inject - } - self.currentUser = currentUser self.appContext = appContext self.foldersService = appContext.getFoldersService() self.decorator = decorator @@ -176,7 +171,7 @@ extension MyMenuViewController { showSpinner() Task { do { - let folders = try await foldersService.fetchFolders(isForceReload: true, for: self.currentUser) + let folders = try await foldersService.fetchFolders(isForceReload: true, for: appContext.user) handleNewFolders(with: folders) } catch { handleError(with: error) @@ -250,10 +245,7 @@ extension MyMenuViewController { private func node(for section: Sections, row: Int) -> ASCellNode { switch (section, state) { case (.header, _): - let headerInput = decorator.header( - for: appContext.dataService.currentUser, - image: state.arrowImage - ) + let headerInput = decorator.header(for: appContext.user, image: state.arrowImage) return TextImageNode(input: headerInput) { [weak self] node in self?.handleTapOn(header: node) } @@ -286,7 +278,7 @@ extension MyMenuViewController { switch folder.itemType { case .folder: let input = InboxViewModel(folder) - let viewController = InboxViewControllerFactory.make(appContext: appContext, with: input) + let viewController = InboxViewControllerFactory.make(appContext: appContext, viewModel: input) if let topController = topController(controllerType: InboxViewController.self), topController.path == folder.path { diff --git a/FlowCrypt/Controllers/Threads/ThreadDetailsViewController.swift b/FlowCrypt/Controllers/Threads/ThreadDetailsViewController.swift index 912772f42..d896dc291 100644 --- a/FlowCrypt/Controllers/Threads/ThreadDetailsViewController.swift +++ b/FlowCrypt/Controllers/Threads/ThreadDetailsViewController.swift @@ -32,13 +32,12 @@ final class ThreadDetailsViewController: TableNodeViewController { case thread, message } - private let appContext: AppContext + private let appContext: AppContextWithUser private let messageService: MessageService private let messageOperationsProvider: MessageOperationsProvider private let threadOperationsProvider: MessagesThreadOperationsProvider private let thread: MessageThread private var input: [ThreadDetailsViewController.Input] - private let user: User let trashFolderProvider: TrashFolderProviderType var currentFolderPath: String { @@ -47,17 +46,13 @@ final class ThreadDetailsViewController: TableNodeViewController { private let onComplete: MessageActionCompletion init( - appContext: AppContext, + appContext: AppContextWithUser, messageService: MessageService? = nil, thread: MessageThread, completion: @escaping MessageActionCompletion ) { self.appContext = appContext - guard let user = appContext.dataService.currentUser else { - fatalError("expected current user to exist") // todo - better accept user as VC argument - } - self.user = user - let clientConfiguration = appContext.clientConfigurationService.getSaved(for: user.email) + let clientConfiguration = appContext.clientConfigurationService.getSaved(for: appContext.user.email) self.messageService = messageService ?? MessageService( contactsService: ContactsService( localContactsProvider: LocalContactsProvider( @@ -75,7 +70,7 @@ final class ThreadDetailsViewController: TableNodeViewController { self.threadOperationsProvider = threadOperationsProvider self.messageOperationsProvider = appContext.getRequiredMailProvider().messageOperationsProvider self.trashFolderProvider = TrashFolderProvider( - user: user, + user: appContext.user, foldersService: FoldersService( encryptedStorage: appContext.encryptedStorage, remoteFoldersProvider: appContext.getRequiredMailProvider().remoteFoldersProvider @@ -100,7 +95,7 @@ final class ThreadDetailsViewController: TableNodeViewController { node.delegate = self node.dataSource = self - setupNavigationBar(user: user) + setupNavigationBar(user: appContext.user) expandThreadMessage() } } @@ -457,7 +452,7 @@ extension ThreadDetailsViewController: MessageActionsHandler { private func handleSuccessfulMessage(action: MessageAction) { hideSpinner() - onComplete(action, .init(thread: thread, folderPath: currentFolderPath, activeUserEmail: user.email)) + onComplete(action, .init(thread: thread, folderPath: currentFolderPath, activeUserEmail: appContext.user.email)) navigationController?.popViewController(animated: true) } @@ -597,7 +592,7 @@ extension ThreadDetailsViewController: NavigationChildController { func handleBackButtonTap() { let isRead = input.contains(where: { $0.rawMessage.isMessageRead }) logger.logInfo("Back button. Are all messages read \(isRead)") - onComplete(MessageAction.markAsRead(isRead), .init(thread: thread, folderPath: currentFolderPath, activeUserEmail: self.user.email)) + onComplete(MessageAction.markAsRead(isRead), .init(thread: thread, folderPath: currentFolderPath, activeUserEmail: appContext.user.email)) navigationController?.popViewController(animated: true) } } diff --git a/FlowCrypt/Functionality/Services/AppStartup.swift b/FlowCrypt/Functionality/Services/AppStartup.swift index 7b0ea9d97..6e4118333 100644 --- a/FlowCrypt/Functionality/Services/AppStartup.swift +++ b/FlowCrypt/Functionality/Services/AppStartup.swift @@ -62,29 +62,24 @@ struct AppStartup { @MainActor private func chooseView(for window: UIWindow) { - let entryPoint = entryPointForUser() - - let viewController: UIViewController - - switch entryPoint { + switch entryPointForUser() { case .mainFlow: - let contentViewController = InboxViewContainerController(appContext: appContext) - viewController = SideMenuNavigationController(appContext: appContext, contentViewController: contentViewController) + startMainFlow(appContext: appContext, window: window) case .signIn: - viewController = MainNavigationController(rootViewController: SignInViewController(appContext: appContext)) + window.rootViewController = MainNavigationController( + rootViewController: SignInViewController(appContext: appContext) + ) case .setupFlow(let userId): let setupViewController = SetupInitialViewController(appContext: appContext, user: userId) - viewController = MainNavigationController(rootViewController: setupViewController) + window.rootViewController = MainNavigationController(rootViewController: setupViewController) } - - window.rootViewController = viewController } private func entryPointForUser() -> EntryPoint { if !appContext.dataService.isLoggedIn { logger.logInfo("User is not logged in -> signIn") return .signIn - } else if appContext.dataService.isSetupFinished { + } else if appContext.dataService.isSetupFinished, appContext.dataService.currentUser != nil { logger.logInfo("Setup finished -> mainFlow") return .mainFlow } else if let session = appContext.session, let userId = makeUserIdForSetup(session: session) { @@ -146,4 +141,37 @@ struct AppStartup { alert.addAction(retry) window.rootViewController?.present(alert, animated: true, completion: nil) } + + @MainActor + private func startMainFlow(appContext: AppContext, window: UIWindow) { + let session = appContext.session + + guard + let authType = appContext.dataService.currentAuthType, + let user = appContext.dataService.currentUser + else { + let message = "Wrong application state. User not found for session \(session?.description ?? "nil")" + logger.logError(message) + + if window.rootViewController == nil { + window.rootViewController = UIViewController() + } + + window.rootViewController?.showAlert( + title: "error".localized, + message: message, + onOk: { fatalError() } + ) + + return + } + + let appContextWithUser = appContext.withSession(session: session, authType: authType, user: user) + let contentViewController = InboxViewContainerController(appContext: appContextWithUser) + let viewController = SideMenuNavigationController( + appContext: appContextWithUser, + contentViewController: contentViewController + ) + window.rootViewController = viewController + } } diff --git a/FlowCrypt/Functionality/Services/GlobalRouter.swift b/FlowCrypt/Functionality/Services/GlobalRouter.swift index 9d3de66f4..49489e554 100644 --- a/FlowCrypt/Functionality/Services/GlobalRouter.swift +++ b/FlowCrypt/Functionality/Services/GlobalRouter.swift @@ -74,10 +74,10 @@ extension GlobalRouter: GlobalRouterType { ) try appContext.userAccountService.startSessionFor(session: session) viewController.hideSpinner() - proceed(with: appContext.withSession(session)) + proceed(with: appContext, session: session) case .other(let session): try appContext.userAccountService.startSessionFor(session: session) - proceed(with: appContext.withSession(session)) + proceed(with: appContext, session: session) } } catch { if case .gmailLogin(let viewController) = route { @@ -91,7 +91,7 @@ extension GlobalRouter: GlobalRouterType { func signOut(appContext: AppContext) throws { if let session = try appContext.userAccountService.startActiveSessionForNextUser() { logger.logInfo("Start session for another email user \(session)") - proceed(with: appContext.withSession(session)) + proceed(with: appContext, session: session) } else { logger.logInfo("Sign out") appContext.userAccountService.cleanup() @@ -130,7 +130,7 @@ extension GlobalRouter: GlobalRouterType { logger.logWarning("Can't switch active user with \(user.email)") return } - proceed(with: appContext.withSession(session)) + proceed(with: appContext, session: session) } @MainActor @@ -151,6 +151,29 @@ extension GlobalRouter: GlobalRouterType { AppStartup(appContext: appContext).initializeApp(window: keyWindow) } + @MainActor + private func proceed(with appContext: AppContext, session: SessionType) { + logger.logInfo("proceed for session: \(session.description)") + guard + let authType = appContext.dataService.currentAuthType, + let user = appContext.dataService.currentUser + else { + let message = "Wrong application state. User not found for session \(session.description)" + logger.logError(message) + + keyWindow.rootViewController?.showAlert( + title: "error".localized, + message: message, + onOk: { fatalError() } + ) + + return + } + + let appContextWithUser = appContext.withSession(session: session, authType: authType, user: user) + AppStartup(appContext: appContextWithUser).initializeApp(window: keyWindow) + } + @MainActor private func handleSignInError(error: Error, appContext: AppContext) { if let gmailUserError = error as? GoogleUserServiceError {