Update to API v3

- Dynamic providers
- Add index.json to API
This commit is contained in:
Davide De Rosa 2019-11-23 14:22:34 +01:00
parent 8cef934a42
commit 97f458385c
12 changed files with 60 additions and 47 deletions

View File

@ -40,11 +40,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
override init() { override init() {
AppConstants.Log.configure() AppConstants.Log.configure()
InfrastructureFactory.shared.preload()
super.init() super.init()
} }
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
InfrastructureFactory.shared.loadCache()
Theme.current.applyAppearance() Theme.current.applyAppearance()
Reviewer.shared.eventCountBeforeRating = AppConstants.Rating.eventCount Reviewer.shared.eventCountBeforeRating = AppConstants.Rating.eventCount

View File

@ -77,8 +77,8 @@ class IssueReporter: NSObject {
var bodyMetadata = "--\n\n" var bodyMetadata = "--\n\n"
bodyMetadata += DebugLog(raw: "").decoratedString() bodyMetadata += DebugLog(raw: "").decoratedString()
if let infrastructure = issue.infrastructure { if let infrastructure = issue.infrastructure {
bodyMetadata += "Provider: \(infrastructure.name.rawValue)\n" bodyMetadata += "Provider: \(infrastructure.name)\n"
if let lastUpdated = InfrastructureFactory.shared.modificationDate(for: infrastructure.name) { if let lastUpdated = InfrastructureFactory.shared.modificationDate(forName: infrastructure.name) {
bodyMetadata += "Last updated: \(lastUpdated)\n" bodyMetadata += "Last updated: \(lastUpdated)\n"
} }
bodyMetadata += "\n" bodyMetadata += "\n"

View File

@ -111,10 +111,10 @@ enum Product: String {
} }
} }
extension Infrastructure.Name { extension Infrastructure.Metadata {
var product: Product { var product: Product {
guard let product = Product(rawValue: "com.algoritmico.ios.Passepartout.providers.\(rawValue)") else { guard let product = Product(rawValue: "com.algoritmico.ios.Passepartout.providers.\(self)") else {
fatalError("Product not found for provider \(rawValue)") fatalError("Product not found for provider \(self)")
} }
return product return product
} }

View File

@ -178,7 +178,7 @@ class ProductManager: NSObject {
return true return true
} }
return purchasedFeatures.contains { return purchasedFeatures.contains {
return $0.rawValue.hasSuffix("providers.\(name.rawValue)") return $0.rawValue.hasSuffix("providers.\(name)")
} }
} }

View File

@ -189,9 +189,10 @@ extension MFMailComposeViewController {
} }
} }
extension Infrastructure.Name { // FIXME: load from index JSON
extension Infrastructure.Metadata {
var logo: UIImage? { var logo: UIImage? {
return ImageAsset(name: rawValue.lowercased()).image return ImageAsset(name: name.lowercased()).image
} }
} }

View File

@ -61,28 +61,32 @@ class AccountViewController: UIViewController, StrongTableHost {
guard let name = infrastructureName else { guard let name = infrastructureName else {
return nil return nil
} }
// FIXME: make this dynamic?
let V = L10n.Core.Account.Sections.Guidance.Footer.Infrastructure.self let V = L10n.Core.Account.Sections.Guidance.Footer.Infrastructure.self
switch name { switch name {
case .mullvad: case .mullvad:
return V.mullvad(name.rawValue) return V.mullvad(name)
case .nordVPN: case .nordvpn:
return V.nordvpn(name.rawValue) return V.nordvpn(name)
case .pia: case .pia:
return V.pia(name.rawValue) return V.pia(name)
case .protonVPN: case .protonvpn:
return V.protonvpn(name.rawValue) return V.protonvpn(name)
case .tunnelBear: case .tunnelbear:
return V.tunnelbear(name.rawValue) return V.tunnelbear(name)
case .vyprVPN: case .vyprvpn:
return V.vyprvpn(name.rawValue) return V.vyprvpn(name)
case .windscribe: case .windscribe:
return V.windscribe(name.rawValue) return V.windscribe(name)
default:
return nil
} }
} }
@ -266,7 +270,7 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate, Fie
fatalError("Sign-up shown when not a provider profile") fatalError("Sign-up shown when not a provider profile")
} }
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Core.Account.Cells.Signup.caption(name.rawValue) cell.leftText = L10n.Core.Account.Cells.Signup.caption(name)
cell.applyAction(.current) cell.applyAction(.current)
return cell return cell
} }

View File

@ -39,7 +39,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
private var hosts: [String] = [] private var hosts: [String] = []
private var availableProviderNames: [Infrastructure.Name]? private var availableProviders: [Infrastructure.Metadata]?
private var didShowSubreddit = false private var didShowSubreddit = false
@ -177,7 +177,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
vc.setProfile(selectedProfile) vc.setProfile(selectedProfile)
} else if let providerVC = destination as? WizardProviderViewController { } else if let providerVC = destination as? WizardProviderViewController {
providerVC.availableNames = availableProviderNames ?? [] providerVC.available = availableProviders ?? []
} }
} }
@ -195,8 +195,8 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
} }
private func addNewProvider() { private func addNewProvider() {
let names = service.availableProviderNames() let providers = service.availableProviders()
guard !names.isEmpty else { guard !providers.isEmpty else {
let alert = UIAlertController.asAlert( let alert = UIAlertController.asAlert(
L10n.Core.Organizer.Sections.Providers.header, L10n.Core.Organizer.Sections.Providers.header,
L10n.Core.Organizer.Alerts.ExhaustedProviders.message L10n.Core.Organizer.Alerts.ExhaustedProviders.message
@ -205,7 +205,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
availableProviderNames = names availableProviders = providers
perform(segue: StoryboardSegue.Organizer.addProviderSegueIdentifier) perform(segue: StoryboardSegue.Organizer.addProviderSegueIdentifier)
} }
@ -479,12 +479,13 @@ extension OrganizerViewController {
case .profile: case .profile:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
let rowProfile = profileKey(at: indexPath) let rowProfile = profileKey(at: indexPath)
if rowProfile.context == .provider, let providerName = Infrastructure.Name(rawValue: rowProfile.id) { if rowProfile.context == .provider, let metadata = InfrastructureFactory.shared.metadata(forName: rowProfile.id) {
cell.imageView?.image = providerName.logo cell.imageView?.image = metadata.logo
cell.leftText = metadata.description
} else { } else {
cell.imageView?.image = nil cell.imageView?.image = nil
}
cell.leftText = rowProfile.id cell.leftText = rowProfile.id
}
cell.rightText = service.isActiveProfile(rowProfile) ? L10n.Core.Organizer.Cells.Profile.Value.current : nil cell.rightText = service.isActiveProfile(rowProfile) ? L10n.Core.Organizer.Cells.Profile.Value.current : nil
return cell return cell

View File

@ -27,7 +27,7 @@ import UIKit
import PassepartoutCore import PassepartoutCore
class WizardProviderViewController: UITableViewController { class WizardProviderViewController: UITableViewController {
var availableNames: [Infrastructure.Name] = [] var available: [Infrastructure.Metadata] = []
private var createdProfile: ProviderConnectionProfile? private var createdProfile: ProviderConnectionProfile?
@ -37,17 +37,17 @@ class WizardProviderViewController: UITableViewController {
title = L10n.Core.Organizer.Sections.Providers.header title = L10n.Core.Organizer.Sections.Providers.header
} }
private func next(withName name: Infrastructure.Name) { private func next(withMetadata metadata: Infrastructure.Metadata) {
guard ProductManager.shared.isEligible(forProvider: name) else { guard ProductManager.shared.isEligible(forProvider: metadata.name) else {
presentPurchaseScreen(forProduct: name.product) presentPurchaseScreen(forProduct: metadata.product)
return return
} }
let profile = ProviderConnectionProfile(name: name) let profile = ProviderConnectionProfile(name: metadata.name)
createdProfile = profile createdProfile = profile
let accountVC = StoryboardScene.Main.accountIdentifier.instantiate() let accountVC = StoryboardScene.Main.accountIdentifier.instantiate()
let infrastructure = InfrastructureFactory.shared.get(name) let infrastructure = InfrastructureFactory.shared.infrastructure(forName: metadata.name)
accountVC.usernamePlaceholder = infrastructure.defaults.username accountVC.usernamePlaceholder = infrastructure.defaults.username
accountVC.infrastructureName = infrastructure.name accountVC.infrastructureName = infrastructure.name
accountVC.delegate = self accountVC.delegate = self
@ -73,20 +73,20 @@ class WizardProviderViewController: UITableViewController {
extension WizardProviderViewController { extension WizardProviderViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return availableNames.count return available.count
} }
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let name = availableNames[indexPath.row] let metadata = available[indexPath.row]
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.imageView?.image = name.logo cell.imageView?.image = metadata.logo
cell.leftText = name.rawValue cell.leftText = metadata.description
return cell return cell
} }
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = availableNames[indexPath.row] let metadata = available[indexPath.row]
next(withName: name) next(withMetadata: metadata)
} }
} }

View File

@ -79,7 +79,7 @@ class ServiceViewController: UIViewController, StrongTableHost {
self.profile = profile self.profile = profile
vpn.profile = profile vpn.profile = profile
title = profile?.id title = profile?.screenTitle
navigationItem.rightBarButtonItem = (profile?.context == .host) ? itemEdit : nil navigationItem.rightBarButtonItem = (profile?.context == .host) ? itemEdit : nil
if reloadingViews { if reloadingViews {
reloadModel() reloadModel()
@ -95,10 +95,9 @@ class ServiceViewController: UIViewController, StrongTableHost {
setProfile(service.activeProfile) setProfile(service.activeProfile)
} }
if let providerProfile = profile as? ProviderConnectionProfile { if let providerProfile = profile as? ProviderConnectionProfile {
lastInfrastructureUpdate = InfrastructureFactory.shared.modificationDate(for: providerProfile.name) lastInfrastructureUpdate = InfrastructureFactory.shared.modificationDate(forName: providerProfile.name)
} }
title = profile?.id
navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
navigationItem.leftItemsSupplementBackButton = true navigationItem.leftItemsSupplementBackButton = true
@ -596,7 +595,7 @@ class ServiceViewController: UIViewController, StrongTableHost {
let alert = UIAlertController.asAlert( let alert = UIAlertController.asAlert(
L10n.Core.Service.Alerts.Download.title, L10n.Core.Service.Alerts.Download.title,
L10n.Core.Service.Alerts.Download.message(providerProfile.name.rawValue) L10n.Core.Service.Alerts.Download.message(providerProfile.name)
) )
alert.addCancelAction(L10n.Core.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
alert.addPreferredAction(L10n.Core.Global.ok) { alert.addPreferredAction(L10n.Core.Global.ok) {

View File

@ -89,6 +89,8 @@
0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD7862257462800D033B4 /* Providers.xcassets */; }; 0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD7862257462800D033B4 /* Providers.xcassets */; };
0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD788225746B300D033B4 /* Flags.xcassets */; }; 0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD788225746B300D033B4 /* Flags.xcassets */; };
0E9CDB6723604AD5006733B4 /* ServerNetworkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */; }; 0E9CDB6723604AD5006733B4 /* ServerNetworkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */; };
0EA84515238A9B5200EFC500 /* Infrastructure+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */; };
0EA8451A238C2AB500EFC500 /* Infrastructure+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */; };
0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; }; 0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; };
0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */; }; 0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */; };
0EB67D6B2184581E00BA6200 /* ImportedHostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */; }; 0EB67D6B2184581E00BA6200 /* ImportedHostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */; };
@ -258,6 +260,8 @@
0E9CD7862257462800D033B4 /* Providers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Providers.xcassets; sourceTree = "<group>"; }; 0E9CD7862257462800D033B4 /* Providers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Providers.xcassets; sourceTree = "<group>"; };
0E9CD788225746B300D033B4 /* Flags.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flags.xcassets; sourceTree = "<group>"; }; 0E9CD788225746B300D033B4 /* Flags.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flags.xcassets; sourceTree = "<group>"; };
0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerNetworkViewController.swift; sourceTree = "<group>"; }; 0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerNetworkViewController.swift; sourceTree = "<group>"; };
0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Infrastructure+Name.swift"; path = "Submodules/Core/Passepartout/Sources/Services/Infrastructure+Name.swift"; sourceTree = SOURCE_ROOT; };
0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Infrastructure+Metadata.swift"; path = "Submodules/Core/Passepartout/Sources/Services/Infrastructure+Metadata.swift"; sourceTree = SOURCE_ROOT; };
0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+Search.swift"; sourceTree = "<group>"; }; 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+Search.swift"; sourceTree = "<group>"; };
0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportedHostsViewController.swift; sourceTree = "<group>"; }; 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportedHostsViewController.swift; sourceTree = "<group>"; };
0EB9EB7223867E7F009C0A1C /* TrustedNetworksUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksUI.swift; sourceTree = "<group>"; }; 0EB9EB7223867E7F009C0A1C /* TrustedNetworksUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksUI.swift; sourceTree = "<group>"; };
@ -545,6 +549,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0ED31C1120CF0ABA0027975F /* Infrastructure.swift */, 0ED31C1120CF0ABA0027975F /* Infrastructure.swift */,
0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */,
0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */,
0EBE3A83213C6ADE00BFA2F5 /* InfrastructureFactory.swift */, 0EBE3A83213C6ADE00BFA2F5 /* InfrastructureFactory.swift */,
0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */, 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */,
0ED31C0F20CF09A30027975F /* Pool.swift */, 0ED31C0F20CF09A30027975F /* Pool.swift */,
@ -985,6 +991,7 @@
0E3152CA223FA04D00F61841 /* InfrastructurePreset.swift in Sources */, 0E3152CA223FA04D00F61841 /* InfrastructurePreset.swift in Sources */,
0E3152CE223FA05400F61841 /* ConnectionService.swift in Sources */, 0E3152CE223FA05400F61841 /* ConnectionService.swift in Sources */,
0ED993B1223FF8C700B0F9C9 /* IntentDispatcher.swift in Sources */, 0ED993B1223FF8C700B0F9C9 /* IntentDispatcher.swift in Sources */,
0EA84515238A9B5200EFC500 /* Infrastructure+Name.swift in Sources */,
0EEF23412321AC55000AEBE3 /* Issue.swift in Sources */, 0EEF23412321AC55000AEBE3 /* Issue.swift in Sources */,
0E3152C3223FA04800F61841 /* StandardVPNProvider.swift in Sources */, 0E3152C3223FA04800F61841 /* StandardVPNProvider.swift in Sources */,
0E3152D1223FA05400F61841 /* Credentials.swift in Sources */, 0E3152D1223FA05400F61841 /* Credentials.swift in Sources */,
@ -996,6 +1003,7 @@
0EFB901822764689006405E4 /* ProfileNetworkSettings.swift in Sources */, 0EFB901822764689006405E4 /* ProfileNetworkSettings.swift in Sources */,
0E3152C0223FA03D00F61841 /* Utils.swift in Sources */, 0E3152C0223FA03D00F61841 /* Utils.swift in Sources */,
0E3152CB223FA04D00F61841 /* Pool.swift in Sources */, 0E3152CB223FA04D00F61841 /* Pool.swift in Sources */,
0EA8451A238C2AB500EFC500 /* Infrastructure+Metadata.swift in Sources */,
0EB9EB7323867E7F009C0A1C /* TrustedNetworksUI.swift in Sources */, 0EB9EB7323867E7F009C0A1C /* TrustedNetworksUI.swift in Sources */,
0E3CAFC0229AAE770008E5C8 /* Intents.intentdefinition in Sources */, 0E3CAFC0229AAE770008E5C8 /* Intents.intentdefinition in Sources */,
0E3152C7223FA04800F61841 /* VPNStatus.swift in Sources */, 0E3152C7223FA04800F61841 /* VPNStatus.swift in Sources */,

@ -1 +1 @@
Subproject commit 60b5c25a3cc79e0bffdd551c4593bdd18d291719 Subproject commit 0d2991f706fbb2a190ecccd390d5c993efd67c92

@ -1 +1 @@
Subproject commit 79cc4a739978b6fc98e910c65d7913431cb41915 Subproject commit c3ed76f010c51139eda1967055998a2308b1c730