Merge branch 'improve-provider-flow'

This commit is contained in:
Davide De Rosa 2019-12-04 15:13:25 +01:00
commit b74c922671
6 changed files with 47 additions and 10 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- "Trusted networks" settings are now saved per profile. [#114](https://github.com/passepartoutvpn/passepartout-ios/issues/114) - "Trusted networks" settings are now saved per profile. [#114](https://github.com/passepartoutvpn/passepartout-ios/issues/114)
- Require explicit `--ca` and `--cipher` in .ovpn configuration file. - Require explicit `--ca` and `--cipher` in .ovpn configuration file.
- Restore provider flow after purchase.
### Fixed ### Fixed

View File

@ -63,10 +63,11 @@ extension UIColor {
} }
extension UIViewController { extension UIViewController {
func presentPurchaseScreen(forProduct product: Product) { func presentPurchaseScreen(forProduct product: Product, delegate: PurchaseViewControllerDelegate? = nil) {
let nav = StoryboardScene.Purchase.initialScene.instantiate() let nav = StoryboardScene.Purchase.initialScene.instantiate()
let vc = nav.topViewController as? PurchaseViewController let vc = nav.topViewController as? PurchaseViewController
vc?.feature = product vc?.feature = product
vc?.delegate = delegate
// enforce pre iOS 13 behavior // enforce pre iOS 13 behavior
nav.modalPresentationStyle = .fullScreen nav.modalPresentationStyle = .fullScreen

View File

@ -24,6 +24,7 @@
// //
import Foundation import Foundation
import StoreKit
import PassepartoutCore import PassepartoutCore
struct Product: RawRepresentable, Equatable, Hashable { struct Product: RawRepresentable, Equatable, Hashable {
@ -136,6 +137,12 @@ struct Product: RawRepresentable, Equatable, Hashable {
extension Infrastructure.Metadata { extension Infrastructure.Metadata {
var product: Product { var product: Product {
return Product(providerId: description) return Product(providerId: inApp ?? description)
}
}
extension Product {
func matchesStoreKitProduct(_ skProduct: SKProduct) -> Bool {
return skProduct.productIdentifier == rawValue
} }
} }

View File

@ -35,6 +35,8 @@ class WizardProviderViewController: UITableViewController, StrongTableHost {
private var createdProfile: ProviderConnectionProfile? private var createdProfile: ProviderConnectionProfile?
private var selectedMetadata: Infrastructure.Metadata?
// MARK: StrongTableHost // MARK: StrongTableHost
let model = StrongTableModel<SectionType, RowType>() let model = StrongTableModel<SectionType, RowType>()
@ -59,8 +61,10 @@ class WizardProviderViewController: UITableViewController, StrongTableHost {
} }
private func tryNext(withMetadata metadata: Infrastructure.Metadata) { private func tryNext(withMetadata metadata: Infrastructure.Metadata) {
selectedMetadata = metadata
guard ProductManager.shared.isEligible(forProvider: metadata.name) else { guard ProductManager.shared.isEligible(forProvider: metadata.name) else {
presentPurchaseScreen(forProduct: metadata.product) presentPurchaseScreen(forProduct: metadata.product, delegate: self)
return return
} }
@ -70,7 +74,7 @@ class WizardProviderViewController: UITableViewController, StrongTableHost {
_ = InfrastructureFactory.shared.update(metadata.name, notBeforeInterval: nil) { [weak self] in _ = InfrastructureFactory.shared.update(metadata.name, notBeforeInterval: nil) { [weak self] in
hud.hide() hud.hide()
guard let _ = $0 else { guard let _ = $0 else {
self?.alertMissingInfrastructure(forName: metadata.name, error: $1) self?.alertMissingInfrastructure(forMetadata: metadata, error: $1)
return return
} }
self?.next(withMetadata: metadata) self?.next(withMetadata: metadata)
@ -95,16 +99,16 @@ class WizardProviderViewController: UITableViewController, StrongTableHost {
navigationController?.pushViewController(accountVC, animated: true) navigationController?.pushViewController(accountVC, animated: true)
} }
private func alertMissingInfrastructure(forName name: Infrastructure.Name, error: Error?) { private func alertMissingInfrastructure(forMetadata metadata: Infrastructure.Metadata, error: Error?) {
var message = L10n.Core.Wizards.Provider.Alerts.Unavailable.message var message = L10n.Core.Wizards.Provider.Alerts.Unavailable.message
if let error = error { if let error = error {
log.error("Unable to download missing \(name) infrastructure (network error): \(error.localizedDescription)") log.error("Unable to download missing \(metadata.description) infrastructure (network error): \(error.localizedDescription)")
message.append(" \(error.localizedDescription)") message.append(" \(error.localizedDescription)")
} else { } else {
log.error("Unable to download missing \(name) infrastructure (API error)") log.error("Unable to download missing \(metadata.description) infrastructure (API error)")
} }
let alert = UIAlertController.asAlert(name, message) let alert = UIAlertController.asAlert(metadata.description, message)
alert.addCancelAction(L10n.Core.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
@ -214,3 +218,14 @@ extension WizardProviderViewController: AccountViewControllerDelegate {
finish(withCredentials: vc.credentials) finish(withCredentials: vc.credentials)
} }
} }
// MARK: -
extension WizardProviderViewController: PurchaseViewControllerDelegate {
func purchaseController(_ purchaseController: PurchaseViewController, didPurchase product: Product) {
guard let metadata = selectedMetadata else {
return
}
tryNext(withMetadata: metadata)
}
}

View File

@ -30,11 +30,17 @@ import Convenience
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self
protocol PurchaseViewControllerDelegate: class {
func purchaseController(_ purchaseController: PurchaseViewController, didPurchase product: Product)
}
class PurchaseViewController: UITableViewController, StrongTableHost { class PurchaseViewController: UITableViewController, StrongTableHost {
private var isLoading = true private var isLoading = true
var feature: Product! var feature: Product!
weak var delegate: PurchaseViewControllerDelegate?
private var skFeature: SKProduct? private var skFeature: SKProduct?
private var skFullVersion: SKProduct? private var skFullVersion: SKProduct?
@ -135,7 +141,14 @@ class PurchaseViewController: UITableViewController, StrongTableHost {
} }
return return
} }
self?.dismiss(animated: true, completion: nil)
self?.dismiss(animated: true) {
guard let weakSelf = self else {
return
}
let product = weakSelf.feature.matchesStoreKitProduct(skProduct) ? weakSelf.feature! : .fullVersion
weakSelf.delegate?.purchaseController(weakSelf, didPurchase: product)
}
} }
} }

@ -1 +1 @@
Subproject commit 20f855f077d974b2a64e3bc952bfd582226ccff4 Subproject commit 26c1f8d41296d2cd5c1ac2654733e3e31911992c