summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteffen Ernst <steffen.ernst@mullvad.net>2025-02-10 12:26:24 +0100
committerSteffen Ernst <steffen.ernst@mullvad.net>2025-02-17 09:40:34 +0100
commitf08ffd7bab6c71c89bc7078833479ce742c4cb10 (patch)
tree96d1ef3a9af464894be4386373cd60e8ba060bcc
parent8b5fee70ee1c00e9cc37f0da78534b57c42e2869 (diff)
downloadmullvadvpn-f08ffd7bab6c71c89bc7078833479ce742c4cb10.tar.xz
mullvadvpn-f08ffd7bab6c71c89bc7078833479ce742c4cb10.zip
Remove voucher from welcome and out of time
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj8
-rw-r--r--ios/MullvadVPN/Coordinators/AccountCoordinator.swift29
-rw-r--r--ios/MullvadVPN/Coordinators/AddCreditSucceededCoordinator.swift77
-rw-r--r--ios/MullvadVPN/Coordinators/CreateAccountVoucherCoordinator.swift74
-rw-r--r--ios/MullvadVPN/Coordinators/InAppPurchaseCoordinator.swift8
-rw-r--r--ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift29
-rw-r--r--ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift64
-rw-r--r--ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeContentView.swift37
-rw-r--r--ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeInteractor.swift13
-rw-r--r--ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift5
-rw-r--r--ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeInteractor.swift39
-rw-r--r--ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift19
12 files changed, 49 insertions, 353 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index e13e1af95a..cc8a72cc14 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -593,12 +593,10 @@
7A9BE5AB2B909A1700E2A7D0 /* LocationDataSourceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE5D2B739A73003F4EDB /* LocationDataSourceProtocol.swift */; };
7A9BE5AD2B90DF2D00E2A7D0 /* AllLocationsDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9BE5AC2B90DF2D00E2A7D0 /* AllLocationsDataSourceTests.swift */; };
7A9CCCB32A96302800DD6A34 /* WelcomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA12A96302700DD6A34 /* WelcomeCoordinator.swift */; };
- 7A9CCCB52A96302800DD6A34 /* AddCreditSucceededCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA32A96302700DD6A34 /* AddCreditSucceededCoordinator.swift */; };
7A9CCCB62A96302800DD6A34 /* OutOfTimeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA42A96302700DD6A34 /* OutOfTimeCoordinator.swift */; };
7A9CCCB72A96302800DD6A34 /* RevokedCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA52A96302700DD6A34 /* RevokedCoordinator.swift */; };
7A9CCCB82A96302800DD6A34 /* SetupAccountCompletedCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA62A96302700DD6A34 /* SetupAccountCompletedCoordinator.swift */; };
7A9CCCB92A96302800DD6A34 /* LocationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA72A96302700DD6A34 /* LocationCoordinator.swift */; };
- 7A9CCCBA2A96302800DD6A34 /* CreateAccountVoucherCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA82A96302700DD6A34 /* CreateAccountVoucherCoordinator.swift */; };
7A9CCCBC2A96302800DD6A34 /* ChangeLogCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCAA2A96302700DD6A34 /* ChangeLogCoordinator.swift */; };
7A9CCCBD2A96302800DD6A34 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCAB2A96302800DD6A34 /* LoginCoordinator.swift */; };
7A9CCCBE2A96302800DD6A34 /* AccountDeletionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCAC2A96302800DD6A34 /* AccountDeletionCoordinator.swift */; };
@@ -1995,12 +1993,10 @@
7A9BE5AC2B90DF2D00E2A7D0 /* AllLocationsDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllLocationsDataSourceTests.swift; sourceTree = "<group>"; };
7A9CCCA12A96302700DD6A34 /* WelcomeCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WelcomeCoordinator.swift; sourceTree = "<group>"; };
7A9CCCA22A96302700DD6A34 /* TermsOfServiceCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TermsOfServiceCoordinator.swift; sourceTree = "<group>"; };
- 7A9CCCA32A96302700DD6A34 /* AddCreditSucceededCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddCreditSucceededCoordinator.swift; sourceTree = "<group>"; };
7A9CCCA42A96302700DD6A34 /* OutOfTimeCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutOfTimeCoordinator.swift; sourceTree = "<group>"; };
7A9CCCA52A96302700DD6A34 /* RevokedCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RevokedCoordinator.swift; sourceTree = "<group>"; };
7A9CCCA62A96302700DD6A34 /* SetupAccountCompletedCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetupAccountCompletedCoordinator.swift; sourceTree = "<group>"; };
7A9CCCA72A96302700DD6A34 /* LocationCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationCoordinator.swift; sourceTree = "<group>"; };
- 7A9CCCA82A96302700DD6A34 /* CreateAccountVoucherCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateAccountVoucherCoordinator.swift; sourceTree = "<group>"; };
7A9CCCAA2A96302700DD6A34 /* ChangeLogCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeLogCoordinator.swift; sourceTree = "<group>"; };
7A9CCCAB2A96302800DD6A34 /* LoginCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginCoordinator.swift; sourceTree = "<group>"; };
7A9CCCAC2A96302800DD6A34 /* AccountDeletionCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountDeletionCoordinator.swift; sourceTree = "<group>"; };
@@ -3651,11 +3647,9 @@
58EFC76F2AFB3FA800E9F4CB /* Settings */,
7A9CCCAF2A96302800DD6A34 /* AccountCoordinator.swift */,
7A9CCCAC2A96302800DD6A34 /* AccountDeletionCoordinator.swift */,
- 7A9CCCA32A96302700DD6A34 /* AddCreditSucceededCoordinator.swift */,
7A2960F52A963F7500389B82 /* AlertCoordinator.swift */,
7A9CCCB12A96302800DD6A34 /* ApplicationCoordinator.swift */,
7A9CCCAA2A96302700DD6A34 /* ChangeLogCoordinator.swift */,
- 7A9CCCA82A96302700DD6A34 /* CreateAccountVoucherCoordinator.swift */,
7A9CCCA72A96302700DD6A34 /* LocationCoordinator.swift */,
7A9CCCAB2A96302800DD6A34 /* LoginCoordinator.swift */,
7A9CCCA42A96302700DD6A34 /* OutOfTimeCoordinator.swift */,
@@ -6077,7 +6071,6 @@
7A9CCCBF2A96302800DD6A34 /* SettingsCoordinator.swift in Sources */,
58F70FE52AEA707800E6890E /* StoreTransactionLog.swift in Sources */,
582AE3102440A6CA00E6733A /* InputTextFormatter.swift in Sources */,
- 7A9CCCBA2A96302800DD6A34 /* CreateAccountVoucherCoordinator.swift in Sources */,
7A6F2FAD2AFD3DA7006D0856 /* CustomDNSViewController.swift in Sources */,
5820EDAB288FF0D2006BF4E4 /* DeviceRowView.swift in Sources */,
F0E8CC0C2A4EE672007ED3B4 /* SetupAccountCompletedController.swift in Sources */,
@@ -6096,7 +6089,6 @@
58CEB3022AFD365600E6E088 /* SwitchCellContentConfiguration.swift in Sources */,
7AA130A12D01B1E200640DF9 /* SplitMainButton.swift in Sources */,
7AA1309F2D007B2500640DF9 /* VisualEffectView.swift in Sources */,
- 7A9CCCB52A96302800DD6A34 /* AddCreditSucceededCoordinator.swift in Sources */,
7A0C0F632A979C4A0058EFCE /* Coordinator+Router.swift in Sources */,
7A6F2FAB2AFD3097006D0856 /* CustomDNSCellFactory.swift in Sources */,
58A99ED3240014A0006599E9 /* TermsOfServiceViewController.swift in Sources */,
diff --git a/ios/MullvadVPN/Coordinators/AccountCoordinator.swift b/ios/MullvadVPN/Coordinators/AccountCoordinator.swift
index 0ff99f583a..8438c8997b 100644
--- a/ios/MullvadVPN/Coordinators/AccountCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/AccountCoordinator.swift
@@ -16,11 +16,6 @@ enum AccountDismissReason: Equatable, Sendable {
case accountDeletion
}
-enum AddedMoreCreditOption: Equatable, Sendable {
- case redeemingVoucher
- case inAppPurchase
-}
-
final class AccountCoordinator: Coordinator, Presentable, Presenting, @unchecked Sendable {
private let interactor: AccountInteractor
private let storePaymentManager: StorePaymentManager
@@ -74,32 +69,20 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting, @unchecked
case .showFailedToLoadProducts:
showFailToFetchProducts()
case .showRestorePurchases:
- showRestorePurchases()
+ didRequestShowInAppPurchase(paymentAction: .restorePurchase)
case .showPurchaseOptions:
- showPurchaseOptions()
+ didRequestShowInAppPurchase(paymentAction: .purchase)
}
}
- private func showPurchaseOptions() {
- guard let accountNumber = interactor.deviceState.accountData?.number else { return }
- let coordinator = InAppPurchaseCoordinator(
- storePaymentManager: storePaymentManager,
- accountNumber: accountNumber,
- paymentAction: .purchase
- )
- coordinator.didFinish = { coordinator, _ in
- coordinator.dismiss(animated: true)
- }
- coordinator.start()
- presentChild(coordinator, animated: true)
- }
-
- private func showRestorePurchases() {
+ private func didRequestShowInAppPurchase(
+ paymentAction: PaymentAction
+ ) {
guard let accountNumber = interactor.deviceState.accountData?.number else { return }
let coordinator = InAppPurchaseCoordinator(
storePaymentManager: storePaymentManager,
accountNumber: accountNumber,
- paymentAction: .restorePurchase
+ paymentAction: paymentAction
)
coordinator.didFinish = { coordinator, _ in
coordinator.dismiss(animated: true)
diff --git a/ios/MullvadVPN/Coordinators/AddCreditSucceededCoordinator.swift b/ios/MullvadVPN/Coordinators/AddCreditSucceededCoordinator.swift
deleted file mode 100644
index df38a0a85f..0000000000
--- a/ios/MullvadVPN/Coordinators/AddCreditSucceededCoordinator.swift
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// AddCreditSucceededCoordinator.swift
-// MullvadVPN
-//
-// Created by Mojgan on 2023-08-01.
-// Copyright © 2025 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-import Routing
-import UIKit
-
-final class AddCreditSucceededCoordinator: Coordinator {
- var didFinish: ((AddCreditSucceededCoordinator) -> Void)?
-
- let paymentType: PurchaseType
- let timeAdded: Int
- let navigationController: RootContainerViewController
-
- enum PurchaseType {
- case redeemingVoucher, inAppPurchase
- }
-
- init(purchaseType: PurchaseType, timeAdded: Int, navigationController: RootContainerViewController) {
- self.timeAdded = timeAdded
- self.navigationController = navigationController
- self.paymentType = purchaseType
- }
-
- func start() {
- let controller =
- AddCreditSucceededViewController(timeAddedComponents: DateComponents(second: timeAdded))
- controller.delegate = self
- self.navigationController.pushViewController(controller, animated: true)
- }
-}
-
-extension AddCreditSucceededCoordinator: @preconcurrency AddCreditSucceededViewControllerDelegate {
- func header(in controller: AddCreditSucceededViewController) -> String {
- switch paymentType {
- case .inAppPurchase:
- return NSLocalizedString(
- "IN_APP_PURCHASE_SUCCESS_TITLE",
- tableName: "Welcome",
- value: "Time was successfully added.",
- comment: ""
- )
- case .redeemingVoucher:
- return NSLocalizedString(
- "REDEEM_VOUCHER_SUCCESS_TITLE",
- tableName: "Welcome",
- value: "Voucher was successfully redeemed.",
- comment: ""
- )
- }
- }
-
- func titleForAction(in controller: AddCreditSucceededViewController) -> String {
- NSLocalizedString(
- "ADDED_TIME_SUCCESS_DISMISS_BUTTON",
- tableName: "Welcome",
- value: "Next",
- comment: ""
- )
- }
-
- func addCreditSucceededViewControllerDidFinish(in controller: AddCreditSucceededViewController) {
- let coordinator = SetupAccountCompletedCoordinator(navigationController: navigationController)
- coordinator.didFinish = { [weak self] coordinator in
- coordinator.removeFromParent()
- guard let self else { return }
- didFinish?(self)
- }
- addChild(coordinator)
- coordinator.start(animated: true)
- }
-}
diff --git a/ios/MullvadVPN/Coordinators/CreateAccountVoucherCoordinator.swift b/ios/MullvadVPN/Coordinators/CreateAccountVoucherCoordinator.swift
deleted file mode 100644
index d57dcf8847..0000000000
--- a/ios/MullvadVPN/Coordinators/CreateAccountVoucherCoordinator.swift
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// CreateAccountVoucherCoordinator.swift
-// MullvadVPN
-//
-// Created by Mojgan on 2023-07-03.
-// Copyright © 2025 Mullvad VPN AB. All rights reserved.
-//
-
-import MullvadREST
-import Routing
-import UIKit
-
-public class CreateAccountVoucherCoordinator: Coordinator {
- private let navigationController: RootContainerViewController
- private let viewController: RedeemVoucherViewController
- private let interactor: RedeemVoucherInteractor
-
- var didFinish: ((CreateAccountVoucherCoordinator) -> Void)?
- var didCancel: ((CreateAccountVoucherCoordinator) -> Void)?
- var didLogout: ((CreateAccountVoucherCoordinator, String) -> Void)?
-
- init(
- navigationController: RootContainerViewController,
- interactor: RedeemVoucherInteractor
- ) {
- self.navigationController = navigationController
- self.interactor = interactor
-
- var layoutMargins = navigationController.view.layoutMargins.toDirectionalInsets
- layoutMargins.top += UIMetrics.contentLayoutMargins.top
- layoutMargins.bottom += UIMetrics.contentLayoutMargins.bottom
-
- viewController = RedeemVoucherViewController(
- configuration: RedeemVoucherViewConfiguration(
- adjustViewWhenKeyboardAppears: true,
- shouldUseCompactStyle: false,
- layoutMargins: layoutMargins
- ),
- 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 CreateAccountVoucherCoordinator: @preconcurrency RedeemVoucherViewControllerDelegate {
- func redeemVoucherDidSucceed(_ controller: RedeemVoucherViewController, with response: REST.SubmitVoucherResponse) {
- let coordinator = AddCreditSucceededCoordinator(
- purchaseType: .redeemingVoucher,
- timeAdded: response.timeAdded,
- navigationController: navigationController
- )
-
- coordinator.didFinish = { [weak self] coordinator in
- coordinator.removeFromParent()
- guard let self else { return }
- didFinish?(self)
- }
-
- addChild(coordinator)
- coordinator.start()
- }
-
- func redeemVoucherDidCancel(_ controller: RedeemVoucherViewController) {
- didCancel?(self)
- }
-}
diff --git a/ios/MullvadVPN/Coordinators/InAppPurchaseCoordinator.swift b/ios/MullvadVPN/Coordinators/InAppPurchaseCoordinator.swift
index 76d6a10a5a..74ad68d72a 100644
--- a/ios/MullvadVPN/Coordinators/InAppPurchaseCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/InAppPurchaseCoordinator.swift
@@ -16,7 +16,7 @@ enum PaymentAction {
}
final class InAppPurchaseCoordinator: Coordinator, Presentable, Presenting {
- private var sheetController: InAppPurchaseViewController?
+ private var controller: InAppPurchaseViewController?
private let storePaymentManager: StorePaymentManager
private let accountNumber: String
private let paymentAction: PaymentAction
@@ -24,7 +24,7 @@ final class InAppPurchaseCoordinator: Coordinator, Presentable, Presenting {
var didFinish: ((InAppPurchaseCoordinator, InAppPurchaseEvent) -> Void)?
var presentedViewController: UIViewController {
- return sheetController!
+ return controller!
}
init(storePaymentManager: StorePaymentManager, accountNumber: String, paymentAction: PaymentAction) {
@@ -38,12 +38,12 @@ final class InAppPurchaseCoordinator: Coordinator, Presentable, Presenting {
}
func start() {
- sheetController = InAppPurchaseViewController(
+ controller = InAppPurchaseViewController(
storePaymentManager: storePaymentManager,
accountNumber: accountNumber,
errorPresenter: PaymentAlertPresenter(alertContext: self),
paymentAction: paymentAction
)
- sheetController?.didFinish = dismiss
+ controller?.didFinish = dismiss
}
}
diff --git a/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift b/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift
index 6e36a2d369..ed86a10309 100644
--- a/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift
@@ -36,7 +36,6 @@ class OutOfTimeCoordinator: Coordinator, Presenting, @preconcurrency OutOfTimeVi
func start(animated: Bool) {
let interactor = OutOfTimeInteractor(
- storePaymentManager: storePaymentManager,
tunnelManager: tunnelManager
)
@@ -74,27 +73,23 @@ class OutOfTimeCoordinator: Coordinator, Presenting, @preconcurrency OutOfTimeVi
// MARK: - OutOfTimeViewControllerDelegate
- func didRequestShowPurchaseOptions(accountNumber: String) {
- let coordinator = InAppPurchaseCoordinator(
- storePaymentManager: storePaymentManager,
- accountNumber: accountNumber,
- paymentAction: .purchase
- )
- coordinator.didFinish = { coordinator, _ in
- coordinator.dismiss(animated: true)
- }
- coordinator.start()
- presentChild(coordinator, animated: true)
- }
-
- func didRequestShowRestorePurchase(accountNumber: String) {
+ func didRequestShowInAppPurchase(
+ accountNumber: String,
+ paymentAction: PaymentAction
+ ) {
let coordinator = InAppPurchaseCoordinator(
storePaymentManager: storePaymentManager,
accountNumber: accountNumber,
- paymentAction: .restorePurchase
+ paymentAction: paymentAction
)
- coordinator.didFinish = { coordinator, _ in
+ coordinator.didFinish = { [weak self] coordinator, event in
coordinator.dismiss(animated: true)
+ switch event {
+ case .paymentEvent(.finished), .purchaseRestored:
+ guard let self else { return }
+ self.didFinishPayment?(self)
+ default: break
+ }
}
coordinator.start()
presentChild(coordinator, animated: true)
diff --git a/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift b/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift
index 7660110b91..15c1b36642 100644
--- a/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift
@@ -40,19 +40,11 @@ final class WelcomeCoordinator: Coordinator, Poppable, Presenting {
func start(animated: Bool) {
let interactor = WelcomeInteractor(
- storePaymentManager: storePaymentManager,
tunnelManager: tunnelManager
)
interactor.didAddMoreCredit = { [weak self] in
- guard let self else { return }
- let coordinator = SetupAccountCompletedCoordinator(navigationController: navigationController)
- coordinator.didFinish = { [weak self] coordinator in
- coordinator.removeFromParent()
- self?.didFinish?()
- }
- addChild(coordinator)
- coordinator.start(animated: true)
+ self?.showSetupAccountCompleted()
}
let controller = WelcomeViewController(interactor: interactor)
@@ -63,6 +55,16 @@ final class WelcomeCoordinator: Coordinator, Poppable, Presenting {
navigationController.pushViewController(controller, animated: animated)
}
+ func showSetupAccountCompleted() {
+ let coordinator = SetupAccountCompletedCoordinator(navigationController: navigationController)
+ coordinator.didFinish = { [weak self] coordinator in
+ coordinator.removeFromParent()
+ self?.didFinish?()
+ }
+ addChild(coordinator)
+ coordinator.start(animated: true)
+ }
+
func popFromNavigationStack(animated: Bool, completion: (() -> Void)?) {
guard let viewController,
let index = navigationController.viewControllers.firstIndex(of: viewController)
@@ -156,55 +158,15 @@ extension WelcomeCoordinator: @preconcurrency WelcomeViewControllerDelegate {
accountNumber: accountNumber,
paymentAction: .purchase
)
- coordinator.didFinish = { coordinator, event in
+ coordinator.didFinish = { [weak self] coordinator, event in
coordinator.dismiss(animated: true)
switch event {
case .paymentEvent(.finished):
- let coordinator = SetupAccountCompletedCoordinator(navigationController: self.navigationController)
- coordinator.didFinish = { [weak self] coordinator in
- coordinator.removeFromParent()
- guard let self else { return }
- didFinish?()
- }
- self.addChild(coordinator)
- coordinator.start(animated: true)
+ self?.showSetupAccountCompleted()
default: break
}
}
coordinator.start()
presentChild(coordinator, animated: true)
}
-
- func didRequestToRedeemVoucher(controller: WelcomeViewController) {
- let coordinator = CreateAccountVoucherCoordinator(
- navigationController: navigationController,
- interactor: RedeemVoucherInteractor(
- tunnelManager: tunnelManager,
- accountsProxy: accountsProxy,
- verifyVoucherAsAccount: true
- )
- )
-
- coordinator.didCancel = { [weak self] coordinator in
- guard let self = self else { return }
- navigationController.popViewController(animated: true)
- coordinator.removeFromParent()
- }
-
- 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 }
- coordinator.removeFromParent()
- didLogout?(accountNumber)
- }
-
- addChild(coordinator)
-
- coordinator.start()
- }
}
diff --git a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeContentView.swift b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeContentView.swift
index ba05410b67..a892e15baf 100644
--- a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeContentView.swift
+++ b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeContentView.swift
@@ -10,7 +10,6 @@ import UIKit
protocol WelcomeContentViewDelegate: AnyObject, Sendable {
func didTapPurchaseButton(welcomeContentView: WelcomeContentView, button: AppButton)
- func didTapRedeemVoucherButton(welcomeContentView: WelcomeContentView, button: AppButton)
func didTapInfoButton(welcomeContentView: WelcomeContentView, button: UIButton)
}
@@ -119,18 +118,6 @@ final class WelcomeContentView: UIView, Sendable {
return button
}()
- private let redeemVoucherButton: AppButton = {
- let button = AppButton(style: .success)
- button.setAccessibilityIdentifier(.redeemVoucherButton)
- button.setTitle(NSLocalizedString(
- "REDEEM_VOUCHER_BUTTON_TITLE",
- tableName: "Account",
- value: "Redeem voucher",
- comment: ""
- ), for: .normal)
- return button
- }()
-
private let textsStackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
@@ -171,23 +158,6 @@ final class WelcomeContentView: UIView, Sendable {
}
}
- var isPurchasing = false {
- didSet {
- let alpha = isPurchasing ? 0.7 : 1.0
- purchaseButton.isEnabled = !isPurchasing
- purchaseButton.alpha = alpha
- redeemVoucherButton.isEnabled = !isPurchasing
- redeemVoucherButton.alpha = alpha
- }
- }
-
- var isFetchingProducts = false {
- didSet {
- purchaseButton.isLoading = isFetchingProducts
- purchaseButton.isEnabled = !isFetchingProducts
- }
- }
-
override init(frame: CGRect) {
super.init(frame: frame)
@@ -222,9 +192,6 @@ final class WelcomeContentView: UIView, Sendable {
textsStackView.addArrangedSubview(descriptionLabel)
buttonsStackView.addArrangedSubview(purchaseButton)
- #if DEBUG
- buttonsStackView.addArrangedSubview(redeemVoucherButton)
- #endif
addSubview(textsStackView)
addSubview(buttonsStackView)
@@ -242,7 +209,7 @@ final class WelcomeContentView: UIView, Sendable {
}
private func addActions() {
- [redeemVoucherButton, purchaseButton, infoButton].forEach {
+ [purchaseButton, infoButton].forEach {
$0.addTarget(self, action: #selector(tapped(button:)), for: .touchUpInside)
}
}
@@ -251,8 +218,6 @@ final class WelcomeContentView: UIView, Sendable {
switch button.accessibilityIdentifier {
case AccessibilityIdentifier.purchaseButton.asString:
delegate?.didTapPurchaseButton(welcomeContentView: self, button: button)
- case AccessibilityIdentifier.redeemVoucherButton.asString:
- delegate?.didTapRedeemVoucherButton(welcomeContentView: self, button: button)
case AccessibilityIdentifier.infoButton.asString:
delegate?.didTapInfoButton(welcomeContentView: self, button: button)
default: return
diff --git a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeInteractor.swift b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeInteractor.swift
index 3004b6212f..2dc587c192 100644
--- a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeInteractor.swift
+++ b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeInteractor.swift
@@ -12,7 +12,6 @@ import MullvadTypes
import StoreKit
final class WelcomeInteractor: @unchecked Sendable {
- private let storePaymentManager: StorePaymentManager
private let tunnelManager: TunnelManager
/// Interval used for periodic polling account updates.
@@ -51,10 +50,8 @@ final class WelcomeInteractor: @unchecked Sendable {
}
init(
- storePaymentManager: StorePaymentManager,
tunnelManager: TunnelManager
) {
- self.storePaymentManager = storePaymentManager
self.tunnelManager = tunnelManager
let tunnelObserver =
TunnelBlockObserver(didUpdateDeviceState: { [weak self] _, deviceState, previousDeviceState in
@@ -69,16 +66,6 @@ final class WelcomeInteractor: @unchecked Sendable {
self.tunnelObserver = tunnelObserver
}
- func requestProducts(
- with productIdentifiers: Set<StoreSubscription>,
- completionHandler: @Sendable @escaping (Result<SKProductsResponse, Error>) -> Void
- ) -> Cancellable {
- storePaymentManager.requestProducts(
- with: productIdentifiers,
- completionHandler: completionHandler
- )
- }
-
private func startAccountUpdateTimer() {
logger.debug(
"Start polling account updates every \(accountUpdateTimerInterval) second(s)."
diff --git a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift
index a94c2ab8c0..271c33048f 100644
--- a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift
+++ b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift
@@ -10,7 +10,6 @@ import StoreKit
import UIKit
protocol WelcomeViewControllerDelegate: AnyObject {
- func didRequestToRedeemVoucher(controller: WelcomeViewController)
func didRequestToShowInfo(controller: WelcomeViewController)
func didRequestToViewPurchaseOptions(
accountNumber: String
@@ -88,8 +87,4 @@ extension WelcomeViewController: @preconcurrency WelcomeContentViewDelegate {
func didTapPurchaseButton(welcomeContentView: WelcomeContentView, button: AppButton) {
delegate?.didRequestToViewPurchaseOptions(accountNumber: interactor.accountNumber)
}
-
- func didTapRedeemVoucherButton(welcomeContentView: WelcomeContentView, button: AppButton) {
- delegate?.didRequestToRedeemVoucher(controller: self)
- }
}
diff --git a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeInteractor.swift b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeInteractor.swift
index b909e44fe5..c89ab573f0 100644
--- a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeInteractor.swift
+++ b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeInteractor.swift
@@ -15,23 +15,19 @@ import Operations
@preconcurrency import StoreKit
final class OutOfTimeInteractor: Sendable {
- private let storePaymentManager: StorePaymentManager
private let tunnelManager: TunnelManager
nonisolated(unsafe) private var tunnelObserver: TunnelObserver?
- nonisolated(unsafe) private var paymentObserver: StorePaymentObserver?
nonisolated(unsafe) private let logger = Logger(label: "OutOfTimeInteractor")
private let accountUpdateTimerInterval: Duration = .minutes(1)
nonisolated(unsafe) private var accountUpdateTimer: DispatchSourceTimer?
- nonisolated(unsafe) var didReceivePaymentEvent: (@Sendable (StorePaymentEvent) -> Void)?
nonisolated(unsafe) var didReceiveTunnelStatus: (@Sendable (TunnelStatus) -> Void)?
nonisolated(unsafe) var didAddMoreCredit: (@Sendable () -> Void)?
- init(storePaymentManager: StorePaymentManager, tunnelManager: TunnelManager) {
- self.storePaymentManager = storePaymentManager
+ init(tunnelManager: TunnelManager) {
self.tunnelManager = tunnelManager
let tunnelObserver = TunnelBlockObserver(
@@ -47,15 +43,9 @@ final class OutOfTimeInteractor: Sendable {
}
)
- let paymentObserver = StorePaymentBlockObserver { [weak self] _, event in
- self?.didReceivePaymentEvent?(event)
- }
-
tunnelManager.addObserver(tunnelObserver)
- storePaymentManager.addPaymentObserver(paymentObserver)
self.tunnelObserver = tunnelObserver
- self.paymentObserver = paymentObserver
}
var tunnelStatus: TunnelStatus {
@@ -70,33 +60,6 @@ final class OutOfTimeInteractor: Sendable {
tunnelManager.stopTunnel()
}
- func addPayment(_ payment: SKPayment, for accountNumber: String) {
- storePaymentManager.addPayment(payment, for: accountNumber)
- }
-
- func restorePurchases(
- for accountNumber: String,
- completionHandler: @escaping @Sendable (Result<
- REST.CreateApplePaymentResponse,
- Error
- >) -> Void
- ) -> Cancellable {
- storePaymentManager.restorePurchases(
- for: accountNumber,
- completionHandler: completionHandler
- )
- }
-
- func requestProducts(
- with productIdentifiers: Set<StoreSubscription>,
- completionHandler: @escaping @Sendable (Result<SKProductsResponse, Error>) -> Void
- ) -> Cancellable {
- storePaymentManager.requestProducts(
- with: productIdentifiers,
- completionHandler: completionHandler
- )
- }
-
func startAccountUpdateTimer() {
logger.debug(
"Start polling account updates every \(accountUpdateTimerInterval) second(s)."
diff --git a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift
index 07dc4bda56..99218c3069 100644
--- a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift
+++ b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift
@@ -13,8 +13,10 @@ import Operations
import UIKit
protocol OutOfTimeViewControllerDelegate: AnyObject, Sendable {
- func didRequestShowPurchaseOptions(accountNumber: String)
- func didRequestShowRestorePurchase(accountNumber: String)
+ func didRequestShowInAppPurchase(
+ accountNumber: String,
+ paymentAction: PaymentAction
+ )
}
@MainActor
@@ -107,9 +109,6 @@ class OutOfTimeViewController: UIViewController, RootContainment {
private func applyViewState() {
let tunnelState = interactor.tunnelStatus.state
- let purchaseButton = contentView.purchaseButton
-
- let isOutOfTime = interactor.deviceState.accountData.map { $0.expiry < Date() } ?? false
contentView.enableDisconnectButton(tunnelState.isSecured, animated: true)
if tunnelState.isSecured {
@@ -145,14 +144,20 @@ class OutOfTimeViewController: UIViewController, RootContainment {
guard let accountNumber = interactor.deviceState.accountData?.number else {
return
}
- delegate?.didRequestShowPurchaseOptions(accountNumber: accountNumber)
+ delegate?.didRequestShowInAppPurchase(
+ accountNumber: accountNumber,
+ paymentAction: .purchase
+ )
}
@objc func restorePurchases() {
guard let accountNumber = interactor.deviceState.accountData?.number else {
return
}
- delegate?.didRequestShowRestorePurchase(accountNumber: accountNumber)
+ delegate?.didRequestShowInAppPurchase(
+ accountNumber: accountNumber,
+ paymentAction: .restorePurchase
+ )
}
@objc private func handleDisconnect(_ sender: Any) {