Fixe file/function related warnings.

This commit is contained in:
Jeroen Leenarts 2018-09-26 11:21:53 +02:00
parent e27a3addb9
commit 3f9858a655
7 changed files with 282 additions and 224 deletions

View File

@ -34,6 +34,11 @@
4A4BAD2320B6026900F12B28 /* Interface+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4BAD1F20B6026900F12B28 /* Interface+CoreDataClass.swift */; };
4A61D82E20D98CE2006C7A76 /* WireGuardNetworkExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4A61D82620D98CE1006C7A76 /* WireGuardNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4A61D83520D98D25006C7A76 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */; };
4A8A2296215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A2295215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift */; };
4A8A2298215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A2297215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift */; };
4A8A229A215B782E00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A2299215B782D00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift */; };
4A8A229C215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A229B215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift */; };
4A8A229E215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A229D215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift */; };
4A8AABD820B6A79100B6D8C1 /* UITableView+WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */; };
4AADEA2B212616F7008C24FD /* String+Arrays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FA1D50F2124D80C00DBA2E6 /* String+Arrays.swift */; };
4ABF718E214D8B0300A1E0BF /* TunnelInfoTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ABF718D214D8B0300A1E0BF /* TunnelInfoTableViewController.swift */; };
@ -123,6 +128,11 @@
4A61D82B20D98CE2006C7A76 /* WireGuardNetworkExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuardNetworkExtension.entitlements; sourceTree = "<group>"; };
4A61D83320D98D07006C7A76 /* WireGuard.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuard.entitlements; sourceTree = "<group>"; };
4A61D83420D98D25006C7A76 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
4A8A2295215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+QRScanViewControllerDelegate.swift"; sourceTree = "<group>"; };
4A8A2297215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+SettingsTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
4A8A2299215B782D00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
4A8A229B215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+TunnelsTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
4A8A229D215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+TunnelInfoTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+WireGuard.swift"; sourceTree = "<group>"; };
4ABF718D214D8B0300A1E0BF /* TunnelInfoTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelInfoTableViewController.swift; sourceTree = "<group>"; };
4ABFFE9D212D399F00107136 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; };
@ -248,6 +258,11 @@
4A4BAD0D20B5F6C300F12B28 /* Coordinator.swift */,
4A4BAD0F20B5F6EC00F12B28 /* RootCoordinator.swift */,
4A4BAD0B20B5F6AA00F12B28 /* AppCoordinator.swift */,
4A8A229D215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift */,
4A8A229B215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift */,
4A8A2295215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift */,
4A8A2297215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift */,
4A8A2299215B782D00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift */,
);
path = Coordinators;
sourceTree = "<group>";
@ -585,16 +600,21 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4A8A229A215B782E00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift in Sources */,
4A4BAD0C20B5F6AA00F12B28 /* AppCoordinator.swift in Sources */,
4A4BAD2220B6026900F12B28 /* Interface+CoreDataProperties.swift in Sources */,
4A8A2298215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift in Sources */,
4AEAC32B20F14BA9007B67AB /* Log.swift in Sources */,
4A8A229E215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift in Sources */,
4A4BAD1320B5F82400F12B28 /* Identifyable.swift in Sources */,
4A4BAD1720B5F8DE00F12B28 /* WireGuard.xcdatamodeld in Sources */,
5FCC4347212B3E2C009A9C58 /* Attribute.swift in Sources */,
4A4BAD1A20B5F8FF00F12B28 /* Tunnel+CoreDataClass.swift in Sources */,
4A4BACE820B5F1BF00F12B28 /* TunnelsTableViewController.swift in Sources */,
4A4BAD1020B5F6EC00F12B28 /* RootCoordinator.swift in Sources */,
4A8A2296215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift in Sources */,
4A4351592124956200261999 /* Validators.swift in Sources */,
4A8A229C215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift in Sources */,
5FA1D4CB21249F7D00DBA2E6 /* Peer+Extension.swift in Sources */,
5FA1D5122124DA6400DBA2E6 /* String+Base64.swift in Sources */,
4AC5462E2116306F00749D21 /* Tunnel+Extension.swift in Sources */,

View File

@ -0,0 +1,16 @@
//
// Copyright © 2018 WireGuard LLC. All rights reserved.
//
import Foundation
extension AppCoordinator: QRScanViewControllerDelegate {
func didSave(tunnel: Tunnel, qrScanViewController: QRScanViewController) {
qrScanViewController.navigationController?.popViewController(animated: true)
showTunnelInfoViewController(tunnel: tunnel, context: tunnel.managedObjectContext!)
}
func didCancel(qrScanViewController: QRScanViewController) {
qrScanViewController.navigationController?.popViewController(animated: true)
}
}

View File

@ -0,0 +1,17 @@
//
// Copyright © 2018 WireGuard LLC. All rights reserved.
//
import UIKit
import PromiseKit
import NetworkExtension
enum GoVersionCoordinatorError: Error {
case noSession
}
extension AppCoordinator: SettingsTableViewControllerDelegate {
func exportTunnels(settingsTableViewController: SettingsTableViewController, sourceView: UIView) {
self.exportConfigs(sourceView: sourceView)
}
}

View File

@ -0,0 +1,11 @@
//
// Copyright © 2018 WireGuard LLC. All rights reserved.
//
import Foundation
extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
saveTunnel(tunnel)
}
}

View File

@ -0,0 +1,19 @@
//
// Copyright © 2018 WireGuard LLC. All rights reserved.
//
import Foundation
extension AppCoordinator: TunnelInfoTableViewControllerDelegate {
func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) {
print("configure tunnel \(tunnel)")
let editContext = persistentContainer.newBackgroundContext()
var backgroundTunnel: Tunnel?
editContext.performAndWait {
backgroundTunnel = editContext.object(with: tunnel.objectID) as? Tunnel
}
showTunnelConfigurationViewController(tunnel: backgroundTunnel, context: editContext)
}
}

View File

@ -0,0 +1,196 @@
//
// Copyright © 2018 WireGuard LLC. All rights reserved.
//
import UIKit
import NetworkExtension
import os.log
import MobileCoreServices
import ZIPFoundation
import PromiseKit
extension AppCoordinator: TunnelsTableViewControllerDelegate {
func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
return session?.status ?? .invalid
}
func addProvider(tunnelsTableViewController: TunnelsTableViewController) {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from file or archive", comment: ""), style: .default) { [unowned self] _ in
self.addProviderFromFile()
})
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from QR code", comment: ""), style: .default) { [unowned self] _ in
self.addProviderWithQRScan()
})
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from scratch", comment: ""), style: .default) { [unowned self] _ in
self.addProviderManually()
})
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel))
tunnelsTableViewController.present(actionSheet, animated: true, completion: nil)
}
func addProviderFromFile() {
let documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypeZipArchive), "com.wireguard.config.quick"], in: .import)
documentPickerController.delegate = documentPickerDelegateObject
tunnelsTableViewController.present(documentPickerController, animated: true, completion: nil)
}
func addProviderManually() {
let addContext = persistentContainer.newBackgroundContext()
showTunnelConfigurationViewController(tunnel: nil, context: addContext)
}
func addProviderWithQRScan() {
let addContext = persistentContainer.newBackgroundContext()
let qrScanViewController = storyboard.instantiateViewController(type: QRScanViewController.self)
qrScanViewController.configure(context: addContext, delegate: self)
self.navigationController.pushViewController(qrScanViewController, animated: true)
}
func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
_ = refreshProviderManagers().then { () -> Promise<Void> in
let manager = self.providerManager(for: tunnel)!
let block = {
switch manager.connection.status {
case .invalid, .disconnected:
self.connect(tunnel: tunnel)
default:
break
}
}
if manager.connection.status == .invalid {
manager.loadFromPreferences { (_) in
block()
}
} else {
block()
}
return Promise.value(())
}
}
func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
_ = refreshProviderManagers().then { () -> Promise<Void> in
let manager = self.providerManager(for: tunnel)!
let block = {
switch manager.connection.status {
case .connected, .connecting:
self.disconnect(tunnel: tunnel)
default:
break
}
}
if manager.connection.status == .invalid {
manager.loadFromPreferences { (_) in
block()
}
} else {
block()
}
return Promise.value(())
}
}
private func connect(tunnel: Tunnel) {
os_log("connect tunnel: %{public}@", log: Log.general, type: .info, tunnel.description)
// Should the manager be enabled?
let manager = providerManager(for: tunnel)
manager?.isEnabled = true
manager?.saveToPreferences { (error) in
if let error = error {
os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
return
}
os_log("saved preferences", log: Log.general, type: .info)
let session = manager?.connection as! NETunnelProviderSession //swiftlint:disable:this force_cast
do {
try session.startTunnel()
} catch let error {
os_log("error starting tunnel: %{public}@", log: Log.general, type: .error, error.localizedDescription)
}
}
}
func disconnect(tunnel: Tunnel) {
let manager = providerManager(for: tunnel)
manager?.connection.stopVPNTunnel()
}
func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
print("info tunnel \(tunnel)")
showTunnelInfoViewController(tunnel: tunnel, context: self.persistentContainer.viewContext)
}
func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
print("delete tunnel \(tunnel)")
if let moc = tunnel.managedObjectContext {
moc.perform {
moc.delete(tunnel)
moc.saveContextToStore()
}
let manager = providerManager(for: tunnel)
manager?.removeFromPreferences { (error) in
if let error = error {
os_log("error removing preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
return
}
self.providerManagers?.removeAll { $0 == manager }
os_log("removed preferences", log: Log.general, type: .info)
}
}
}
private func providerManager(for tunnel: Tunnel) -> NETunnelProviderManager? {
return self.providerManagers?.first {
guard let prot = $0.protocolConfiguration as? NETunnelProviderProtocol else {
return false
}
guard let tunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else {
return false
}
return tunnelIdentifier == tunnel.tunnelIdentifier
}
}
func saveTunnel(_ tunnel: Tunnel) {
let manager = providerManager(for: tunnel) ?? NETunnelProviderManager()
manager.localizedDescription = tunnel.title
let protocolConfiguration = NETunnelProviderProtocol()
protocolConfiguration.providerBundleIdentifier = VPNBUNDLE
protocolConfiguration.serverAddress = (tunnel.peers?.array as? [Peer])?.compactMap { $0.endpoint}.joined(separator: ", ")
protocolConfiguration.providerConfiguration = tunnel.generateProviderConfiguration()
manager.protocolConfiguration = protocolConfiguration
let connectRule = NEOnDemandRuleConnect()
connectRule.interfaceTypeMatch = .any
manager.onDemandRules = [connectRule]
manager.saveToPreferences { (error) in
if let error = error {
os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
return
}
os_log("saved preferences", log: Log.general, type: .info)
}
_ = refreshProviderManagers().then { () -> Promise<Void> in
self.navigationController.popViewController(animated: true)
return Promise.value(())
}
}
}

View File

@ -27,7 +27,7 @@ class AppCoordinator: RootViewCoordinator {
let persistentContainer = NSPersistentContainer(name: "WireGuard")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var providerManagers: [NETunnelProviderManager]?
private let documentPickerDelegate: AppDocumentPickerDelegate
let documentPickerDelegateObject: AppDocumentPickerDelegate
// MARK: - Properties
@ -54,8 +54,8 @@ class AppCoordinator: RootViewCoordinator {
self.window.rootViewController = self.navigationController
self.window.makeKeyAndVisible()
documentPickerDelegate = AppDocumentPickerDelegate()
documentPickerDelegate.appCoordinator = self
documentPickerDelegateObject = AppDocumentPickerDelegate()
documentPickerDelegateObject.appCoordinator = self
NotificationCenter.default.addObserver(self,
selector: #selector(VPNStatusDidChange(notification:)),
@ -315,227 +315,6 @@ class AppCoordinator: RootViewCoordinator {
}
}
extension AppCoordinator: TunnelInfoTableViewControllerDelegate {
func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) {
print("configure tunnel \(tunnel)")
let editContext = persistentContainer.newBackgroundContext()
var backgroundTunnel: Tunnel?
editContext.performAndWait {
backgroundTunnel = editContext.object(with: tunnel.objectID) as? Tunnel
}
showTunnelConfigurationViewController(tunnel: backgroundTunnel, context: editContext)
}
}
extension AppCoordinator: TunnelsTableViewControllerDelegate {
func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
return session?.status ?? .invalid
}
func addProvider(tunnelsTableViewController: TunnelsTableViewController) {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Add from File", comment: ""), style: .default) { [unowned self] _ in
self.addProviderFromFile()
})
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Add Manually", comment: ""), style: .default) { [unowned self] _ in
self.addProviderManually()
})
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Scan QR Code", comment: ""), style: .default) { [unowned self] _ in
self.addProviderWithQRScan()
})
actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel))
tunnelsTableViewController.present(actionSheet, animated: true, completion: nil)
}
func addProviderFromFile() {
let documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypeZipArchive), "com.wireguard.config.quick"], in: .import)
documentPickerController.delegate = documentPickerDelegate
tunnelsTableViewController.present(documentPickerController, animated: true, completion: nil)
}
func addProviderManually() {
let addContext = persistentContainer.newBackgroundContext()
showTunnelConfigurationViewController(tunnel: nil, context: addContext)
}
func addProviderWithQRScan() {
let addContext = persistentContainer.newBackgroundContext()
let qrScanViewController = storyboard.instantiateViewController(type: QRScanViewController.self)
qrScanViewController.configure(context: addContext, delegate: self)
self.navigationController.pushViewController(qrScanViewController, animated: true)
}
func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
_ = refreshProviderManagers().then { () -> Promise<Void> in
let manager = self.providerManager(for: tunnel)!
let block = {
switch manager.connection.status {
case .invalid, .disconnected:
self.connect(tunnel: tunnel)
default:
break
}
}
if manager.connection.status == .invalid {
manager.loadFromPreferences { (_) in
block()
}
} else {
block()
}
return Promise.value(())
}
}
func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
_ = refreshProviderManagers().then { () -> Promise<Void> in
let manager = self.providerManager(for: tunnel)!
let block = {
switch manager.connection.status {
case .connected, .connecting:
self.disconnect(tunnel: tunnel)
default:
break
}
}
if manager.connection.status == .invalid {
manager.loadFromPreferences { (_) in
block()
}
} else {
block()
}
return Promise.value(())
}
}
private func connect(tunnel: Tunnel) {
os_log("connect tunnel: %{public}@", log: Log.general, type: .info, tunnel.description)
// Should the manager be enabled?
let manager = providerManager(for: tunnel)
manager?.isEnabled = true
manager?.saveToPreferences { (error) in
if let error = error {
os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
return
}
os_log("saved preferences", log: Log.general, type: .info)
let session = manager?.connection as! NETunnelProviderSession //swiftlint:disable:this force_cast
do {
try session.startTunnel()
} catch let error {
os_log("error starting tunnel: %{public}@", log: Log.general, type: .error, error.localizedDescription)
}
}
}
func disconnect(tunnel: Tunnel) {
let manager = providerManager(for: tunnel)
manager?.connection.stopVPNTunnel()
}
func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
print("info tunnel \(tunnel)")
showTunnelInfoViewController(tunnel: tunnel, context: self.persistentContainer.viewContext)
}
func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
print("delete tunnel \(tunnel)")
if let moc = tunnel.managedObjectContext {
moc.perform {
moc.delete(tunnel)
moc.saveContextToStore()
}
let manager = providerManager(for: tunnel)
manager?.removeFromPreferences { (error) in
if let error = error {
os_log("error removing preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
return
}
self.providerManagers?.removeAll { $0 == manager }
os_log("removed preferences", log: Log.general, type: .info)
}
}
}
private func providerManager(for tunnel: Tunnel) -> NETunnelProviderManager? {
return self.providerManagers?.first {
guard let prot = $0.protocolConfiguration as? NETunnelProviderProtocol else {
return false
}
guard let tunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else {
return false
}
return tunnelIdentifier == tunnel.tunnelIdentifier
}
}
private func saveTunnel(_ tunnel: Tunnel) {
let manager = providerManager(for: tunnel) ?? NETunnelProviderManager()
manager.localizedDescription = tunnel.title
let protocolConfiguration = NETunnelProviderProtocol()
protocolConfiguration.providerBundleIdentifier = VPNBUNDLE
protocolConfiguration.serverAddress = (tunnel.peers?.array as? [Peer])?.compactMap { $0.endpoint}.joined(separator: ", ")
protocolConfiguration.providerConfiguration = tunnel.generateProviderConfiguration()
manager.protocolConfiguration = protocolConfiguration
let connectRule = NEOnDemandRuleConnect()
connectRule.interfaceTypeMatch = .any
manager.onDemandRules = [connectRule]
manager.saveToPreferences { (error) in
if let error = error {
os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
return
}
os_log("saved preferences", log: Log.general, type: .info)
}
_ = refreshProviderManagers().then { () -> Promise<Void> in
self.navigationController.popViewController(animated: true)
return Promise.value(())
}
}
}
extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
saveTunnel(tunnel)
}
}
extension AppCoordinator: QRScanViewControllerDelegate {
func didSave(tunnel: Tunnel, qrScanViewController: QRScanViewController) {
qrScanViewController.navigationController?.popViewController(animated: true)
showTunnelInfoViewController(tunnel: tunnel, context: tunnel.managedObjectContext!)
}
func didCancel(qrScanViewController: QRScanViewController) {
qrScanViewController.navigationController?.popViewController(animated: true)
}
}
extension AppCoordinator: SettingsTableViewControllerDelegate {
func exportTunnels(settingsTableViewController: SettingsTableViewController, sourceView: UIView) {
self.exportConfigs(sourceView: sourceView)
}
}
class AppDocumentPickerDelegate: NSObject, UIDocumentPickerDelegate {
weak var appCoordinator: AppCoordinator?