Skip to content

Commit

Permalink
Fix brave/brave-ios#8353: Add Subscription Custom Offer Codes Interac…
Browse files Browse the repository at this point in the history
  • Loading branch information
soner-yuksel authored Nov 16, 2023
1 parent bfd9bec commit 98d369d
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 10 deletions.
15 changes: 13 additions & 2 deletions Sources/Brave/Frontend/Settings/SettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ class SettingsViewController: TableViewController {
case .notPurchased, .expired:
return BraveVPN.vpnState.enableVPNDestinationVC
case .purchased:
let vc = BraveVPNSettingsViewController()
let vc = BraveVPNSettingsViewController(iapObserver: BraveVPN.iapObserver)
vc.openURL = { [unowned self] url in
self.settingsDelegate?.settingsOpenURLInNewTab(url)
self.dismiss(animated: true)
Expand All @@ -623,7 +623,18 @@ class SettingsViewController: TableViewController {
}()

guard let vcToShow = vc else { return }
self.navigationController?.pushViewController(vcToShow, animated: true)

if VPNProductInfo.isComplete {
self.navigationController?.pushViewController(vcToShow, animated: true)
} else {
let alert = UIAlertController(
title: Strings.VPN.errorCantGetPricesTitle,
message: Strings.VPN.errorCantGetPricesBody,
preferredStyle: .alert)

alert.addAction(UIAlertAction(title: Strings.OKString, style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
},
image: Preferences.VPN.vpnReceiptStatus.value == BraveVPN.ReceiptResponse.Status.retryPeriod.rawValue
? UIImage(braveSystemNamed: "leo.warning.triangle-filled")?
Expand Down
15 changes: 15 additions & 0 deletions Sources/BraveStrings/BraveStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2820,6 +2820,11 @@ extension Strings {
value: "Manage Subscription",
comment: "Button to manage your VPN subscription")

public static let settingsRedeemOfferCode =
NSLocalizedString("vpn.settingsManageSubscription", tableName: "BraveShared", bundle: .module,
value: "Redeem Offer Code",
comment: "Button to redeem offer code subscription")

public static let settingsLinkReceipt =
NSLocalizedString("vpn.settingsLinkReceipt", tableName: "BraveShared", bundle: .module,
value: "Link purchase to your Brave account",
Expand Down Expand Up @@ -2904,6 +2909,11 @@ extension Strings {
NSLocalizedString("vpn.vpnConfigPermissionDeniedErrorTitle", tableName: "BraveShared", bundle: .module,
value: "Permission denied",
comment: "Title for an alert when the user didn't allow to install VPN profile")

public static let vpnRedeemCodeButtonActionTitle =
NSLocalizedString("vpn.vpnRedeemCodeButtonActionTitle", tableName: "BraveShared", bundle: .module,
value: "Redeem Code",
comment: "Title for a button for enabling the Redeem Code flow")

public static let vpnConfigPermissionDeniedErrorBody =
NSLocalizedString("vpn.vpnConfigPermissionDeniedErrorBody", tableName: "BraveShared", bundle: .module,
Expand All @@ -2929,6 +2939,11 @@ extension Strings {
NSLocalizedString("vpn.vpnErrorPurchaseFailedBody", tableName: "BraveShared", bundle: .module,
value: "Unable to complete purchase. Please try again, or check your payment details on Apple and try again.",
comment: "Message for error when VPN could not be purchased.")

public static let vpnErrorOfferCodeFailedBody =
NSLocalizedString("vpn.vpnErrorOfferCodeFailedBody", tableName: "BraveShared", bundle: .module,
value: "Unable to redeem offer code. Please try again, or check your offer code details and try again.",
comment: "Message for error when VPN offer code could not be redeemed.")

public static let vpnResetAlertTitle =
NSLocalizedString("vpn.vpnResetAlertTitle", tableName: "BraveShared", bundle: .module,
Expand Down
51 changes: 50 additions & 1 deletion Sources/BraveVPN/BraveVPNSettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import GuardianConnect
public class BraveVPNSettingsViewController: TableViewController {

public var openURL: ((URL) -> Void)?
let iapObserver: IAPObserver

public init(iapObserver: IAPObserver) {
self.iapObserver = iapObserver

public init() {
super.init(style: .grouped)
}

Expand Down Expand Up @@ -146,6 +149,13 @@ public class BraveVPNSettingsViewController: TableViewController {
UIApplication.shared.open(url, options: [:])
}
},
cellClass: ButtonCell.self),
Row(text: Strings.VPN.settingsRedeemOfferCode,
selection: {
self.isLoading = false
// Open the redeem code sheet
SKPaymentQueue.default().presentCodeRedemptionSheet()
},
cellClass: ButtonCell.self)
] + linkReceiptRows,
footer: .title(Strings.VPN.settingsLinkReceiptFooter))
Expand Down Expand Up @@ -339,3 +349,42 @@ public class BraveVPNSettingsViewController: TableViewController {
isLoading = false
}
}

// MARK: - IAPObserverDelegate

extension BraveVPNSettingsViewController: IAPObserverDelegate {
public func purchasedOrRestoredProduct(validateReceipt: Bool) {
DispatchQueue.main.async {
self.isLoading = false
}

if validateReceipt {
BraveVPN.validateReceiptData()
}
}

public func purchaseFailed(error: IAPObserver.PurchaseError) {
// Handle Offer Code error
guard isLoading else {
return
}

handleOfferCodeError(error: error)
}

private func handleOfferCodeError(error: IAPObserver.PurchaseError) {
DispatchQueue.main.async {
self.isLoading = false

let message = Strings.VPN.vpnErrorOfferCodeFailedBody

let alert = UIAlertController(
title: Strings.VPN.vpnErrorPurchaseFailedTitle,
message: message,
preferredStyle: .alert)
let ok = UIAlertAction(title: Strings.OKString, style: .default, handler: nil)
alert.addAction(ok)
self.present(alert, animated: true)
}
}
}
34 changes: 27 additions & 7 deletions Sources/BraveVPN/BuyVPNViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ class BuyVPNViewController: VPNSetupLoadingController {
title: Strings.VPN.restorePurchases, style: .done,
target: self, action: #selector(restorePurchasesAction))

let actionTitle = Preferences.VPN.freeTrialUsed.value
let buyTitle = Preferences.VPN.freeTrialUsed.value
? Strings.VPN.activateSubscriptionAction.capitalized
: Strings.VPN.freeTrialPeriodAction.capitalized

let actionButton = BraveGradientButton(gradient: .backgroundGradient1).then {
let buyButton = BraveGradientButton(gradient: .backgroundGradient1).then {
$0.titleLabel?.font = .systemFont(ofSize: 15, weight: .bold)
$0.titleLabel?.textAlignment = .center

$0.setTitle(actionTitle, for: .normal)
$0.setTitle(buyTitle, for: .normal)

$0.snp.makeConstraints {
$0.height.equalTo(50)
Expand All @@ -66,7 +66,15 @@ class BuyVPNViewController: VPNSetupLoadingController {

$0.addTarget(self, action: #selector(startSubscriptionAction), for: .touchUpInside)
}


let redeemButton = UIButton().then {
$0.setTitle(Strings.VPN.vpnRedeemCodeButtonActionTitle, for: .normal)
$0.titleLabel?.font = .systemFont(ofSize: 13, weight: .medium)
$0.titleLabel?.textAlignment = .center

$0.addTarget(self, action: #selector(redeemOfferSubscriptionCode), for: .touchUpInside)
}

let seperator = UIView().then {
$0.backgroundColor = UIColor.white.withAlphaComponent(0.1)
$0.snp.makeConstraints { make in
Expand All @@ -76,7 +84,8 @@ class BuyVPNViewController: VPNSetupLoadingController {

view.addSubview(buyVPNView)
view.addSubview(seperator)
view.addSubview(actionButton)
view.addSubview(buyButton)
view.addSubview(redeemButton)

buyVPNView.snp.makeConstraints {
$0.leading.trailing.top.equalToSuperview()
Expand All @@ -87,9 +96,15 @@ class BuyVPNViewController: VPNSetupLoadingController {
$0.leading.trailing.equalToSuperview()
}

actionButton.snp.makeConstraints() {
buyButton.snp.makeConstraints() {
$0.top.equalTo(seperator.snp.bottom).inset(-12)
$0.leading.trailing.bottom.equalToSuperview().inset(24)
$0.leading.trailing.equalToSuperview().inset(24)
}

redeemButton.snp.makeConstraints() {
$0.top.equalTo(buyButton.snp.bottom).inset(-12)
$0.bottom.equalToSuperview().inset(24)
$0.centerX.equalToSuperview()
}

buyVPNView.monthlySubButton
Expand Down Expand Up @@ -154,6 +169,11 @@ class BuyVPNViewController: VPNSetupLoadingController {
addPaymentForSubcription(type: activeSubcriptionChoice)
}

@objc func redeemOfferSubscriptionCode() {
// Open the redeem code sheet
SKPaymentQueue.default().presentCodeRedemptionSheet()
}

private func addPaymentForSubcription(type: SubscriptionType) {
var subscriptionProduct: SKProduct?

Expand Down

0 comments on commit 98d369d

Please sign in to comment.