Skip to content

Commit

Permalink
Refactor alerts to be presented on their respective coordinator
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson committed Sep 6, 2023
1 parent 34fbe02 commit 974f5c3
Show file tree
Hide file tree
Showing 23 changed files with 189 additions and 69 deletions.
2 changes: 2 additions & 0 deletions ios/.swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ line_length:
ignores_interpolated_strings: true
warning: 120
error: 300
cyclomatic_complexity:
ignores_case_statements: true

type_name:
min_length: 4
Expand Down
2 changes: 1 addition & 1 deletion ios/MullvadVPN/Classes/AppRoutes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ enum AppRoute: AppRouteProtocol {
/**
Alert route.
*/
case alert(AlertPresentation)
case alert(String)

/**
Routes that are part of primary horizontal navigation group.
Expand Down
23 changes: 14 additions & 9 deletions ios/MullvadVPN/Coordinators/AccountCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting {
navigationController
}

var presentationContext: UIViewController {
navigationController
}

var didFinish: ((AccountCoordinator, AccountDismissReason) -> Void)?

init(
Expand All @@ -48,7 +44,7 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting {

let accountController = AccountViewController(
interactor: interactor,
errorPresenter: PaymentAlertPresenter(coordinator: self)
errorPresenter: PaymentAlertPresenter(alertContext: self)
)

accountController.actionHandler = handleViewControllerAction
Expand Down Expand Up @@ -133,18 +129,25 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting {
// MARK: - Alerts

private func logOut() {
let presentation = AlertPresentation(icon: .spinner, message: nil, buttons: [])
let presentation = AlertPresentation(
id: "account-logout-alert",
icon: .spinner,
message: nil,
buttons: []
)

let alertPresenter = AlertPresenter(context: self)

interactor.logout {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { [weak self] in
guard let self else { return }

applicationRouter?.dismiss(.alert(presentation), animated: true)
alertPresenter.dismissAlert(presentation: presentation, animated: true)
self.didFinish?(self, .userLoggedOut)
}
}

applicationRouter?.present(.alert(presentation))
alertPresenter.showAlert(presentation: presentation, animated: true)
}

private func showAccountDeviceInfo() {
Expand All @@ -164,6 +167,7 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting {
)

let presentation = AlertPresentation(
id: "account-device-info-alert",
message: message,
buttons: [AlertAction(
title: NSLocalizedString(
Expand All @@ -176,6 +180,7 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting {
)]
)

applicationRouter?.present(.alert(presentation), animated: true)
let presenter = AlertPresenter(context: self)
presenter.showAlert(presentation: presentation, animated: true)
}
}
31 changes: 18 additions & 13 deletions ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import UIKit
Application coordinator managing split view and two navigation contexts.
*/
final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewControllerDelegate,
UISplitViewControllerDelegate, ApplicationRouterDelegate,
NotificationManagerDelegate {
UISplitViewControllerDelegate, ApplicationRouterDelegate, NotificationManagerDelegate {
typealias RouteType = AppRoute

/**
Expand Down Expand Up @@ -120,11 +119,11 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo

func applicationRouter(
_ router: ApplicationRouter<RouteType>,
route: AppRoute,
presentWithContext context: RoutePresentationContext<RouteType>,
animated: Bool,
completion: @escaping (Coordinator) -> Void
) {
switch route {
switch context.route {
case .account:
presentAccount(animated: animated, completion: completion)

Expand Down Expand Up @@ -155,8 +154,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
case .welcome:
presentWelcome(animated: animated, completion: completion)

case let .alert(presentation):
presentAlert(presentation: presentation, animated: animated, completion: completion)
case .alert:
presentAlert(animated: animated, context: context, completion: completion)
}
}

Expand Down Expand Up @@ -564,11 +563,10 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
)

coordinator.didFinishPayment = { [weak self] _ in
guard let self else { return }
guard let self = self else { return }

if shouldDismissOutOfTime() {
router.dismiss(.outOfTime, animated: true)

continueFlow(animated: true)
}
}
Expand All @@ -589,7 +587,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
)

coordinator.didFinish = { [weak self] _ in
guard let self else { return }
guard let self = self else { return }
appPreferences.isShownOnboarding = true
router.dismiss(.welcome, animated: false)
continueFlow(animated: false)
Expand Down Expand Up @@ -642,19 +640,24 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
}

private func presentAlert(
presentation: AlertPresentation,
animated: Bool,
context: RoutePresentationContext<RouteType>,
completion: @escaping (Coordinator) -> Void
) {
let coordinator = AlertCoordinator(presentation: presentation)
guard let metadata = context.metadata as? AlertMetadata else {
assertionFailure("Could not get AlertMetadata from RoutePresentationContext.")
return
}

let coordinator = AlertCoordinator(presentation: metadata.presentation)

coordinator.didFinish = { [weak self] in
self?.router.dismiss(.alert(presentation))
self?.router.dismiss(.alert(metadata.presentation.id))
}

coordinator.start()

presentChild(coordinator, animated: animated) {
metadata.context.presentChild(coordinator, animated: animated) {
completion(coordinator)
}
}
Expand Down Expand Up @@ -996,4 +999,6 @@ private protocol Poppable: Presentable {
animated: Bool,
completion: () -> Void
)

// swiftlint:disable:next file_length
}
6 changes: 4 additions & 2 deletions ios/MullvadVPN/Coordinators/InAppPurchaseCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Routing
import StoreKit
import UIKit

class InAppPurchaseCoordinator: Coordinator, Presentable {
class InAppPurchaseCoordinator: Coordinator, Presenting, Presentable {
private let navigationController: RootContainerViewController
private let interactor: InAppPurchaseInteractor

Expand Down Expand Up @@ -50,6 +50,7 @@ class InAppPurchaseCoordinator: Coordinator, Presentable {

case let .failure(failure):
let presentation = AlertPresentation(
id: "in-app-purchase-error-alert",
icon: .alert,
message: failure.error.localizedDescription,
buttons: [
Expand All @@ -69,7 +70,8 @@ class InAppPurchaseCoordinator: Coordinator, Presentable {
]
)

applicationRouter?.present(.alert(presentation), animated: true)
let presenter = AlertPresenter(context: self)
presenter.showAlert(presentation: presentation, animated: true)
}
}
}
Expand Down
11 changes: 8 additions & 3 deletions ios/MullvadVPN/Coordinators/LoginCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Operations
import Routing
import UIKit

final class LoginCoordinator: Coordinator, DeviceManagementViewControllerDelegate {
final class LoginCoordinator: Coordinator, Presenting, DeviceManagementViewControllerDelegate {
private let tunnelManager: TunnelManager
private let devicesProxy: REST.DevicesProxy

Expand All @@ -22,6 +22,10 @@ final class LoginCoordinator: Coordinator, DeviceManagementViewControllerDelegat
var didFinish: ((LoginCoordinator) -> Void)?
var didCreateAccount: (() -> Void)?

var presentationContext: UIViewController {
navigationController
}

let navigationController: RootContainerViewController

init(
Expand Down Expand Up @@ -107,11 +111,12 @@ final class LoginCoordinator: Coordinator, DeviceManagementViewControllerDelegat
)
let controller = DeviceManagementViewController(
interactor: interactor,
alertPresenter: AlertPresenter(coordinator: self)
alertPresenter: AlertPresenter(context: self)
)
controller.delegate = self

controller.fetchDevices(animateUpdates: false) { [weak self] result in
guard let self else { return }
guard let self = self else { return }

switch result {
case .success:
Expand Down
8 changes: 6 additions & 2 deletions ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
import Routing
import UIKit

class OutOfTimeCoordinator: Coordinator, OutOfTimeViewControllerDelegate {
class OutOfTimeCoordinator: Coordinator, Presenting, OutOfTimeViewControllerDelegate {
let navigationController: RootContainerViewController
let storePaymentManager: StorePaymentManager
let tunnelManager: TunnelManager

var didFinishPayment: ((OutOfTimeCoordinator) -> Void)?

var presentationContext: UIViewController {
navigationController
}

private(set) var isMakingPayment = false
private var viewController: OutOfTimeViewController?

Expand All @@ -42,7 +46,7 @@ class OutOfTimeCoordinator: Coordinator, OutOfTimeViewControllerDelegate {

let controller = OutOfTimeViewController(
interactor: interactor,
errorPresenter: PaymentAlertPresenter(coordinator: self)
errorPresenter: PaymentAlertPresenter(alertContext: self)
)

controller.delegate = self
Expand Down
8 changes: 2 additions & 6 deletions ios/MullvadVPN/Coordinators/SettingsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV
navigationController
}

var presentationContext: UIViewController {
navigationController
}

var willNavigate: ((
_ coordinator: SettingsCoordinator,
_ from: SettingsNavigationRoute?,
Expand Down Expand Up @@ -159,13 +155,13 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV
case .preferences:
return PreferencesViewController(
interactor: interactorFactory.makePreferencesInteractor(),
alertPresenter: AlertPresenter(coordinator: self)
alertPresenter: AlertPresenter(context: self)
)

case .problemReport:
return ProblemReportViewController(
interactor: interactorFactory.makeProblemReportInteractor(),
alertPresenter: AlertPresenter(coordinator: self)
alertPresenter: AlertPresenter(context: self)
)

case .faq:
Expand Down
10 changes: 8 additions & 2 deletions ios/MullvadVPN/Coordinators/TunnelCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
import Routing
import UIKit

class TunnelCoordinator: Coordinator {
class TunnelCoordinator: Coordinator, Presenting {
private let tunnelManager: TunnelManager
private let controller: TunnelViewController

private var tunnelObserver: TunnelObserver?

var presentationContext: UIViewController {
controller
}

var rootViewController: UIViewController {
controller
}
Expand Down Expand Up @@ -59,6 +63,7 @@ class TunnelCoordinator: Coordinator {

private func showCancelTunnelAlert() {
let presentation = AlertPresentation(
id: "main-cancel-tunnel-alert",
icon: .alert,
message: NSLocalizedString(
"CANCEL_TUNNEL_ALERT_MESSAGE",
Expand Down Expand Up @@ -91,6 +96,7 @@ class TunnelCoordinator: Coordinator {
]
)

applicationRouter?.present(.alert(presentation), animated: true)
let presenter = AlertPresenter(context: self)
presenter.showAlert(presentation: presentation, animated: true)
}
}
10 changes: 4 additions & 6 deletions ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ final class WelcomeCoordinator: Coordinator, Presentable, Presenting {
navigationController
}

var presentationContext: UIViewController {
navigationController
}

init(
navigationController: RootContainerViewController,
storePaymentManager: StorePaymentManager,
Expand Down Expand Up @@ -102,6 +98,7 @@ extension WelcomeCoordinator: WelcomeViewControllerDelegate {
)

let presentation = AlertPresentation(
id: "welcome-device-name-alert",
icon: .info,
message: message,
buttons: [
Expand All @@ -117,7 +114,8 @@ extension WelcomeCoordinator: WelcomeViewControllerDelegate {
]
)

applicationRouter?.present(.alert(presentation), animated: true)
let presenter = AlertPresenter(context: self)
presenter.showAlert(presentation: presentation, animated: true)
}

func didRequestToPurchaseCredit(controller: WelcomeViewController, accountNumber: String, product: SKProduct) {
Expand Down Expand Up @@ -150,7 +148,7 @@ extension WelcomeCoordinator: WelcomeViewControllerDelegate {
)

coordinator.didCancel = { [weak self] coordinator in
guard let self else { return }
guard let self = self else { return }
navigationController.popViewController(animated: true)
coordinator.removeFromParent()
}
Expand Down
10 changes: 9 additions & 1 deletion ios/MullvadVPN/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, SettingsMigrationUIHand
private var tunnelObserver: TunnelObserver?

private var appDelegate: AppDelegate {
// swiftlint:disable:next force_cast
UIApplication.shared.delegate as! AppDelegate
}

Expand Down Expand Up @@ -185,7 +186,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, SettingsMigrationUIHand
// MARK: - SettingsMigrationUIHandler

func showMigrationError(_ error: Error, completionHandler: @escaping () -> Void) {
guard let appCoordinator else {
completionHandler()
return
}

let presentation = AlertPresentation(
id: "settings-migration-error-alert",
title: NSLocalizedString(
"ALERT_TITLE",
tableName: "SettingsMigrationUI",
Expand All @@ -204,7 +211,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, SettingsMigrationUIHand
]
)

appCoordinator?.router.present(.alert(presentation), animated: true) ?? completionHandler()
let presenter = AlertPresenter(context: appCoordinator)
presenter.showAlert(presentation: presentation, animated: true)
}

private static func migrationErrorReason(_ error: Error) -> String {
Expand Down
Loading

0 comments on commit 974f5c3

Please sign in to comment.