diff options
| author | Steffen Ernst <steffen@Steffens-MacBook-Pro.local> | 2025-01-13 19:51:06 +0100 |
|---|---|---|
| committer | Steffen Ernst <steffen.ernst@mullvad.net> | 2025-01-20 15:54:12 +0100 |
| commit | 726595bf271dc8e130272a035d4cb7be1307d9cf (patch) | |
| tree | a9469e45061021ec4c252c395c7fa5645c839e83 | |
| parent | 7261493c00339a9945d4ac32161e8a245b975b6e (diff) | |
| download | mullvadvpn-726595bf271dc8e130272a035d4cb7be1307d9cf.tar.xz mullvadvpn-726595bf271dc8e130272a035d4cb7be1307d9cf.zip | |
Format 90 day payment code
7 files changed, 79 insertions, 34 deletions
diff --git a/ios/MullvadVPN/Coordinators/AccountCoordinator.swift b/ios/MullvadVPN/Coordinators/AccountCoordinator.swift index 28e39c831d..78cc78ba75 100644 --- a/ios/MullvadVPN/Coordinators/AccountCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/AccountCoordinator.swift @@ -7,8 +7,8 @@ // import Routing -import UIKit import StoreKit +import UIKit enum AccountDismissReason: Equatable, Sendable { case none @@ -68,14 +68,22 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting, @unchecked navigateToDeleteAccount() case .restorePurchasesInfo: showRestorePurchasesInfo() - case .showPurchaseOptions(let details): - showPurchaseOptions(availableProducts: details.products, accountNumber: details.accountNumber, didRequestPurchase: details.didRequestPurchase) + case let .showPurchaseOptions(details): + showPurchaseOptions( + availableProducts: details.products, + accountNumber: details.accountNumber, + didRequestPurchase: details.didRequestPurchase + ) case .showFailedToLoadProducts: showFailToFetchProducts() } } - - func showPurchaseOptions(availableProducts: [SKProduct], accountNumber: String, didRequestPurchase: @escaping (_ product: SKProduct) -> Void) { + + func showPurchaseOptions( + availableProducts: [SKProduct], + accountNumber: String, + didRequestPurchase: @escaping (_ product: SKProduct) -> Void + ) { let localizedString = NSLocalizedString( "BUY_CREDIT_BUTTON", tableName: "Welcome", @@ -92,7 +100,9 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting, @unchecked didRequestPurchase(product) }) }) - action.accessibilityIdentifier = "\(AccessibilityIdentifier.purchaseButton.asString)_\(product.productIdentifier)" + action + .accessibilityIdentifier = + "\(AccessibilityIdentifier.purchaseButton.asString)_\(product.productIdentifier)" alert.addAction(action) } let cancelAction = UIAlertAction(title: NSLocalizedString( @@ -266,8 +276,7 @@ final class AccountCoordinator: Coordinator, Presentable, Presenting, @unchecked let presenter = AlertPresenter(context: self) presenter.showAlert(presentation: presentation, animated: true) } - - + func showFailToFetchProducts() { let message = NSLocalizedString( "WELCOME_FAILED_TO_FETCH_PRODUCTS_DIALOG", diff --git a/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift b/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift index 354b4148d3..d1e59b69ff 100644 --- a/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/OutOfTimeCoordinator.swift @@ -7,8 +7,8 @@ // import Routing -import UIKit import StoreKit +import UIKit class OutOfTimeCoordinator: Coordinator, Presenting, @preconcurrency OutOfTimeViewControllerDelegate, Poppable { let navigationController: RootContainerViewController @@ -83,8 +83,12 @@ class OutOfTimeCoordinator: Coordinator, Presenting, @preconcurrency OutOfTimeVi didFinishPayment?(self) } - - func outOfTimeViewControllerDidRequestShowPurchaseOptions(_ controller: OutOfTimeViewController, products: [SKProduct], didRequestPurchase: @escaping (SKProduct) -> Void) { + + func outOfTimeViewControllerDidRequestShowPurchaseOptions( + _ controller: OutOfTimeViewController, + products: [SKProduct], + didRequestPurchase: @escaping (SKProduct) -> Void + ) { let localizedString = NSLocalizedString( "BUY_CREDIT_BUTTON", tableName: "Welcome", @@ -101,7 +105,9 @@ class OutOfTimeCoordinator: Coordinator, Presenting, @preconcurrency OutOfTimeVi didRequestPurchase(product) }) }) - action.accessibilityIdentifier = "\(AccessibilityIdentifier.purchaseButton.asString)_\(product.productIdentifier)" + action + .accessibilityIdentifier = + "\(AccessibilityIdentifier.purchaseButton.asString)_\(product.productIdentifier)" alert.addAction(action) } let cancelAction = UIAlertAction(title: NSLocalizedString( @@ -114,7 +120,7 @@ class OutOfTimeCoordinator: Coordinator, Presenting, @preconcurrency OutOfTimeVi alert.addAction(cancelAction) presentationContext.present(alert, animated: true) } - + func outOfTimeViewControllerDidFailToFetchProducts(_ controller: OutOfTimeViewController) { let message = NSLocalizedString( "WELCOME_FAILED_TO_FETCH_PRODUCTS_DIALOG", diff --git a/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift b/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift index 90255d306e..a9dab2ab0a 100644 --- a/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/WelcomeCoordinator.swift @@ -111,7 +111,7 @@ extension WelcomeCoordinator: @preconcurrency WelcomeViewControllerDelegate { let presenter = AlertPresenter(context: self) presenter.showAlert(presentation: presentation, animated: true) } - + func didRequestToShowInfo(controller: WelcomeViewController) { let message = NSLocalizedString( "WELCOME_DEVICE_CONCEPT_TEXT_DIALOG", @@ -148,8 +148,12 @@ extension WelcomeCoordinator: @preconcurrency WelcomeViewControllerDelegate { let presenter = AlertPresenter(context: self) presenter.showAlert(presentation: presentation, animated: true) } - - func didRequestToViewPurchaseOptions(controller: WelcomeViewController, availableProducts: [SKProduct], accountNumber: String) { + + func didRequestToViewPurchaseOptions( + controller: WelcomeViewController, + availableProducts: [SKProduct], + accountNumber: String + ) { let localizedString = NSLocalizedString( "BUY_CREDIT_BUTTON", tableName: "Welcome", @@ -163,10 +167,16 @@ extension WelcomeCoordinator: @preconcurrency WelcomeViewControllerDelegate { } let action = UIAlertAction(title: localizedTitle, style: .default, handler: { _ in alert.dismiss(animated: true, completion: { - self.didRequestToPurchaseCredit(controller: controller, accountNumber: accountNumber, product: product) + self.didRequestToPurchaseCredit( + controller: controller, + accountNumber: accountNumber, + product: product + ) }) }) - action.accessibilityIdentifier = "\(AccessibilityIdentifier.purchaseButton.asString)_\(product.productIdentifier)" + action + .accessibilityIdentifier = + "\(AccessibilityIdentifier.purchaseButton.asString)_\(product.productIdentifier)" alert.addAction(action) } let cancelAction = UIAlertAction(title: NSLocalizedString( diff --git a/ios/MullvadVPN/StorePaymentManager/StoreSubscription.swift b/ios/MullvadVPN/StorePaymentManager/StoreSubscription.swift index 884da8ea87..0401ea8d9c 100644 --- a/ios/MullvadVPN/StorePaymentManager/StoreSubscription.swift +++ b/ios/MullvadVPN/StorePaymentManager/StoreSubscription.swift @@ -37,7 +37,7 @@ enum StoreSubscription: String, CaseIterable { extension SKProduct { var customLocalizedTitle: String? { guard let localizedTitle = StoreSubscription(rawValue: productIdentifier)?.localizedTitle, - let localizedPrice else { + let localizedPrice else { return nil } return "\(localizedTitle) (\(localizedPrice))" diff --git a/ios/MullvadVPN/View controllers/Account/AccountViewController.swift b/ios/MullvadVPN/View controllers/Account/AccountViewController.swift index 4fe06f955e..2ab766e41a 100644 --- a/ios/MullvadVPN/View controllers/Account/AccountViewController.swift +++ b/ios/MullvadVPN/View controllers/Account/AccountViewController.swift @@ -43,7 +43,7 @@ class AccountViewController: UIViewController, @unchecked Sendable { return contentView }() - private var isFetchingProducts: Bool = false + private var isFetchingProducts = false private var paymentState: PaymentState = .none var actionHandler: ActionHandler? @@ -150,7 +150,7 @@ class AccountViewController: UIViewController, @unchecked Sendable { contentView.storeKit2Button.addTarget(self, action: #selector(handleStoreKit2Purchase), for: .touchUpInside) } - + private func doPurchase(product: SKProduct) { guard let accountData = interactor.deviceState.accountData else { return @@ -261,7 +261,7 @@ class AccountViewController: UIViewController, @unchecked Sendable { @objc private func deleteAccount() { actionHandler?(.navigateToDeleteAccount) } - + @objc private func requestStoreProducts() { guard let accountData = interactor.deviceState.accountData else { return @@ -271,10 +271,14 @@ class AccountViewController: UIViewController, @unchecked Sendable { _ = interactor.requestProducts(with: productIdentifiers) { [weak self] result in guard let self else { return } switch result { - case .success(let success): + case let .success(success): let products = success.products if !products.isEmpty { - actionHandler?(.showPurchaseOptions(PurchaseOptionDetails(products: products, accountNumber: accountData.number, didRequestPurchase: self.doPurchase))) + actionHandler?(.showPurchaseOptions(PurchaseOptionDetails( + products: products, + accountNumber: accountData.number, + didRequestPurchase: self.doPurchase + ))) } else { actionHandler?(.showFailedToLoadProducts) } @@ -317,7 +321,7 @@ class AccountViewController: UIViewController, @unchecked Sendable { guard let accountData = interactor.deviceState.accountData else { return } - + let productIdentifiers = Set(StoreSubscription.allCases).map { $0.rawValue } setPaymentState(.makingStoreKit2Purchase, animated: true) diff --git a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift index 194f2d5732..33a3046b30 100644 --- a/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift +++ b/ios/MullvadVPN/View controllers/CreationAccount/Welcome/WelcomeViewController.swift @@ -12,7 +12,11 @@ import UIKit protocol WelcomeViewControllerDelegate: AnyObject { func didRequestToRedeemVoucher(controller: WelcomeViewController) func didRequestToShowInfo(controller: WelcomeViewController) - func didRequestToViewPurchaseOptions(controller: WelcomeViewController, availableProducts: [SKProduct], accountNumber: String) + func didRequestToViewPurchaseOptions( + controller: WelcomeViewController, + availableProducts: [SKProduct], + accountNumber: String + ) func didRequestToShowFailToFetchProducts(controller: WelcomeViewController) } @@ -91,10 +95,14 @@ extension WelcomeViewController: @preconcurrency WelcomeContentViewDelegate { _ = interactor.requestProducts(with: productIdentifiers) { [weak self] result in guard let self else { return } switch result { - case .success(let success): + case let .success(success): let products = success.products if !products.isEmpty { - delegate?.didRequestToViewPurchaseOptions(controller: self, availableProducts: products, accountNumber: interactor.accountNumber) + delegate?.didRequestToViewPurchaseOptions( + controller: self, + availableProducts: products, + accountNumber: interactor.accountNumber + ) } else { delegate?.didRequestToShowFailToFetchProducts(controller: self) } diff --git a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift index 56d5af7490..32fc44f417 100644 --- a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift +++ b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift @@ -15,7 +15,11 @@ import UIKit protocol OutOfTimeViewControllerDelegate: AnyObject, Sendable { func outOfTimeViewControllerDidBeginPayment(_ controller: OutOfTimeViewController) func outOfTimeViewControllerDidEndPayment(_ controller: OutOfTimeViewController) - func outOfTimeViewControllerDidRequestShowPurchaseOptions(_ controller: OutOfTimeViewController, products: [SKProduct], didRequestPurchase: @escaping (SKProduct) -> Void) + func outOfTimeViewControllerDidRequestShowPurchaseOptions( + _ controller: OutOfTimeViewController, + products: [SKProduct], + didRequestPurchase: @escaping (SKProduct) -> Void + ) func outOfTimeViewControllerDidFailToFetchProducts(_ controller: OutOfTimeViewController) } @@ -34,9 +38,9 @@ class OutOfTimeViewController: UIViewController, RootContainment { } private lazy var contentView = OutOfTimeContentView() - + private var isFetchingProducts = false - + override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent } @@ -205,7 +209,7 @@ class OutOfTimeViewController: UIViewController, RootContainment { paymentState = .none } - + private func doPurchase(product: SKProduct) { guard let accountData = interactor.deviceState.accountData else { return @@ -229,10 +233,14 @@ class OutOfTimeViewController: UIViewController, RootContainment { _ = interactor.requestProducts(with: productIdentifiers) { [weak self] result in guard let self else { return } switch result { - case .success(let success): + case let .success(success): let products = success.products if !products.isEmpty { - delegate?.outOfTimeViewControllerDidRequestShowPurchaseOptions(self, products: products, didRequestPurchase: self.doPurchase) + delegate?.outOfTimeViewControllerDidRequestShowPurchaseOptions( + self, + products: products, + didRequestPurchase: self.doPurchase + ) } else { delegate?.outOfTimeViewControllerDidFailToFetchProducts(self) } |
