From 0e7c0b6388d425df5d73a50ca52c65beee262c0d Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Sat, 27 Oct 2018 11:14:06 +0200 Subject: [PATCH] List imported .ovpn if any, fall back to alert Use .formSheet presentation (iPad). --- .../ImportedHostsViewController.swift | 57 +++++++++++++++++++ .../Organizer/OrganizerViewController.swift | 7 +-- .../en.lproj/Organizer.storyboard | 4 +- .../Resources/en.lproj/Localizable.strings | 2 +- .../ConnectionService+Configurations.swift | 13 +++++ Passepartout/Sources/SwiftGen+Strings.swift | 2 +- 6 files changed, 75 insertions(+), 10 deletions(-) diff --git a/Passepartout-iOS/Scenes/Organizer/ImportedHostsViewController.swift b/Passepartout-iOS/Scenes/Organizer/ImportedHostsViewController.swift index 4cee520b..f5cbd812 100644 --- a/Passepartout-iOS/Scenes/Organizer/ImportedHostsViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/ImportedHostsViewController.swift @@ -22,18 +22,75 @@ // You should have received a copy of the GNU General Public License // along with Passepartout. If not, see . // + import UIKit +import TunnelKit +import SwiftyBeaver + +private let log = SwiftyBeaver.self class ImportedHostsViewController: UITableViewController { + private lazy var pendingConfigurationURLs = TransientStore.shared.service.pendingConfigurationURLs() + + private var parsedFile: ParsedFile? + override func viewDidLoad() { super.viewDidLoad() title = L10n.ImportedHosts.title } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + guard !pendingConfigurationURLs.isEmpty else { + let alert = Macros.alert( + L10n.ImportedHosts.title, + L10n.Organizer.Alerts.AddHost.message + ) + alert.addCancelAction(L10n.Global.ok) { + self.close() + } + present(alert, animated: true, completion: nil) + return + } + } + // MARK: Actions + override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { + guard let cell = sender as? UITableViewCell, let indexPath = tableView.indexPath(for: cell) else { + return false + } + let url = pendingConfigurationURLs[indexPath.row] + guard let parsedFile = ParsedFile.from(url, withErrorAlertIn: self) else { + return false + } + self.parsedFile = parsedFile + return true + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + guard let wizard = segue.destination as? WizardHostViewController else { + return + } + wizard.parsedFile = parsedFile + } + @IBAction private func close() { dismiss(animated: true, completion: nil) } } + +extension ImportedHostsViewController { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return pendingConfigurationURLs.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let url = pendingConfigurationURLs[indexPath.row] + let cell = Cells.setting.dequeue(from: tableView, for: indexPath) + cell.leftText = url.normalizedFilename + return cell + } +} diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift index 9b7bb949..0785cd76 100644 --- a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift @@ -174,12 +174,7 @@ class OrganizerViewController: UITableViewController, TableModelHost { } private func addNewHost() { - let alert = Macros.alert( - L10n.Organizer.Sections.Hosts.header, - L10n.Organizer.Alerts.AddHost.message - ) - alert.addCancelAction(L10n.Global.ok) - present(alert, animated: true, completion: nil) + perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier) } private func removeProfile(at indexPath: IndexPath) { diff --git a/Passepartout-iOS/en.lproj/Organizer.storyboard b/Passepartout-iOS/en.lproj/Organizer.storyboard index 2a100a63..f4006b7c 100644 --- a/Passepartout-iOS/en.lproj/Organizer.storyboard +++ b/Passepartout-iOS/en.lproj/Organizer.storyboard @@ -293,7 +293,7 @@ - + @@ -567,6 +567,6 @@ - + diff --git a/Passepartout/Resources/en.lproj/Localizable.strings b/Passepartout/Resources/en.lproj/Localizable.strings index fc3021a4..e3a06b30 100644 --- a/Passepartout/Resources/en.lproj/Localizable.strings +++ b/Passepartout/Resources/en.lproj/Localizable.strings @@ -43,7 +43,7 @@ "organizer.cells.about.caption" = "About %@"; "organizer.cells.uninstall.caption" = "Delete VPN profile"; "organizer.alerts.exhausted_providers.message" = "You have created profiles for any available network."; -"organizer.alerts.add_host.message" = "Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile."; +"organizer.alerts.add_host.message" = "Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile.\n\nYou can also import an .ovpn with iTunes File Sharing."; "organizer.alerts.delete_vpn_profile.message" = "Do you really want to delete the VPN profile from the device?"; "account.suggestion_footer.infrastructure.pia" = "Use your website credentials. Your username is usually numeric with a \"p\" prefix."; diff --git a/Passepartout/Sources/Model/ConnectionService+Configurations.swift b/Passepartout/Sources/Model/ConnectionService+Configurations.swift index 9a717fc9..d17ce951 100644 --- a/Passepartout/Sources/Model/ConnectionService+Configurations.swift +++ b/Passepartout/Sources/Model/ConnectionService+Configurations.swift @@ -24,6 +24,9 @@ // import Foundation +import SwiftyBeaver + +private let log = SwiftyBeaver.self extension ConnectionService { func save(configurationURL: URL, for profile: ConnectionProfile) throws -> URL { @@ -46,4 +49,14 @@ extension ConnectionService { let contextURL = ConnectionService.ProfileKey(profile).contextURL(in: self) return contextURL.appendingPathComponent(profile.id).appendingPathExtension("ovpn") } + + func pendingConfigurationURLs() -> [URL] { + do { + let list = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil, options: []) + return list.filter { $0.pathExtension == "ovpn" } + } catch let e { + log.error("Could not list imported configurations: \(e)") + return [] + } + } } diff --git a/Passepartout/Sources/SwiftGen+Strings.swift b/Passepartout/Sources/SwiftGen+Strings.swift index b87019a4..7859a287 100644 --- a/Passepartout/Sources/SwiftGen+Strings.swift +++ b/Passepartout/Sources/SwiftGen+Strings.swift @@ -343,7 +343,7 @@ internal enum L10n { internal enum Alerts { internal enum AddHost { - /// Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile. + /// Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile.\n\nYou can also import an .ovpn with iTunes File Sharing. internal static let message = L10n.tr("Localizable", "organizer.alerts.add_host.message") }