diff --git a/Passepartout-iOS/AppDelegate.swift b/Passepartout-iOS/AppDelegate.swift
index f8ddbce8..795ea6b4 100644
--- a/Passepartout-iOS/AppDelegate.swift
+++ b/Passepartout-iOS/AppDelegate.swift
@@ -24,9 +24,6 @@
//
import UIKit
-import SwiftyBeaver
-
-private let log = SwiftyBeaver.self
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
@@ -87,60 +84,41 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
}
// MARK: URLs
-
+
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
guard let root = window?.rootViewController else {
fatalError("No window.rootViewController?")
}
- do {
-
- // already presented: update URL
- if let nav = root.presentedViewController as? UINavigationController, let wizard = nav.topViewController as? WizardHostViewController {
- try wizard.setConfigurationURL(url)
- return true
- }
-
- // present now
- let nav = StoryboardScene.Organizer.wizardHostIdentifier.instantiate()
- guard let wizard = nav.topViewController as? WizardHostViewController else {
- fatalError("Expected WizardHostViewController from storyboard")
- }
- try wizard.setConfigurationURL(url)
-
- // best effort to delegate to main vc
- let split = root as? UISplitViewController
- let master = split?.viewControllers.first as? UINavigationController
- master?.viewControllers.forEach {
- if let organizerVC = $0 as? OrganizerViewController {
- wizard.delegate = organizerVC
- }
- }
- nav.modalPresentationStyle = .formSheet
- root.present(nav, animated: true, completion: nil)
- } catch ApplicationError.missingConfiguration(let option) {
- let message = L10n.Wizards.Host.Alerts.Missing.message(option)
- alertConfigurationImportError(url: url, in: root, withMessage: message)
- } catch ApplicationError.unsupportedConfiguration(let option) {
- let message = L10n.Wizards.Host.Alerts.Unsupported.message(option)
- alertConfigurationImportError(url: url, in: root, withMessage: message)
- } catch let e {
- let message = L10n.Wizards.Host.Alerts.Parsing.message(e.localizedDescription)
- alertConfigurationImportError(url: url, in: root, withMessage: message)
+ guard let parsedFile = ParsedFile.from(url, withErrorAlertIn: root) else {
+ return true
}
+
+ // already presented: update parsed configuration
+ if let nav = root.presentedViewController as? UINavigationController, let wizard = nav.topViewController as? WizardHostViewController {
+ wizard.parsedFile = parsedFile
+ return true
+ }
+
+ // present now
+ let nav = StoryboardScene.Organizer.wizardHostIdentifier.instantiate()
+ guard let wizard = nav.topViewController as? WizardHostViewController else {
+ fatalError("Expected WizardHostViewController from storyboard")
+ }
+ wizard.parsedFile = parsedFile
+
+ // best effort to delegate to main vc
+ let split = root as? UISplitViewController
+ let master = split?.viewControllers.first as? UINavigationController
+ master?.viewControllers.forEach {
+ if let organizerVC = $0 as? OrganizerViewController {
+ wizard.delegate = organizerVC
+ }
+ }
+ nav.modalPresentationStyle = .formSheet
+ root.present(nav, animated: true, completion: nil)
return true
}
-
- private func alertConfigurationImportError(url: URL, in vc: UIViewController, withMessage message: String) {
- let alert = Macros.alert(L10n.Organizer.Sections.Hosts.header, message)
-// alert.addDefaultAction(L10n.Wizards.Host.Alerts.Buttons.report) {
-// var attach = IssueReporter.Attachments(debugLog: false, configurationURL: url)
-// attach.description = message
-// IssueReporter.shared.present(in: vc, withAttachments: attach)
-// }
- alert.addCancelAction(L10n.Global.cancel)
- vc.present(alert, animated: true, completion: nil)
- }
}
extension UISplitViewController {
diff --git a/Passepartout-iOS/Global/ParsedFile+Alerts.swift b/Passepartout-iOS/Global/ParsedFile+Alerts.swift
new file mode 100644
index 00000000..7cc370dd
--- /dev/null
+++ b/Passepartout-iOS/Global/ParsedFile+Alerts.swift
@@ -0,0 +1,64 @@
+//
+// ParsedFile+Alerts.swift
+// Passepartout-iOS
+//
+// Created by Davide De Rosa on 10/27/18.
+// Copyright (c) 2018 Davide De Rosa. All rights reserved.
+//
+// https://github.com/keeshux
+//
+// This file is part of Passepartout.
+//
+// Passepartout is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Passepartout is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Passepartout. If not, see .
+//
+
+import Foundation
+import UIKit
+import TunnelKit
+import SwiftyBeaver
+
+private let log = SwiftyBeaver.self
+
+extension ParsedFile {
+ static func from(_ url: URL, withErrorAlertIn viewController: UIViewController) -> ParsedFile? {
+ log.debug("Parsing configuration URL: \(url)")
+ do {
+ return try TunnelKitProvider.Configuration.parsed(from: url)
+ } catch ApplicationError.missingConfiguration(let option) {
+ log.error("Could not parse configuration URL: missing configuration, \(option)")
+ let message = L10n.ParsedFile.Alerts.Missing.message(option)
+ alertConfigurationImportError(url: url, in: viewController, withMessage: message)
+ } catch ApplicationError.unsupportedConfiguration(let option) {
+ log.error("Could not parse configuration URL: unsupported configuration, \(option)")
+ let message = L10n.ParsedFile.Alerts.Unsupported.message(option)
+ alertConfigurationImportError(url: url, in: viewController, withMessage: message)
+ } catch let e {
+ log.error("Could not parse configuration URL: \(e)")
+ let message = L10n.ParsedFile.Alerts.Parsing.message(e.localizedDescription)
+ alertConfigurationImportError(url: url, in: viewController, withMessage: message)
+ }
+ return nil
+ }
+
+ private static func alertConfigurationImportError(url: URL, in vc: UIViewController, withMessage message: String) {
+ let alert = Macros.alert(url.normalizedFilename, message)
+// alert.addDefaultAction(L10n.ParsedFile.Alerts.Buttons.report) {
+// var attach = IssueReporter.Attachments(debugLog: false, configurationURL: url)
+// attach.description = message
+// IssueReporter.shared.present(in: vc, withAttachments: attach)
+// }
+ alert.addCancelAction(L10n.Global.ok)
+ vc.present(alert, animated: true, completion: nil)
+ }
+}
diff --git a/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift b/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift
index c94168de..db2c4b73 100644
--- a/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift
+++ b/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift
@@ -36,7 +36,7 @@ class WizardHostViewController: UITableViewController, TableModelHost, Wizard {
return TransientStore.shared.service.ids(forContext: .host).sorted()
}()
- private var parsedFile: ParsedFile? {
+ var parsedFile: ParsedFile? {
didSet {
useSuggestedTitle()
}
@@ -86,17 +86,6 @@ class WizardHostViewController: UITableViewController, TableModelHost, Wizard {
// MARK: Actions
- func setConfigurationURL(_ url: URL) throws {
- log.debug("Parsing configuration URL: \(url)")
-
- do {
- parsedFile = try TunnelKitProvider.Configuration.parsed(from: url)
- } catch let e {
- log.error("Could not parse .ovpn configuration file: \(e)")
- throw e
- }
- }
-
private func useSuggestedTitle() {
guard let field = cellTitle?.field else {
return
diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj
index 7ae60691..eafffd55 100644
--- a/Passepartout.xcodeproj/project.pbxproj
+++ b/Passepartout.xcodeproj/project.pbxproj
@@ -46,6 +46,7 @@
0E89DFD0213F223400741BA1 /* Wizard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCF213F223400741BA1 /* Wizard.swift */; };
0E8D97E221388B52006FB4A0 /* InfrastructurePreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */; };
0E8D97E521389277006FB4A0 /* pia.json in Resources */ = {isa = PBXBuildFile; fileRef = 0E8D97E421389276006FB4A0 /* pia.json */; };
+ 0EA068F4218475F800C320AD /* ParsedFile+Alerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA068F3218475F800C320AD /* ParsedFile+Alerts.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 */; };
0EBBE8F221822B4D00106008 /* ConnectionServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBBE8F021822B4D00106008 /* ConnectionServiceTests.swift */; };
@@ -166,6 +167,7 @@
0E89DFCF213F223400741BA1 /* Wizard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wizard.swift; sourceTree = ""; };
0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfrastructurePreset.swift; sourceTree = ""; };
0E8D97E421389276006FB4A0 /* pia.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pia.json; sourceTree = ""; };
+ 0EA068F3218475F800C320AD /* ParsedFile+Alerts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParsedFile+Alerts.swift"; sourceTree = ""; };
0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+Search.swift"; sourceTree = ""; };
0EBBE8F021822B4D00106008 /* ConnectionServiceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionServiceTests.swift; sourceTree = ""; };
0EBBE8F121822B4D00106008 /* ConnectionService.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConnectionService.json; sourceTree = ""; };
@@ -435,6 +437,7 @@
0EFD943D215BE10800529B64 /* IssueReporter.swift */,
0E4FD7F020D58618002221FF /* Macros.swift */,
0ED38AE9214054A50004D387 /* OptionViewController.swift */,
+ 0EA068F3218475F800C320AD /* ParsedFile+Alerts.swift */,
0EDE8DE320C89028004C739C /* SwiftGen+Storyboards.swift */,
0E05C61C20D27C82006EE732 /* Theme.swift */,
0ECEE44F20E1182E00A6BB43 /* Theme+Cells.swift */,
@@ -852,6 +855,7 @@
0E57F63E20C83FC5008323CF /* ServiceViewController.swift in Sources */,
0E39BCF0214B9EF10035E9DE /* WebServices.swift in Sources */,
0EDE8DE720C93945004C739C /* Credentials.swift in Sources */,
+ 0EA068F4218475F800C320AD /* ParsedFile+Alerts.swift in Sources */,
0ED38AF2214177920004D387 /* VPNProvider.swift in Sources */,
0E4C9CB920DB9BC600A0C59C /* TrustedNetworks.swift in Sources */,
0E57F63C20C83FC5008323CF /* AppDelegate.swift in Sources */,
diff --git a/Passepartout/Resources/en.lproj/Localizable.strings b/Passepartout/Resources/en.lproj/Localizable.strings
index aec45ff9..67084496 100644
--- a/Passepartout/Resources/en.lproj/Localizable.strings
+++ b/Passepartout/Resources/en.lproj/Localizable.strings
@@ -52,10 +52,11 @@
"wizards.host.cells.title_input.placeholder" = "My Profile";
"wizards.host.sections.existing.header" = "Existing profiles";
"wizards.host.alerts.existing.message" = "A host profile with the same title already exists. Replace it?";
-"wizards.host.alerts.missing.message" = "The configuration file lacks a required option (%@).";
-"wizards.host.alerts.unsupported.message" = "The configuration file contains an unsupported option (%@).";
-"wizards.host.alerts.parsing.message" = "Unable to parse the provided configuration file (%@).";
-"wizards.host.alerts.buttons.report" = "Report an issue";
+
+"parsed_file.alerts.missing.message" = "The configuration file lacks a required option (%@).";
+"parsed_file.alerts.unsupported.message" = "The configuration file contains an unsupported option (%@).";
+"parsed_file.alerts.parsing.message" = "Unable to parse the provided configuration file (%@).";
+"parsed_file.alerts.buttons.report" = "Report an issue";
"service.welcome.message" = "Welcome to Passepartout!\n\nUse the organizer to add a new profile.";
"service.sections.general.header" = "General";
diff --git a/Passepartout/Sources/SwiftGen+Strings.swift b/Passepartout/Sources/SwiftGen+Strings.swift
index e6827a50..29293221 100644
--- a/Passepartout/Sources/SwiftGen+Strings.swift
+++ b/Passepartout/Sources/SwiftGen+Strings.swift
@@ -404,6 +404,38 @@ internal enum L10n {
}
}
+ internal enum ParsedFile {
+
+ internal enum Alerts {
+
+ internal enum Buttons {
+ /// Report an issue
+ internal static let report = L10n.tr("Localizable", "parsed_file.alerts.buttons.report")
+ }
+
+ internal enum Missing {
+ /// The configuration file lacks a required option (%@).
+ internal static func message(_ p1: String) -> String {
+ return L10n.tr("Localizable", "parsed_file.alerts.missing.message", p1)
+ }
+ }
+
+ internal enum Parsing {
+ /// Unable to parse the provided configuration file (%@).
+ internal static func message(_ p1: String) -> String {
+ return L10n.tr("Localizable", "parsed_file.alerts.parsing.message", p1)
+ }
+ }
+
+ internal enum Unsupported {
+ /// The configuration file contains an unsupported option (%@).
+ internal static func message(_ p1: String) -> String {
+ return L10n.tr("Localizable", "parsed_file.alerts.unsupported.message", p1)
+ }
+ }
+ }
+ }
+
internal enum Provider {
internal enum Preset {
@@ -734,36 +766,10 @@ internal enum L10n {
internal enum Alerts {
- internal enum Buttons {
- /// Report an issue
- internal static let report = L10n.tr("Localizable", "wizards.host.alerts.buttons.report")
- }
-
internal enum Existing {
/// A host profile with the same title already exists. Replace it?
internal static let message = L10n.tr("Localizable", "wizards.host.alerts.existing.message")
}
-
- internal enum Missing {
- /// The configuration file lacks a required option (%@).
- internal static func message(_ p1: String) -> String {
- return L10n.tr("Localizable", "wizards.host.alerts.missing.message", p1)
- }
- }
-
- internal enum Parsing {
- /// Unable to parse the provided configuration file (%@).
- internal static func message(_ p1: String) -> String {
- return L10n.tr("Localizable", "wizards.host.alerts.parsing.message", p1)
- }
- }
-
- internal enum Unsupported {
- /// The configuration file contains an unsupported option (%@).
- internal static func message(_ p1: String) -> String {
- return L10n.tr("Localizable", "wizards.host.alerts.unsupported.message", p1)
- }
- }
}
internal enum Cells {