Skip to content

Commit

Permalink
Merge branch 'account-number-as-voucher-input-error-in-account-flow-i…
Browse files Browse the repository at this point in the history
…os-207'
  • Loading branch information
buggmagnet committed Sep 12, 2023
2 parents b952fff + 5144389 commit d7e598d
Show file tree
Hide file tree
Showing 17 changed files with 389 additions and 76 deletions.
44 changes: 24 additions & 20 deletions ios/MullvadVPN.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions ios/MullvadVPN/Coordinators/AccountCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,19 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting {
}

private func navigateToRedeemVoucher() {
let coordinator = SettingsRedeemVoucherCoordinator(
let coordinator = ProfileVoucherCoordinator(
navigationController: CustomNavigationController(),
interactor: RedeemVoucherInteractor(tunnelManager: interactor.tunnelManager)
interactor: RedeemVoucherInteractor(
tunnelManager: interactor.tunnelManager,
accountsProxy: interactor.accountsProxy,
verifyVoucherAsAccount: false
)
)
coordinator.didFinish = { redeemVoucherCoordinator in
redeemVoucherCoordinator.dismiss(animated: true)
coordinator.didFinish = { coordinator in
coordinator.dismiss(animated: true)
}
coordinator.didCancel = { redeemVoucherCoordinator in
redeemVoucherCoordinator.dismiss(animated: true)
coordinator.didCancel = { coordinator in
coordinator.dismiss(animated: true)
}

coordinator.start()
Expand Down
24 changes: 20 additions & 4 deletions ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//

import Combine
import MullvadREST
import MullvadTypes
import RelayCache
Expand Down Expand Up @@ -43,6 +44,9 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
*/
private let secondaryNavigationContainer = RootContainerViewController()

/// Posts `preferredAccountNumber` notification when user inputs the account number instead of voucher code
private let preferredAccountNumberSubject = PassthroughSubject<String, Never>()

private lazy var secondaryRootConfiguration = ModalPresentationConfiguration(
preferredContentSize: UIMetrics.preferredFormSheetContentSize,
modalPresentationStyle: .custom,
Expand Down Expand Up @@ -70,6 +74,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo

private let apiProxy: REST.APIProxy
private let devicesProxy: REST.DevicesProxy
private let accountsProxy: REST.AccountsProxy
private var tunnelObserver: TunnelObserver?
private var appPreferences: AppPreferencesDataSource

Expand All @@ -85,13 +90,15 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
relayCacheTracker: RelayCacheTracker,
apiProxy: REST.APIProxy,
devicesProxy: REST.DevicesProxy,
accountsProxy: REST.AccountsProxy,
appPreferences: AppPreferencesDataSource
) {
self.tunnelManager = tunnelManager
self.storePaymentManager = storePaymentManager
self.relayCacheTracker = relayCacheTracker
self.apiProxy = apiProxy
self.devicesProxy = devicesProxy
self.accountsProxy = accountsProxy
self.appPreferences = appPreferences

super.init()
Expand Down Expand Up @@ -593,15 +600,21 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
let coordinator = WelcomeCoordinator(
navigationController: horizontalFlowController,
storePaymentManager: storePaymentManager,
tunnelManager: tunnelManager
tunnelManager: tunnelManager,
accountsProxy: accountsProxy
)

coordinator.didFinish = { [weak self] _ in
coordinator.didFinish = { [weak self] in
guard let self else { return }
appPreferences.isShownOnboarding = true
router.dismiss(.welcome, animated: false)
continueFlow(animated: false)
}
coordinator.didLogout = { [weak self] preferredAccountNumber in
guard let self else { return }
router.dismissAll(.primary, animated: true)
continueFlow(animated: true)
preferredAccountNumberSubject.send(preferredAccountNumber)
}

addChild(coordinator)
coordinator.start(animated: animated)
Expand Down Expand Up @@ -634,6 +647,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
devicesProxy: devicesProxy
)

coordinator.preferredAccountNumberPublisher = preferredAccountNumberSubject.eraseToAnyPublisher()

coordinator.didFinish = { [weak self] _ in
self?.continueFlow(animated: true)
}
Expand Down Expand Up @@ -682,7 +697,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
private func presentAccount(animated: Bool, completion: @escaping (Coordinator) -> Void) {
let accountInteractor = AccountInteractor(
storePaymentManager: storePaymentManager,
tunnelManager: tunnelManager
tunnelManager: tunnelManager,
accountsProxy: accountsProxy
)

let coordinator = AccountCoordinator(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// AccountRedeemingVoucherCoordinator.swift
// CreateAccountVoucherCoordinator.swift
// MullvadVPN
//
// Created by Mojgan on 2023-07-03.
Expand All @@ -10,32 +10,35 @@ import MullvadREST
import Routing
import UIKit

public class AccountRedeemingVoucherCoordinator: Coordinator, Presentable {
public class CreateAccountVoucherCoordinator: Coordinator {
private let navigationController: RootContainerViewController
private let viewController: RedeemVoucherViewController
private let interactor: RedeemVoucherInteractor

var didFinish: ((AccountRedeemingVoucherCoordinator) -> Void)?
var didCancel: ((AccountRedeemingVoucherCoordinator) -> Void)?

public var presentedViewController: UIViewController {
viewController
}
var didFinish: ((CreateAccountVoucherCoordinator) -> Void)?
var didCancel: ((CreateAccountVoucherCoordinator) -> Void)?
var didLogout: ((CreateAccountVoucherCoordinator, String) -> Void)?

init(
navigationController: RootContainerViewController,
interactor: RedeemVoucherInteractor
) {
self.navigationController = navigationController
self.interactor = interactor
viewController = RedeemVoucherViewController(interactor: interactor)
}

func start() {
interactor.didLogout = { [weak self] accountNumber in
guard let self else { return }
didLogout?(self, accountNumber)
}
viewController.delegate = self
navigationController.pushViewController(viewController, animated: true)
}
}

extension AccountRedeemingVoucherCoordinator: RedeemVoucherViewControllerDelegate {
extension CreateAccountVoucherCoordinator: RedeemVoucherViewControllerDelegate {
func redeemVoucherDidSucceed(_ controller: RedeemVoucherViewController, with response: REST.SubmitVoucherResponse) {
let coordinator = AddCreditSucceededCoordinator(
purchaseType: .redeemingVoucher,
Expand Down
12 changes: 12 additions & 0 deletions ios/MullvadVPN/Coordinators/LoginCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//

import Combine
import MullvadREST
import MullvadTypes
import Operations
Expand All @@ -18,10 +19,13 @@ final class LoginCoordinator: Coordinator, DeviceManagementViewControllerDelegat

private var loginController: LoginViewController?
private var lastLoginAction: LoginAction?
private var subscriptions = Set<Combine.AnyCancellable>()

var didFinish: ((LoginCoordinator) -> Void)?
var didCreateAccount: (() -> Void)?

var preferredAccountNumberPublisher: AnyPublisher<String, Never>?

let navigationController: RootContainerViewController

init(
Expand All @@ -41,6 +45,14 @@ final class LoginCoordinator: Coordinator, DeviceManagementViewControllerDelegat
loginController.didFinishLogin = { [weak self] action, error in
self?.didFinishLogin(action: action, error: error) ?? .nothing
}

preferredAccountNumberPublisher?
.compactMap { $0 }
.sink(receiveValue: { preferredAccountNumber in
interactor.suggestPreferredAccountNumber?(preferredAccountNumber)
})
.store(in: &subscriptions)

interactor.didCreateAccount = self.didCreateAccount

navigationController.pushViewController(loginController, animated: animated)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// SettingsRedeemVoucherCoordinator.swift
// ProfileVoucherCoordinator.swift
// MullvadVPN
//
// Created by Mojgan on 2023-06-13.
Expand All @@ -11,11 +11,12 @@ import MullvadREST
import Routing
import UIKit

final class SettingsRedeemVoucherCoordinator: Coordinator, Presentable {
final class ProfileVoucherCoordinator: Coordinator, Presentable {
private let navigationController: UINavigationController
private let viewController: RedeemVoucherViewController
var didFinish: ((SettingsRedeemVoucherCoordinator) -> Void)?
var didCancel: ((SettingsRedeemVoucherCoordinator) -> Void)?

var didFinish: ((ProfileVoucherCoordinator) -> Void)?
var didCancel: ((ProfileVoucherCoordinator) -> Void)?

init(
navigationController: UINavigationController,
Expand All @@ -36,7 +37,7 @@ final class SettingsRedeemVoucherCoordinator: Coordinator, Presentable {
}
}

extension SettingsRedeemVoucherCoordinator: RedeemVoucherViewControllerDelegate {
extension ProfileVoucherCoordinator: RedeemVoucherViewControllerDelegate {
func redeemVoucherDidSucceed(
_ controller: RedeemVoucherViewController,
with response: REST.SubmitVoucherResponse
Expand All @@ -51,15 +52,15 @@ extension SettingsRedeemVoucherCoordinator: RedeemVoucherViewControllerDelegate
}
}

extension SettingsRedeemVoucherCoordinator: AddCreditSucceededViewControllerDelegate {
extension ProfileVoucherCoordinator: AddCreditSucceededViewControllerDelegate {
func addCreditSucceededViewControllerDidFinish(in controller: AddCreditSucceededViewController) {
didFinish?(self)
}

func header(in controller: AddCreditSucceededViewController) -> String {
NSLocalizedString(
"REDEEM_VOUCHER_SUCCESS_TITLE",
tableName: "RedeemVoucher",
tableName: "ProfileRedeemVoucher",
value: "Voucher was successfully redeemed.",
comment: ""
)
Expand All @@ -68,7 +69,7 @@ extension SettingsRedeemVoucherCoordinator: AddCreditSucceededViewControllerDele
func titleForAction(in controller: AddCreditSucceededViewController) -> String {
NSLocalizedString(
"REDEEM_VOUCHER_DISMISS_BUTTON",
tableName: "RedeemVoucher",
tableName: "ProfileRedeemVoucher",
value: "Got it!",
comment: ""
)
Expand Down
29 changes: 21 additions & 8 deletions ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ final class WelcomeCoordinator: Coordinator, Presentable, Presenting {
private let storePaymentManager: StorePaymentManager
private let tunnelManager: TunnelManager
private let inAppPurchaseInteractor: InAppPurchaseInteractor
private let accountsProxy: REST.AccountsProxy

private var viewController: WelcomeViewController?

var didFinish: ((WelcomeCoordinator) -> Void)?
var didFinish: (() -> Void)?
var didLogout: ((String) -> Void)?

var presentedViewController: UIViewController {
navigationController
Expand All @@ -33,11 +35,13 @@ final class WelcomeCoordinator: Coordinator, Presentable, Presenting {
init(
navigationController: RootContainerViewController,
storePaymentManager: StorePaymentManager,
tunnelManager: TunnelManager
tunnelManager: TunnelManager,
accountsProxy: REST.AccountsProxy
) {
self.navigationController = navigationController
self.storePaymentManager = storePaymentManager
self.tunnelManager = tunnelManager
self.accountsProxy = accountsProxy
self.inAppPurchaseInteractor = InAppPurchaseInteractor(storePaymentManager: storePaymentManager)
}

Expand All @@ -52,8 +56,7 @@ final class WelcomeCoordinator: Coordinator, Presentable, Presenting {
let coordinator = SetupAccountCompletedCoordinator(navigationController: navigationController)
coordinator.didFinish = { [weak self] coordinator in
coordinator.removeFromParent()
guard let self else { return }
didFinish?(self)
self?.didFinish?()
}
addChild(coordinator)
coordinator.start(animated: true)
Expand Down Expand Up @@ -127,7 +130,7 @@ extension WelcomeCoordinator: WelcomeViewControllerDelegate {
coordinator.didFinish = { [weak self] coordinator in
guard let self else { return }
coordinator.removeFromParent()
didFinish?(self)
didFinish?()
}

coordinator.didCancel = { coordinator in
Expand All @@ -140,9 +143,13 @@ extension WelcomeCoordinator: WelcomeViewControllerDelegate {
}

func didRequestToRedeemVoucher(controller: WelcomeViewController) {
let coordinator = AccountRedeemingVoucherCoordinator(
let coordinator = CreateAccountVoucherCoordinator(
navigationController: navigationController,
interactor: RedeemVoucherInteractor(tunnelManager: tunnelManager)
interactor: RedeemVoucherInteractor(
tunnelManager: tunnelManager,
accountsProxy: accountsProxy,
verifyVoucherAsAccount: true
)
)

coordinator.didCancel = { [weak self] coordinator in
Expand All @@ -152,9 +159,15 @@ extension WelcomeCoordinator: WelcomeViewControllerDelegate {
}

coordinator.didFinish = { [weak self] coordinator in
guard let self else { return }
coordinator.removeFromParent()
didFinish?()
}

coordinator.didLogout = { [weak self] coordinator, accountNumber in
guard let self else { return }
didFinish?(self)
coordinator.removeFromParent()
didLogout?(accountNumber)
}

addChild(coordinator)
Expand Down
1 change: 1 addition & 0 deletions ios/MullvadVPN/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, SettingsMigrationUIHand
relayCacheTracker: appDelegate.relayCacheTracker,
apiProxy: appDelegate.apiProxy,
devicesProxy: appDelegate.devicesProxy,
accountsProxy: appDelegate.accountsProxy,
appPreferences: AppPreferences()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,22 @@ import StoreKit
final class AccountInteractor {
private let storePaymentManager: StorePaymentManager
let tunnelManager: TunnelManager
let accountsProxy: REST.AccountsProxy

var didReceivePaymentEvent: ((StorePaymentEvent) -> Void)?
var didReceiveDeviceState: ((DeviceState) -> Void)?

private var tunnelObserver: TunnelObserver?
private var paymentObserver: StorePaymentObserver?

init(storePaymentManager: StorePaymentManager, tunnelManager: TunnelManager) {
init(
storePaymentManager: StorePaymentManager,
tunnelManager: TunnelManager,
accountsProxy: REST.AccountsProxy
) {
self.storePaymentManager = storePaymentManager
self.tunnelManager = tunnelManager
self.accountsProxy = accountsProxy

let tunnelObserver =
TunnelBlockObserver(didUpdateDeviceState: { [weak self] _, deviceState, _ in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class LoginInteractor {
private let logger = Logger(label: "LoginInteractor")
private var tunnelObserver: TunnelObserver?
var didCreateAccount: (() -> Void)?
var suggestPreferredAccountNumber: ((String) -> Void)?

init(tunnelManager: TunnelManager) {
self.tunnelManager = tunnelManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ class LoginViewController: UIViewController, RootContainment {
self?.attemptLogin()
}

interactor.suggestPreferredAccountNumber = { [weak self] value in
self?.contentView.accountInputGroup.setAccount(value)
}

contentView.accountInputGroup.setOnReturnKey { [weak self] _ in
guard let self else { return true }

Expand Down
Loading

0 comments on commit d7e598d

Please sign in to comment.