diff --git a/Passepartout-iOS/AppDelegate.swift b/Passepartout-iOS/AppDelegate.swift index ddd18ddb..9fccea82 100644 --- a/Passepartout-iOS/AppDelegate.swift +++ b/Passepartout-iOS/AppDelegate.swift @@ -95,12 +95,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele try? fm.removeItem(at: url) return true } + handleParsedFile(parsedFile, in: root) + return true + } + + private func handleParsedFile(_ parsedFile: ParsedFile, in root: UIViewController) { // already presented: update parsed configuration if let nav = root.presentedViewController as? UINavigationController, let wizard = nav.topViewController as? WizardHostViewController { wizard.parsedFile = parsedFile wizard.removesConfigurationOnCancel = true - return true + return } // present now @@ -121,7 +126,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele } nav.modalPresentationStyle = .formSheet root.present(nav, animated: true, completion: nil) - return true } } diff --git a/Passepartout-iOS/Global/ParsedFile+Alerts.swift b/Passepartout-iOS/Global/ParsedFile+Alerts.swift index 7cc370dd..abd3cdc1 100644 --- a/Passepartout-iOS/Global/ParsedFile+Alerts.swift +++ b/Passepartout-iOS/Global/ParsedFile+Alerts.swift @@ -32,26 +32,19 @@ private let log = SwiftyBeaver.self extension ParsedFile { static func from(_ url: URL, withErrorAlertIn viewController: UIViewController) -> ParsedFile? { + let file: 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) + file = try TunnelKitProvider.Configuration.parsed(from: url) } 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) + let message = localizedMessage(forError: e) + alertImportError(url: url, in: viewController, withMessage: message) + return nil } - return nil + return file } - private static func alertConfigurationImportError(url: URL, in vc: UIViewController, withMessage message: String) { + private static func alertImportError(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) @@ -61,4 +54,48 @@ extension ParsedFile { alert.addCancelAction(L10n.Global.ok) vc.present(alert, animated: true, completion: nil) } + + static func alertImportWarning(url: URL, in vc: UIViewController, withWarning warning: ApplicationError, completionHandler: @escaping (Bool) -> Void) { + let message = details(forWarning: warning) + let alert = Macros.alert(url.normalizedFilename, L10n.ParsedFile.Alerts.PotentiallyUnsupported.message(message)) + alert.addDefaultAction(L10n.Global.ok) { + completionHandler(true) + } + alert.addCancelAction(L10n.Global.cancel) { + completionHandler(false) + } + vc.present(alert, animated: true, completion: nil) + } + + private static func localizedMessage(forError error: Error) -> String { + if let appError = error as? ApplicationError { + switch appError { + case .missingConfiguration(let option): + log.error("Could not parse configuration URL: missing configuration, \(option)") + return L10n.ParsedFile.Alerts.Missing.message(option) + + case .unsupportedConfiguration(let option): + log.error("Could not parse configuration URL: unsupported configuration, \(option)") + return L10n.ParsedFile.Alerts.Unsupported.message(option) + + default: + break + } + } + log.error("Could not parse configuration URL: \(error)") + return L10n.ParsedFile.Alerts.Parsing.message(error.localizedDescription) + } + + private static func details(forWarning warning: ApplicationError) -> String { + switch warning { + case .missingConfiguration(let option): + return option + + case .unsupportedConfiguration(let option): + return option + + default: + fatalError("Only use .missingConfiguration or .unsupportedConfiguration for warnings") + } + } } diff --git a/Passepartout/Resources/en.lproj/Localizable.strings b/Passepartout/Resources/en.lproj/Localizable.strings index e3a06b30..28a2c496 100644 --- a/Passepartout/Resources/en.lproj/Localizable.strings +++ b/Passepartout/Resources/en.lproj/Localizable.strings @@ -55,6 +55,7 @@ "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.potentially_unsupported.message" = "The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings."; "parsed_file.alerts.parsing.message" = "Unable to parse the provided configuration file (%@)."; "parsed_file.alerts.buttons.report" = "Report an issue"; diff --git a/Passepartout/Sources/SwiftGen+Strings.swift b/Passepartout/Sources/SwiftGen+Strings.swift index 7859a287..4ff76209 100644 --- a/Passepartout/Sources/SwiftGen+Strings.swift +++ b/Passepartout/Sources/SwiftGen+Strings.swift @@ -432,6 +432,13 @@ internal enum L10n { } } + internal enum PotentiallyUnsupported { + /// The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings. + internal static func message(_ p1: String) -> String { + return L10n.tr("Localizable", "parsed_file.alerts.potentially_unsupported.message", p1) + } + } + internal enum Unsupported { /// The configuration file contains an unsupported option (%@). internal static func message(_ p1: String) -> String {