diff --git a/Passepartout-iOS/AppDelegate.swift b/Passepartout-iOS/AppDelegate.swift index 9419c868..02be3bd1 100644 --- a/Passepartout-iOS/AppDelegate.swift +++ b/Passepartout-iOS/AppDelegate.swift @@ -40,11 +40,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele override init() { AppConstants.Log.configure() + InfrastructureFactory.shared.preload() super.init() } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - InfrastructureFactory.shared.loadCache() Theme.current.applyAppearance() Reviewer.shared.eventCountBeforeRating = AppConstants.Rating.eventCount diff --git a/Passepartout-iOS/Global/IssueReporter.swift b/Passepartout-iOS/Global/IssueReporter.swift index 787e58d8..13ea6dde 100644 --- a/Passepartout-iOS/Global/IssueReporter.swift +++ b/Passepartout-iOS/Global/IssueReporter.swift @@ -77,8 +77,8 @@ class IssueReporter: NSObject { var bodyMetadata = "--\n\n" bodyMetadata += DebugLog(raw: "").decoratedString() if let infrastructure = issue.infrastructure { - bodyMetadata += "Provider: \(infrastructure.name.rawValue)\n" - if let lastUpdated = InfrastructureFactory.shared.modificationDate(for: infrastructure.name) { + bodyMetadata += "Provider: \(infrastructure.name)\n" + if let lastUpdated = InfrastructureFactory.shared.modificationDate(forName: infrastructure.name) { bodyMetadata += "Last updated: \(lastUpdated)\n" } bodyMetadata += "\n" diff --git a/Passepartout-iOS/Global/Product.swift b/Passepartout-iOS/Global/Product.swift index ebd7beff..20e50bab 100644 --- a/Passepartout-iOS/Global/Product.swift +++ b/Passepartout-iOS/Global/Product.swift @@ -111,10 +111,10 @@ enum Product: String { } } -extension Infrastructure.Name { +extension Infrastructure.Metadata { var product: Product { - guard let product = Product(rawValue: "com.algoritmico.ios.Passepartout.providers.\(rawValue)") else { - fatalError("Product not found for provider \(rawValue)") + guard let product = Product(rawValue: "com.algoritmico.ios.Passepartout.providers.\(self)") else { + fatalError("Product not found for provider \(self)") } return product } diff --git a/Passepartout-iOS/Global/ProductManager.swift b/Passepartout-iOS/Global/ProductManager.swift index 11f23aea..245fc6e1 100644 --- a/Passepartout-iOS/Global/ProductManager.swift +++ b/Passepartout-iOS/Global/ProductManager.swift @@ -178,7 +178,7 @@ class ProductManager: NSObject { return true } return purchasedFeatures.contains { - return $0.rawValue.hasSuffix("providers.\(name.rawValue)") + return $0.rawValue.hasSuffix("providers.\(name)") } } diff --git a/Passepartout-iOS/Global/Theme.swift b/Passepartout-iOS/Global/Theme.swift index f60aeaaa..936089cb 100644 --- a/Passepartout-iOS/Global/Theme.swift +++ b/Passepartout-iOS/Global/Theme.swift @@ -189,9 +189,10 @@ extension MFMailComposeViewController { } } -extension Infrastructure.Name { +// FIXME: load from index JSON +extension Infrastructure.Metadata { var logo: UIImage? { - return ImageAsset(name: rawValue.lowercased()).image + return ImageAsset(name: name.lowercased()).image } } diff --git a/Passepartout-iOS/Scenes/AccountViewController.swift b/Passepartout-iOS/Scenes/AccountViewController.swift index e61f4237..df336194 100644 --- a/Passepartout-iOS/Scenes/AccountViewController.swift +++ b/Passepartout-iOS/Scenes/AccountViewController.swift @@ -61,28 +61,32 @@ class AccountViewController: UIViewController, StrongTableHost { guard let name = infrastructureName else { return nil } + // FIXME: make this dynamic? let V = L10n.Core.Account.Sections.Guidance.Footer.Infrastructure.self switch name { case .mullvad: - return V.mullvad(name.rawValue) + return V.mullvad(name) - case .nordVPN: - return V.nordvpn(name.rawValue) + case .nordvpn: + return V.nordvpn(name) case .pia: - return V.pia(name.rawValue) + return V.pia(name) - case .protonVPN: - return V.protonvpn(name.rawValue) + case .protonvpn: + return V.protonvpn(name) - case .tunnelBear: - return V.tunnelbear(name.rawValue) + case .tunnelbear: + return V.tunnelbear(name) - case .vyprVPN: - return V.vyprvpn(name.rawValue) + case .vyprvpn: + return V.vyprvpn(name) 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") } 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) return cell } diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift index b9891e06..0a69379f 100644 --- a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift @@ -39,7 +39,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost { private var hosts: [String] = [] - private var availableProviderNames: [Infrastructure.Name]? + private var availableProviders: [Infrastructure.Metadata]? private var didShowSubreddit = false @@ -177,7 +177,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost { vc.setProfile(selectedProfile) } else if let providerVC = destination as? WizardProviderViewController { - providerVC.availableNames = availableProviderNames ?? [] + providerVC.available = availableProviders ?? [] } } @@ -195,8 +195,8 @@ class OrganizerViewController: UITableViewController, StrongTableHost { } private func addNewProvider() { - let names = service.availableProviderNames() - guard !names.isEmpty else { + let providers = service.availableProviders() + guard !providers.isEmpty else { let alert = UIAlertController.asAlert( L10n.Core.Organizer.Sections.Providers.header, L10n.Core.Organizer.Alerts.ExhaustedProviders.message @@ -205,7 +205,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost { present(alert, animated: true, completion: nil) return } - availableProviderNames = names + availableProviders = providers perform(segue: StoryboardSegue.Organizer.addProviderSegueIdentifier) } @@ -479,12 +479,13 @@ extension OrganizerViewController { case .profile: let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let rowProfile = profileKey(at: indexPath) - if rowProfile.context == .provider, let providerName = Infrastructure.Name(rawValue: rowProfile.id) { - cell.imageView?.image = providerName.logo + if rowProfile.context == .provider, let metadata = InfrastructureFactory.shared.metadata(forName: rowProfile.id) { + cell.imageView?.image = metadata.logo + cell.leftText = metadata.description } else { 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 return cell diff --git a/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift b/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift index 18e12271..277fb019 100644 --- a/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift @@ -27,7 +27,7 @@ import UIKit import PassepartoutCore class WizardProviderViewController: UITableViewController { - var availableNames: [Infrastructure.Name] = [] + var available: [Infrastructure.Metadata] = [] private var createdProfile: ProviderConnectionProfile? @@ -37,17 +37,17 @@ class WizardProviderViewController: UITableViewController { title = L10n.Core.Organizer.Sections.Providers.header } - private func next(withName name: Infrastructure.Name) { - guard ProductManager.shared.isEligible(forProvider: name) else { - presentPurchaseScreen(forProduct: name.product) + private func next(withMetadata metadata: Infrastructure.Metadata) { + guard ProductManager.shared.isEligible(forProvider: metadata.name) else { + presentPurchaseScreen(forProduct: metadata.product) return } - let profile = ProviderConnectionProfile(name: name) + let profile = ProviderConnectionProfile(name: metadata.name) createdProfile = profile 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.infrastructureName = infrastructure.name accountVC.delegate = self @@ -73,20 +73,20 @@ class WizardProviderViewController: UITableViewController { extension WizardProviderViewController { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return availableNames.count + return available.count } 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) - cell.imageView?.image = name.logo - cell.leftText = name.rawValue + cell.imageView?.image = metadata.logo + cell.leftText = metadata.description return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let name = availableNames[indexPath.row] - next(withName: name) + let metadata = available[indexPath.row] + next(withMetadata: metadata) } } diff --git a/Passepartout-iOS/Scenes/ServiceViewController.swift b/Passepartout-iOS/Scenes/ServiceViewController.swift index f34c0cca..0a2e5f15 100644 --- a/Passepartout-iOS/Scenes/ServiceViewController.swift +++ b/Passepartout-iOS/Scenes/ServiceViewController.swift @@ -79,7 +79,7 @@ class ServiceViewController: UIViewController, StrongTableHost { self.profile = profile vpn.profile = profile - title = profile?.id + title = profile?.screenTitle navigationItem.rightBarButtonItem = (profile?.context == .host) ? itemEdit : nil if reloadingViews { reloadModel() @@ -95,10 +95,9 @@ class ServiceViewController: UIViewController, StrongTableHost { setProfile(service.activeProfile) } 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.leftItemsSupplementBackButton = true @@ -596,7 +595,7 @@ class ServiceViewController: UIViewController, StrongTableHost { let alert = UIAlertController.asAlert( 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.addPreferredAction(L10n.Core.Global.ok) { diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 33910cfd..de41e9eb 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -89,6 +89,8 @@ 0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD7862257462800D033B4 /* Providers.xcassets */; }; 0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD788225746B300D033B4 /* Flags.xcassets */; }; 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 */; }; 0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB60FD92111136E00AD27F3 /* UITextView+Search.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 = ""; }; 0E9CD788225746B300D033B4 /* Flags.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flags.xcassets; sourceTree = ""; }; 0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerNetworkViewController.swift; sourceTree = ""; }; + 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 = ""; }; 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportedHostsViewController.swift; sourceTree = ""; }; 0EB9EB7223867E7F009C0A1C /* TrustedNetworksUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksUI.swift; sourceTree = ""; }; @@ -545,6 +549,8 @@ isa = PBXGroup; children = ( 0ED31C1120CF0ABA0027975F /* Infrastructure.swift */, + 0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */, + 0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */, 0EBE3A83213C6ADE00BFA2F5 /* InfrastructureFactory.swift */, 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */, 0ED31C0F20CF09A30027975F /* Pool.swift */, @@ -985,6 +991,7 @@ 0E3152CA223FA04D00F61841 /* InfrastructurePreset.swift in Sources */, 0E3152CE223FA05400F61841 /* ConnectionService.swift in Sources */, 0ED993B1223FF8C700B0F9C9 /* IntentDispatcher.swift in Sources */, + 0EA84515238A9B5200EFC500 /* Infrastructure+Name.swift in Sources */, 0EEF23412321AC55000AEBE3 /* Issue.swift in Sources */, 0E3152C3223FA04800F61841 /* StandardVPNProvider.swift in Sources */, 0E3152D1223FA05400F61841 /* Credentials.swift in Sources */, @@ -996,6 +1003,7 @@ 0EFB901822764689006405E4 /* ProfileNetworkSettings.swift in Sources */, 0E3152C0223FA03D00F61841 /* Utils.swift in Sources */, 0E3152CB223FA04D00F61841 /* Pool.swift in Sources */, + 0EA8451A238C2AB500EFC500 /* Infrastructure+Metadata.swift in Sources */, 0EB9EB7323867E7F009C0A1C /* TrustedNetworksUI.swift in Sources */, 0E3CAFC0229AAE770008E5C8 /* Intents.intentdefinition in Sources */, 0E3152C7223FA04800F61841 /* VPNStatus.swift in Sources */, diff --git a/Submodules/API b/Submodules/API index 60b5c25a..0d2991f7 160000 --- a/Submodules/API +++ b/Submodules/API @@ -1 +1 @@ -Subproject commit 60b5c25a3cc79e0bffdd551c4593bdd18d291719 +Subproject commit 0d2991f706fbb2a190ecccd390d5c993efd67c92 diff --git a/Submodules/Core b/Submodules/Core index 79cc4a73..c3ed76f0 160000 --- a/Submodules/Core +++ b/Submodules/Core @@ -1 +1 @@ -Subproject commit 79cc4a739978b6fc98e910c65d7913431cb41915 +Subproject commit c3ed76f010c51139eda1967055998a2308b1c730