Merge branch 'improve-provider-flow'
This commit is contained in:
commit
b74c922671
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,10 +30,16 @@ 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?
|
||||||
|
|
||||||
|
@ -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
|
Loading…
Reference in New Issue