Add import and export logic.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
4950254013
commit
2572c4781c
Binary file not shown.
After Width: | Height: | Size: 730 B |
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
48CF751B34E9703133F1B1AF /* Pods_WireGuard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 861983CAE8FDC13BC83E7E04 /* Pods_WireGuard.framework */; };
|
48CF751B34E9703133F1B1AF /* Pods_WireGuard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 861983CAE8FDC13BC83E7E04 /* Pods_WireGuard.framework */; };
|
||||||
|
4A430E802139DC8F0078172C /* icon_20pt@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4A430E7F2139DC8F0078172C /* icon_20pt@3x.png */; };
|
||||||
|
4A430E842139DCFB0078172C /* icon_60pt@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4A430E832139DCFB0078172C /* icon_60pt@3x.png */; };
|
||||||
4A4351592124956200261999 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4351582124956200261999 /* Validators.swift */; };
|
4A4351592124956200261999 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4351582124956200261999 /* Validators.swift */; };
|
||||||
4A43515A2124956200261999 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4351582124956200261999 /* Validators.swift */; };
|
4A43515A2124956200261999 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4351582124956200261999 /* Validators.swift */; };
|
||||||
4A43515C21249E5700261999 /* ValidatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A43515B21249E5700261999 /* ValidatorsTests.swift */; };
|
4A43515C21249E5700261999 /* ValidatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A43515B21249E5700261999 /* ValidatorsTests.swift */; };
|
||||||
|
@ -85,6 +87,9 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
0CE52E030FAA93F3BF5747B2 /* Pods-WireGuard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WireGuard.release.xcconfig"; path = "Pods/Target Support Files/Pods-WireGuard/Pods-WireGuard.release.xcconfig"; sourceTree = "<group>"; };
|
0CE52E030FAA93F3BF5747B2 /* Pods-WireGuard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WireGuard.release.xcconfig"; path = "Pods/Target Support Files/Pods-WireGuard/Pods-WireGuard.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
25E2BE31A33C8CCE6E79B6EF /* Pods-WireGuard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WireGuard.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WireGuard/Pods-WireGuard.debug.xcconfig"; sourceTree = "<group>"; };
|
25E2BE31A33C8CCE6E79B6EF /* Pods-WireGuard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WireGuard.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WireGuard/Pods-WireGuard.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
4A430E7F2139DC8F0078172C /* icon_20pt@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_20pt@3x.png"; sourceTree = "<group>"; };
|
||||||
|
4A430E812139DCCB0078172C /* icon_20pt.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_20pt.png; sourceTree = "<group>"; };
|
||||||
|
4A430E832139DCFB0078172C /* icon_60pt@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon_60pt@3x.png"; path = "WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png"; sourceTree = SOURCE_ROOT; };
|
||||||
4A4351582124956200261999 /* Validators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validators.swift; sourceTree = "<group>"; };
|
4A4351582124956200261999 /* Validators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validators.swift; sourceTree = "<group>"; };
|
||||||
4A43515B21249E5700261999 /* ValidatorsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorsTests.swift; sourceTree = "<group>"; };
|
4A43515B21249E5700261999 /* ValidatorsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorsTests.swift; sourceTree = "<group>"; };
|
||||||
4A4BA6D720B73CBA00223AB8 /* TunnelConfigurationTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelConfigurationTableViewController.swift; sourceTree = "<group>"; };
|
4A4BA6D720B73CBA00223AB8 /* TunnelConfigurationTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelConfigurationTableViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -223,6 +228,9 @@
|
||||||
4A4BAD0720B5F4BC00F12B28 /* Resources */ = {
|
4A4BAD0720B5F4BC00F12B28 /* Resources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4A430E7F2139DC8F0078172C /* icon_20pt@3x.png */,
|
||||||
|
4A430E812139DCCB0078172C /* icon_20pt.png */,
|
||||||
|
4A430E832139DCFB0078172C /* icon_60pt@3x.png */,
|
||||||
4A4BAD0520B5F4B500F12B28 /* Settings.bundle */,
|
4A4BAD0520B5F4B500F12B28 /* Settings.bundle */,
|
||||||
);
|
);
|
||||||
path = Resources;
|
path = Resources;
|
||||||
|
@ -468,6 +476,8 @@
|
||||||
files = (
|
files = (
|
||||||
4A4BAD0620B5F4B500F12B28 /* Settings.bundle in Resources */,
|
4A4BAD0620B5F4B500F12B28 /* Settings.bundle in Resources */,
|
||||||
4A4BACF020B5F1C100F12B28 /* LaunchScreen.storyboard in Resources */,
|
4A4BACF020B5F1C100F12B28 /* LaunchScreen.storyboard in Resources */,
|
||||||
|
4A430E842139DCFB0078172C /* icon_60pt@3x.png in Resources */,
|
||||||
|
4A430E802139DC8F0078172C /* icon_20pt@3x.png in Resources */,
|
||||||
4A4BACED20B5F1C100F12B28 /* Assets.xcassets in Resources */,
|
4A4BACED20B5F1C100F12B28 /* Assets.xcassets in Resources */,
|
||||||
4A4BACEB20B5F1BF00F12B28 /* Main.storyboard in Resources */,
|
4A4BACEB20B5F1BF00F12B28 /* Main.storyboard in Resources */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import os.log
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
@ -22,4 +23,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -> Bool {
|
||||||
|
defer {
|
||||||
|
do {
|
||||||
|
try FileManager.default.removeItem(at: url)
|
||||||
|
} catch {
|
||||||
|
os_log("Failed to remove item from Inbox: %{public}@", log: Log.general, type: .error, url.absoluteString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guard url.pathExtension == "conf" else { return false }
|
||||||
|
|
||||||
|
do {
|
||||||
|
try appCoordinator.importConfig(config: url)
|
||||||
|
} catch {
|
||||||
|
os_log("Unable to import config: %{public}@", log: Log.general, type: .error, url.absoluteString)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
<outlet property="delegate" destination="kTU-BV-32R" id="b6T-ZR-cmO"/>
|
<outlet property="delegate" destination="kTU-BV-32R" id="b6T-ZR-cmO"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<navigationItem key="navigationItem" title="WireGuard Tunnels" id="j0L-5U-jDs">
|
<navigationItem key="navigationItem" title="WireGuard Tunnels" largeTitleDisplayMode="always" id="j0L-5U-jDs">
|
||||||
<barButtonItem key="rightBarButtonItem" systemItem="add" id="h2H-H8-3Tn">
|
<barButtonItem key="rightBarButtonItem" systemItem="add" id="h2H-H8-3Tn">
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="addProvider:" destination="kTU-BV-32R" id="xSg-ap-3Fx"/>
|
<action selector="addProvider:" destination="kTU-BV-32R" id="xSg-ap-3Fx"/>
|
||||||
|
@ -486,14 +486,22 @@
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<navigationItem key="navigationItem" title="Tunnel settings" id="PPu-rX-T38">
|
<navigationItem key="navigationItem" title="Tunnel settings" id="PPu-rX-T38">
|
||||||
<barButtonItem key="rightBarButtonItem" systemItem="save" id="mft-1l-bWa">
|
<rightBarButtonItems>
|
||||||
<connections>
|
<barButtonItem systemItem="save" id="mft-1l-bWa">
|
||||||
<action selector="saveTunnelConfiguration:" destination="0VM-73-EPX" id="Hni-0w-hFF"/>
|
<connections>
|
||||||
</connections>
|
<action selector="saveTunnelConfiguration:" destination="0VM-73-EPX" id="Hni-0w-hFF"/>
|
||||||
</barButtonItem>
|
</connections>
|
||||||
|
</barButtonItem>
|
||||||
|
<barButtonItem systemItem="action" id="uim-Mz-omJ">
|
||||||
|
<connections>
|
||||||
|
<action selector="exportTunnel:" destination="0VM-73-EPX" id="oVI-TL-4o9"/>
|
||||||
|
</connections>
|
||||||
|
</barButtonItem>
|
||||||
|
</rightBarButtonItems>
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="exportButton" destination="uim-Mz-omJ" id="1Tq-ie-xo7"/>
|
||||||
<outlet property="saveButton" destination="mft-1l-bWa" id="Uif-KZ-isx"/>
|
<outlet property="saveButton" destination="mft-1l-bWa" id="Uif-KZ-isx"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
|
@ -524,7 +532,7 @@
|
||||||
</constraints>
|
</constraints>
|
||||||
<viewLayoutGuide key="safeArea" id="Soo-c9-MsX"/>
|
<viewLayoutGuide key="safeArea" id="Soo-c9-MsX"/>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" title="Scan Code" largeTitleDisplayMode="never" id="WGY-tY-ySz"/>
|
<navigationItem key="navigationItem" title="Scan Code" largeTitleDisplayMode="always" id="WGY-tY-ySz"/>
|
||||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="TQ2-zp-o40" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="TQ2-zp-o40" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
|
|
@ -13,6 +13,10 @@ import os.log
|
||||||
import CoreData
|
import CoreData
|
||||||
import BNRCoreDataStack
|
import BNRCoreDataStack
|
||||||
|
|
||||||
|
enum AppCoordinatorError: Error {
|
||||||
|
case configImportError(msg: String)
|
||||||
|
}
|
||||||
|
|
||||||
extension UINavigationController: Identifyable {}
|
extension UINavigationController: Identifyable {}
|
||||||
|
|
||||||
let APPGROUP = "group.com.wireguard.ios.WireGuard"
|
let APPGROUP = "group.com.wireguard.ios.WireGuard"
|
||||||
|
@ -92,6 +96,46 @@ class AppCoordinator: RootViewCoordinator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func importConfig(config: URL) throws {
|
||||||
|
do {
|
||||||
|
let configString = try String(contentsOf: config)
|
||||||
|
let addContext = persistentContainer.newBackgroundContext()
|
||||||
|
let tunnel = try Tunnel.fromConfig(configString, context: addContext)
|
||||||
|
let title = config.deletingPathExtension().lastPathComponent
|
||||||
|
tunnel.title = title
|
||||||
|
addContext.saveContext()
|
||||||
|
self.saveTunnel(tunnel)
|
||||||
|
} catch {
|
||||||
|
throw AppCoordinatorError.configImportError(msg: "Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func exportConfig(tunnel: Tunnel, barButtonItem: UIBarButtonItem) {
|
||||||
|
let exportString = tunnel.export()
|
||||||
|
|
||||||
|
guard let path = FileManager.default
|
||||||
|
.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let saveFileURL = path.appendingPathComponent("/\(tunnel.title ?? "wireguard").conf")
|
||||||
|
do {
|
||||||
|
try exportString.write(to: saveFileURL, atomically: true, encoding: .utf8)
|
||||||
|
} catch {
|
||||||
|
os_log("Failed to export tunnelto: %{public}@", log: Log.general, type: .error, saveFileURL.absoluteString)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let activityViewController = UIActivityViewController(
|
||||||
|
activityItems: [saveFileURL],
|
||||||
|
applicationActivities: nil)
|
||||||
|
if let popoverPresentationController = activityViewController.popoverPresentationController {
|
||||||
|
popoverPresentationController.barButtonItem = barButtonItem
|
||||||
|
}
|
||||||
|
self.navigationController.present(activityViewController, animated: true) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - NEVPNManager handling
|
// MARK: - NEVPNManager handling
|
||||||
|
|
||||||
@objc private func VPNStatusDidChange(notification: NSNotification) {
|
@objc private func VPNStatusDidChange(notification: NSNotification) {
|
||||||
|
@ -151,7 +195,6 @@ class AppCoordinator: RootViewCoordinator {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppCoordinator: TunnelsTableViewControllerDelegate {
|
extension AppCoordinator: TunnelsTableViewControllerDelegate {
|
||||||
|
|
||||||
func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
|
func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
|
||||||
let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
|
let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
|
||||||
return session?.status ?? .invalid
|
return session?.status ?? .invalid
|
||||||
|
@ -330,6 +373,10 @@ extension AppCoordinator: TunnelsTableViewControllerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
|
extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
|
||||||
|
func export(tunnel: Tunnel, barButtonItem: UIBarButtonItem) {
|
||||||
|
exportConfig(tunnel: tunnel, barButtonItem: barButtonItem)
|
||||||
|
}
|
||||||
|
|
||||||
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
|
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
|
||||||
saveTunnel(tunnel)
|
saveTunnel(tunnel)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,35 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Camera is used to scan QR codes</string>
|
<string>${PRODUCT_NAME}</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string></string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>icon_20pt</string>
|
||||||
|
<string>icon_20pt@3x</string>
|
||||||
|
<string>icon_60pt@3x</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>WireGuard configuration</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>com.wireguard.config.quick</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
@ -22,6 +47,12 @@
|
||||||
<string>auto-generated</string>
|
<string>auto-generated</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||||
|
<false/>
|
||||||
|
<key>UIFileSharingEnabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>Camera is used to scan QR codes</string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
@ -45,5 +76,51 @@
|
||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>UTExportedTypeDeclarations</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<string>conf</string>
|
||||||
|
</dict>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeDescription</key>
|
||||||
|
<string>WireGuard configuration</string>
|
||||||
|
<key>UTTypeIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>icon_20pt@3x</string>
|
||||||
|
<string>icon_60pt@3x</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>com.wireguard.config.quick</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>UTImportedTypeDeclarations</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<string>conf</string>
|
||||||
|
</dict>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeDescription</key>
|
||||||
|
<string>WireGuard configuration</string>
|
||||||
|
<key>UTTypeIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>icon_20pt@3x</string>
|
||||||
|
<string>icon_60pt@3x</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>com.wireguard.config.quick</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -13,11 +13,13 @@ import PromiseKit
|
||||||
|
|
||||||
protocol TunnelConfigurationTableViewControllerDelegate: class {
|
protocol TunnelConfigurationTableViewControllerDelegate: class {
|
||||||
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController)
|
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController)
|
||||||
|
func export(tunnel: Tunnel, barButtonItem: UIBarButtonItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TunnelConfigurationTableViewController: UITableViewController {
|
class TunnelConfigurationTableViewController: UITableViewController {
|
||||||
|
|
||||||
@IBOutlet weak var saveButton: UIBarButtonItem!
|
@IBOutlet weak var saveButton: UIBarButtonItem!
|
||||||
|
@IBOutlet weak var exportButton: UIBarButtonItem!
|
||||||
|
|
||||||
private var viewContext: NSManagedObjectContext!
|
private var viewContext: NSManagedObjectContext!
|
||||||
private weak var delegate: TunnelConfigurationTableViewControllerDelegate?
|
private weak var delegate: TunnelConfigurationTableViewControllerDelegate?
|
||||||
|
@ -61,6 +63,10 @@ class TunnelConfigurationTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction func exportTunnel(_ sender: UIBarButtonItem) {
|
||||||
|
self.delegate?.export(tunnel: tunnel, barButtonItem: sender)
|
||||||
|
}
|
||||||
|
|
||||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 730 B |
Loading…
Reference in New Issue