Merge branch 'minor-cosmetic-fixes'
This commit is contained in:
commit
aeb042b225
|
@ -382,14 +382,14 @@ extension OrganizerViewController {
|
||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
private func profileKey(at indexPath: IndexPath) -> ConnectionService.ProfileKey {
|
private func profileKey(at indexPath: IndexPath) -> ProfileKey {
|
||||||
let section = model.section(for: indexPath.section)
|
let section = model.section(for: indexPath.section)
|
||||||
switch section {
|
switch section {
|
||||||
case .providers:
|
case .providers:
|
||||||
return ConnectionService.ProfileKey(.provider, providers[indexPath.row])
|
return ProfileKey(.provider, providers[indexPath.row])
|
||||||
|
|
||||||
case .hosts:
|
case .hosts:
|
||||||
return ConnectionService.ProfileKey(.host, hosts[indexPath.row])
|
return ProfileKey(.host, hosts[indexPath.row])
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatalError("Profile found in unexpected section: \(section)")
|
fatalError("Profile found in unexpected section: \(section)")
|
||||||
|
@ -450,7 +450,7 @@ extension OrganizerViewController: ConnectionServiceDelegate {
|
||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectionService(didRemoveProfileWithKey key: ConnectionService.ProfileKey) {
|
func connectionService(didRemoveProfileWithKey key: ProfileKey) {
|
||||||
TransientStore.shared.serialize(withProfiles: false) // delete
|
TransientStore.shared.serialize(withProfiles: false) // delete
|
||||||
|
|
||||||
splitViewController?.serviceViewController?.hideProfileIfDeleted()
|
splitViewController?.serviceViewController?.hideProfileIfDeleted()
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
0E5E5DE521511C5F00E318A3 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */; };
|
0E5E5DE521511C5F00E318A3 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */; };
|
||||||
0E6BE13A20CFB76800A6DD36 /* ApplicationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */; };
|
0E6BE13A20CFB76800A6DD36 /* ApplicationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */; };
|
||||||
0E6BE13F20CFBAB300A6DD36 /* DebugLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */; };
|
0E6BE13F20CFBAB300A6DD36 /* DebugLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */; };
|
||||||
|
0E79D13F21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */; };
|
||||||
|
0E79D14121919F5600BB5FB2 /* ProfileKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79D14021919F5600BB5FB2 /* ProfileKey.swift */; };
|
||||||
0E89DFC5213DF7AE00741BA1 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC4213DF7AE00741BA1 /* Preferences.swift */; };
|
0E89DFC5213DF7AE00741BA1 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC4213DF7AE00741BA1 /* Preferences.swift */; };
|
||||||
0E89DFC8213E8FC500741BA1 /* SessionProxy+Communication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */; };
|
0E89DFC8213E8FC500741BA1 /* SessionProxy+Communication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */; };
|
||||||
0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; };
|
0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; };
|
||||||
|
@ -162,6 +164,8 @@
|
||||||
0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GracefulVPN.swift; sourceTree = "<group>"; };
|
0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GracefulVPN.swift; sourceTree = "<group>"; };
|
||||||
0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationError.swift; sourceTree = "<group>"; };
|
0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationError.swift; sourceTree = "<group>"; };
|
||||||
0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugLogViewController.swift; sourceTree = "<group>"; };
|
0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugLogViewController.swift; sourceTree = "<group>"; };
|
||||||
|
0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderConnectionProfile.swift; sourceTree = "<group>"; };
|
||||||
|
0E79D14021919F5600BB5FB2 /* ProfileKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileKey.swift; sourceTree = "<group>"; };
|
||||||
0E89DFC4213DF7AE00741BA1 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
|
0E89DFC4213DF7AE00741BA1 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
|
||||||
0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+Communication.swift"; sourceTree = "<group>"; };
|
0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+Communication.swift"; sourceTree = "<group>"; };
|
||||||
0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardProviderViewController.swift; sourceTree = "<group>"; };
|
0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardProviderViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -368,6 +372,8 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
0EBE3AA3213DC1B000BFA2F5 /* HostConnectionProfile.swift */,
|
0EBE3AA3213DC1B000BFA2F5 /* HostConnectionProfile.swift */,
|
||||||
|
0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */,
|
||||||
|
0E79D14021919F5600BB5FB2 /* ProfileKey.swift */,
|
||||||
0EBE3AA4213DC1B000BFA2F5 /* ProviderConnectionProfile.swift */,
|
0EBE3AA4213DC1B000BFA2F5 /* ProviderConnectionProfile.swift */,
|
||||||
);
|
);
|
||||||
path = Profiles;
|
path = Profiles;
|
||||||
|
@ -834,6 +840,7 @@
|
||||||
0E39BCF3214DA9310035E9DE /* AppConstants.swift in Sources */,
|
0E39BCF3214DA9310035E9DE /* AppConstants.swift in Sources */,
|
||||||
0E05C5D620D1645F006EE732 /* SwiftGen+Scenes.swift in Sources */,
|
0E05C5D620D1645F006EE732 /* SwiftGen+Scenes.swift in Sources */,
|
||||||
0E2B494220FD16540094784C /* TransientStore.swift in Sources */,
|
0E2B494220FD16540094784C /* TransientStore.swift in Sources */,
|
||||||
|
0E79D14121919F5600BB5FB2 /* ProfileKey.swift in Sources */,
|
||||||
0E89DFC5213DF7AE00741BA1 /* Preferences.swift in Sources */,
|
0E89DFC5213DF7AE00741BA1 /* Preferences.swift in Sources */,
|
||||||
0E6BE13A20CFB76800A6DD36 /* ApplicationError.swift in Sources */,
|
0E6BE13A20CFB76800A6DD36 /* ApplicationError.swift in Sources */,
|
||||||
0EFD9440215BED8E00529B64 /* LabelViewController.swift in Sources */,
|
0EFD9440215BED8E00529B64 /* LabelViewController.swift in Sources */,
|
||||||
|
@ -866,6 +873,7 @@
|
||||||
0ED38AE721404F100004D387 /* EndpointDataSource.swift in Sources */,
|
0ED38AE721404F100004D387 /* EndpointDataSource.swift in Sources */,
|
||||||
0E8D97E221388B52006FB4A0 /* InfrastructurePreset.swift in Sources */,
|
0E8D97E221388B52006FB4A0 /* InfrastructurePreset.swift in Sources */,
|
||||||
0ED31C3720CF38D10027975F /* VPN.swift in Sources */,
|
0ED31C3720CF38D10027975F /* VPN.swift in Sources */,
|
||||||
|
0E79D13F21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift in Sources */,
|
||||||
0ED31C2920CF2A340027975F /* AccountViewController.swift in Sources */,
|
0ED31C2920CF2A340027975F /* AccountViewController.swift in Sources */,
|
||||||
0E5E5DE521511C5F00E318A3 /* GracefulVPN.swift in Sources */,
|
0E5E5DE521511C5F00E318A3 /* GracefulVPN.swift in Sources */,
|
||||||
0E158ADA20E11B0B00C85A82 /* EndpointViewController.swift in Sources */,
|
0E158ADA20E11B0B00C85A82 /* EndpointViewController.swift in Sources */,
|
||||||
|
@ -1133,7 +1141,7 @@
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout-iOS.app/Passepartout-iOS";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout.app/Passepartout";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
@ -1155,7 +1163,7 @@
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout-iOS.app/Passepartout-iOS";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passepartout.app/Passepartout";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
"global.ok" = "OK";
|
"global.ok" = "OK";
|
||||||
"global.cancel" = "Cancel";
|
"global.cancel" = "Cancel";
|
||||||
"global.next" = "Next";
|
"global.next" = "Next";
|
||||||
"global.host.title_input.message" = "Legal characters are alphanumerics plus dash (-), underscore (_) and dot (.).";
|
"global.host.title_input.message" = "Acceptable characters are alphanumerics plus dash \"-\", underscore \"_\" and dot \".\".";
|
||||||
"global.host.title_input.placeholder" = "My Profile";
|
"global.host.title_input.placeholder" = "My Profile";
|
||||||
|
|
||||||
"reddit.title" = "Reddit";
|
"reddit.title" = "Reddit";
|
||||||
|
|
|
@ -83,6 +83,6 @@ extension ConnectionProfile {
|
||||||
|
|
||||||
extension ConnectionProfile {
|
extension ConnectionProfile {
|
||||||
var description: String {
|
var description: String {
|
||||||
return "[\(context):\(id)]"
|
return "(\(context),\(id))"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ protocol ConnectionServiceDelegate: class {
|
||||||
|
|
||||||
func connectionService(didRename oldProfile: ConnectionProfile, to newProfile: ConnectionProfile)
|
func connectionService(didRename oldProfile: ConnectionProfile, to newProfile: ConnectionProfile)
|
||||||
|
|
||||||
func connectionService(didRemoveProfileWithKey key: ConnectionService.ProfileKey)
|
func connectionService(didRemoveProfileWithKey key: ProfileKey)
|
||||||
|
|
||||||
func connectionService(willDeactivate profile: ConnectionProfile)
|
func connectionService(willDeactivate profile: ConnectionProfile)
|
||||||
|
|
||||||
|
@ -55,40 +55,6 @@ class ConnectionService: Codable {
|
||||||
case preferences
|
case preferences
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProfileKey: RawRepresentable, Hashable, Codable {
|
|
||||||
let context: Context
|
|
||||||
|
|
||||||
let id: String
|
|
||||||
|
|
||||||
init(_ context: Context, _ id: String) {
|
|
||||||
self.context = context
|
|
||||||
self.id = id
|
|
||||||
}
|
|
||||||
|
|
||||||
init(_ profile: ConnectionProfile) {
|
|
||||||
context = profile.context
|
|
||||||
id = profile.id
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: RawRepresentable
|
|
||||||
|
|
||||||
var rawValue: String {
|
|
||||||
return "\(context).\(id)"
|
|
||||||
}
|
|
||||||
|
|
||||||
init?(rawValue: String) {
|
|
||||||
let comps = rawValue.components(separatedBy: ".")
|
|
||||||
guard comps.count == 2 else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
guard let context = Context(rawValue: comps[0]) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
self.context = context
|
|
||||||
id = comps[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var directory: String? = nil
|
var directory: String? = nil
|
||||||
|
|
||||||
var rootURL: URL {
|
var rootURL: URL {
|
||||||
|
@ -209,7 +175,7 @@ class ConnectionService: Codable {
|
||||||
cache[key] = PlaceholderConnectionProfile(key)
|
cache[key] = PlaceholderConnectionProfile(key)
|
||||||
}
|
}
|
||||||
} catch let e {
|
} catch let e {
|
||||||
log.error("Could not list provider contents: \(e) (\(providersURL))")
|
log.warning("Could not list provider contents: \(e) (\(providersURL))")
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
let files = try fm.contentsOfDirectory(at: hostsURL, includingPropertiesForKeys: nil, options: [])
|
let files = try fm.contentsOfDirectory(at: hostsURL, includingPropertiesForKeys: nil, options: [])
|
||||||
|
@ -222,7 +188,7 @@ class ConnectionService: Codable {
|
||||||
cache[key] = PlaceholderConnectionProfile(key)
|
cache[key] = PlaceholderConnectionProfile(key)
|
||||||
}
|
}
|
||||||
} catch let e {
|
} catch let e {
|
||||||
log.error("Could not list host contents: \(e) (\(hostsURL))")
|
log.warning("Could not list host contents: \(e) (\(hostsURL))")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,38 +504,3 @@ class ConnectionService: Codable {
|
||||||
// defaults.removeObject(forKey: Keys.vpnLog)
|
// defaults.removeObject(forKey: Keys.vpnLog)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PlaceholderConnectionProfile: ConnectionProfile {
|
|
||||||
let context: Context
|
|
||||||
|
|
||||||
let id: String
|
|
||||||
|
|
||||||
var username: String? = nil
|
|
||||||
|
|
||||||
var requiresCredentials: Bool = false
|
|
||||||
|
|
||||||
func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
|
||||||
fatalError("Generating configuration from a PlaceholderConnectionProfile")
|
|
||||||
}
|
|
||||||
|
|
||||||
func with(newId: String) -> ConnectionProfile {
|
|
||||||
return PlaceholderConnectionProfile(ConnectionService.ProfileKey(context, newId))
|
|
||||||
}
|
|
||||||
|
|
||||||
var mainAddress: String = ""
|
|
||||||
|
|
||||||
var addresses: [String] = []
|
|
||||||
|
|
||||||
var protocols: [TunnelKitProvider.EndpointProtocol] = []
|
|
||||||
|
|
||||||
var canCustomizeEndpoint: Bool = false
|
|
||||||
|
|
||||||
var customAddress: String?
|
|
||||||
|
|
||||||
var customProtocol: TunnelKitProvider.EndpointProtocol?
|
|
||||||
|
|
||||||
init(_ key: ConnectionService.ProfileKey) {
|
|
||||||
self.context = key.context
|
|
||||||
self.id = key.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// PlaceholderConnectionProfile.swift
|
||||||
|
// Passepartout
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 11/6/18.
|
||||||
|
// Copyright (c) 2018 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
// https://github.com/passepartoutvpn
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import TunnelKit
|
||||||
|
|
||||||
|
class PlaceholderConnectionProfile: ConnectionProfile {
|
||||||
|
let context: Context
|
||||||
|
|
||||||
|
let id: String
|
||||||
|
|
||||||
|
var username: String? = nil
|
||||||
|
|
||||||
|
var requiresCredentials: Bool = false
|
||||||
|
|
||||||
|
func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
|
||||||
|
fatalError("Generating configuration from a PlaceholderConnectionProfile")
|
||||||
|
}
|
||||||
|
|
||||||
|
func with(newId: String) -> ConnectionProfile {
|
||||||
|
return PlaceholderConnectionProfile(context, newId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mainAddress: String = ""
|
||||||
|
|
||||||
|
var addresses: [String] = []
|
||||||
|
|
||||||
|
var protocols: [TunnelKitProvider.EndpointProtocol] = []
|
||||||
|
|
||||||
|
var canCustomizeEndpoint: Bool = false
|
||||||
|
|
||||||
|
var customAddress: String?
|
||||||
|
|
||||||
|
var customProtocol: TunnelKitProvider.EndpointProtocol?
|
||||||
|
|
||||||
|
init(_ context: Context, _ id: String) {
|
||||||
|
self.context = context
|
||||||
|
self.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_ key: ProfileKey) {
|
||||||
|
context = key.context
|
||||||
|
id = key.id
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
//
|
||||||
|
// ProfileKey.swift
|
||||||
|
// Passepartout
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 11/6/18.
|
||||||
|
// Copyright (c) 2018 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
// https://github.com/passepartoutvpn
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct ProfileKey: RawRepresentable, Hashable, Codable {
|
||||||
|
let context: Context
|
||||||
|
|
||||||
|
let id: String
|
||||||
|
|
||||||
|
init(_ context: Context, _ id: String) {
|
||||||
|
self.context = context
|
||||||
|
self.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_ profile: ConnectionProfile) {
|
||||||
|
context = profile.context
|
||||||
|
id = profile.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: RawRepresentable
|
||||||
|
|
||||||
|
var rawValue: String {
|
||||||
|
return "\(context).\(id)"
|
||||||
|
}
|
||||||
|
|
||||||
|
init?(rawValue: String) {
|
||||||
|
let comps = rawValue.components(separatedBy: ".")
|
||||||
|
guard comps.count == 2 else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard let context = Context(rawValue: comps[0]) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
self.context = context
|
||||||
|
id = comps[1]
|
||||||
|
}
|
||||||
|
}
|
|
@ -245,7 +245,7 @@ internal enum L10n {
|
||||||
internal static let ok = L10n.tr("Localizable", "global.ok")
|
internal static let ok = L10n.tr("Localizable", "global.ok")
|
||||||
internal enum Host {
|
internal enum Host {
|
||||||
internal enum TitleInput {
|
internal enum TitleInput {
|
||||||
/// Legal characters are alphanumerics plus dash (-), underscore (_) and dot (.).
|
/// Acceptable characters are alphanumerics plus dash "-", underscore "_" and dot ".".
|
||||||
internal static let message = L10n.tr("Localizable", "global.host.title_input.message")
|
internal static let message = L10n.tr("Localizable", "global.host.title_input.message")
|
||||||
/// My Profile
|
/// My Profile
|
||||||
internal static let placeholder = L10n.tr("Localizable", "global.host.title_input.placeholder")
|
internal static let placeholder = L10n.tr("Localizable", "global.host.title_input.placeholder")
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
import TunnelKit
|
import TunnelKit
|
||||||
@testable import Passepartout_iOS
|
@testable import Passepartout
|
||||||
|
|
||||||
class ConnectionServiceTests: XCTestCase {
|
class ConnectionServiceTests: XCTestCase {
|
||||||
let url = Bundle(for: ConnectionServiceTests.self).url(forResource: "ConnectionService", withExtension: "json")!
|
let url = Bundle(for: ConnectionServiceTests.self).url(forResource: "ConnectionService", withExtension: "json")!
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
import TunnelKit
|
import TunnelKit
|
||||||
@testable import Passepartout_iOS
|
@testable import Passepartout
|
||||||
|
|
||||||
class FileConfigurationTests: XCTestCase {
|
class FileConfigurationTests: XCTestCase {
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
@testable import Passepartout_iOS
|
@testable import Passepartout
|
||||||
import TunnelKit
|
import TunnelKit
|
||||||
|
|
||||||
class InfrastructureTests: XCTestCase {
|
class InfrastructureTests: XCTestCase {
|
||||||
|
|
|
@ -100,7 +100,7 @@ It's highly recommended to use the Git and Ruby packages provided by [Homebrew][
|
||||||
|
|
||||||
Download the app codebase locally:
|
Download the app codebase locally:
|
||||||
|
|
||||||
$ git clone https://github.com/keeshux/passepartout-ios.git
|
$ git clone https://github.com/passepartoutvpn/passepartout-ios.git
|
||||||
|
|
||||||
Assuming you have a [working CocoaPods environment][dep-cocoapods], setting up the app workspace only requires installing the pod dependencies:
|
Assuming you have a [working CocoaPods environment][dep-cocoapods], setting up the app workspace only requires installing the pod dependencies:
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ Website: [passepartoutvpn.app][about-website]
|
||||||
|
|
||||||
[openvpn]: https://openvpn.net/index.php/open-source/overview.html
|
[openvpn]: https://openvpn.net/index.php/open-source/overview.html
|
||||||
|
|
||||||
[app-api]: https://github.com/keeshux/passepartout-api
|
[app-api]: https://github.com/passepartoutvpn/passepartout-api
|
||||||
[app-net-pia]: https://www.privateinternetaccess.com
|
[app-net-pia]: https://www.privateinternetaccess.com
|
||||||
|
|
||||||
[dep-cocoapods]: https://guides.cocoapods.org/using/getting-started.html
|
[dep-cocoapods]: https://guides.cocoapods.org/using/getting-started.html
|
||||||
|
|
Loading…
Reference in New Issue