Merge pull request #46 from passepartoutvpn/edit-siri-shortcuts
Manage Siri shortcuts
This commit is contained in:
commit
a89b040c44
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Siri Shortcuts in-app manager. [#46](https://github.com/passepartoutvpn/passepartout-ios/pull/46)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- EKU not verified with providers (regression).
|
- EKU not verified with providers (regression).
|
||||||
|
|
|
@ -38,6 +38,8 @@ internal enum StoryboardScene {
|
||||||
internal static let storyboardName = "Shortcuts"
|
internal static let storyboardName = "Shortcuts"
|
||||||
|
|
||||||
internal static let initialScene = InitialSceneType<UIKit.UINavigationController>(storyboard: Shortcuts.self)
|
internal static let initialScene = InitialSceneType<UIKit.UINavigationController>(storyboard: Shortcuts.self)
|
||||||
|
|
||||||
|
internal static let shortcutsViewController = SceneType<UIKit.UINavigationController>(storyboard: Shortcuts.self, identifier: "ShortcutsViewController")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||||
|
|
|
@ -32,6 +32,7 @@ internal enum StoryboardSegue {
|
||||||
internal enum Shortcuts: String, SegueType {
|
internal enum Shortcuts: String, SegueType {
|
||||||
case connectToSegueIdentifier = "ConnectToSegueIdentifier"
|
case connectToSegueIdentifier = "ConnectToSegueIdentifier"
|
||||||
case pickLocationSegueIdentifier = "PickLocationSegueIdentifier"
|
case pickLocationSegueIdentifier = "PickLocationSegueIdentifier"
|
||||||
|
case shortcutAddSegueIdentifier = "ShortcutAddSegueIdentifier"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
//
|
||||||
|
// ShortcutsAddViewController.swift
|
||||||
|
// Passepartout-iOS
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 3/18/19.
|
||||||
|
// Copyright (c) 2019 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 UIKit
|
||||||
|
import Intents
|
||||||
|
import Passepartout_Core
|
||||||
|
|
||||||
|
@available(iOS 12, *)
|
||||||
|
class ShortcutsAddViewController: UITableViewController, TableModelHost {
|
||||||
|
weak var delegate: ShortcutsIntentDelegate?
|
||||||
|
|
||||||
|
// MARK: TableModel
|
||||||
|
|
||||||
|
let model: TableModel<SectionType, RowType> = {
|
||||||
|
let model: TableModel<SectionType, RowType> = TableModel()
|
||||||
|
model.add(.vpn)
|
||||||
|
model.add(.wifi)
|
||||||
|
model.add(.cellular)
|
||||||
|
model.set([.connect, .enableVPN, .disableVPN], in: .vpn)
|
||||||
|
model.set([.trustCurrentWiFi, .untrustCurrentWiFi], in: .wifi)
|
||||||
|
model.set([.trustCellular, .untrustCellular], in: .cellular)
|
||||||
|
model.setHeader(L10n.Shortcuts.Add.Sections.Vpn.header, for: .vpn)
|
||||||
|
model.setHeader(L10n.Shortcuts.Add.Sections.Wifi.header, for: .wifi)
|
||||||
|
model.setHeader(L10n.Shortcuts.Add.Sections.Cellular.header, for: .cellular)
|
||||||
|
return model
|
||||||
|
}()
|
||||||
|
|
||||||
|
func reloadModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: UIViewController
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
title = L10n.Shortcuts.Add.title
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: UITableViewController
|
||||||
|
|
||||||
|
enum SectionType {
|
||||||
|
case vpn
|
||||||
|
|
||||||
|
case wifi
|
||||||
|
|
||||||
|
case cellular
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RowType {
|
||||||
|
case connect // host or provider+location
|
||||||
|
|
||||||
|
case enableVPN
|
||||||
|
|
||||||
|
case disableVPN
|
||||||
|
|
||||||
|
case trustCurrentWiFi
|
||||||
|
|
||||||
|
case untrustCurrentWiFi
|
||||||
|
|
||||||
|
case trustCellular
|
||||||
|
|
||||||
|
case untrustCellular
|
||||||
|
}
|
||||||
|
|
||||||
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
return model.count
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||||
|
return model.header(for: section)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return model.count(for: section)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
||||||
|
switch model.row(at: indexPath) {
|
||||||
|
case .connect:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.Connect.caption
|
||||||
|
|
||||||
|
case .enableVPN:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.EnableVpn.caption
|
||||||
|
|
||||||
|
case .disableVPN:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.DisableVpn.caption
|
||||||
|
|
||||||
|
case .trustCurrentWiFi:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.TrustCurrentWifi.caption
|
||||||
|
|
||||||
|
case .untrustCurrentWiFi:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.UntrustCurrentWifi.caption
|
||||||
|
|
||||||
|
case .trustCellular:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.TrustCellular.caption
|
||||||
|
|
||||||
|
case .untrustCellular:
|
||||||
|
cell.leftText = L10n.Shortcuts.Add.Cells.UntrustCellular.caption
|
||||||
|
}
|
||||||
|
cell.apply(Theme.current)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
switch model.row(at: indexPath) {
|
||||||
|
case .connect:
|
||||||
|
addConnect()
|
||||||
|
|
||||||
|
case .enableVPN:
|
||||||
|
addEnable()
|
||||||
|
|
||||||
|
case .disableVPN:
|
||||||
|
addDisable()
|
||||||
|
|
||||||
|
case .trustCurrentWiFi:
|
||||||
|
addTrustWiFi()
|
||||||
|
|
||||||
|
case .untrustCurrentWiFi:
|
||||||
|
addUntrustWiFi()
|
||||||
|
|
||||||
|
case .trustCellular:
|
||||||
|
addTrustCellular()
|
||||||
|
|
||||||
|
case .untrustCellular:
|
||||||
|
addUntrustCellular()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Actions
|
||||||
|
|
||||||
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||||
|
if let vc = segue.destination as? ShortcutsConnectToViewController {
|
||||||
|
vc.delegate = delegate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addConnect() {
|
||||||
|
guard TransientStore.shared.service.hasProfiles() else {
|
||||||
|
let alert = Macros.alert(
|
||||||
|
L10n.Shortcuts.Add.Cells.Connect.caption,
|
||||||
|
L10n.Shortcuts.Add.Alerts.NoProfiles.message
|
||||||
|
)
|
||||||
|
alert.addAction(L10n.Global.ok) {
|
||||||
|
if let ip = self.tableView.indexPathForSelectedRow {
|
||||||
|
self.tableView.deselectRow(at: ip, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
present(alert, animated: true, completion: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
perform(segue: StoryboardSegue.Shortcuts.connectToSegueIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addEnable() {
|
||||||
|
addShortcut(with: IntentDispatcher.intentEnable())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addDisable() {
|
||||||
|
addShortcut(with: IntentDispatcher.intentDisable())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addTrustWiFi() {
|
||||||
|
addShortcut(with: IntentDispatcher.intentTrustWiFi())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addUntrustWiFi() {
|
||||||
|
addShortcut(with: IntentDispatcher.intentUntrustWiFi())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addTrustCellular() {
|
||||||
|
addShortcut(with: IntentDispatcher.intentTrustCellular())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addUntrustCellular() {
|
||||||
|
addShortcut(with: IntentDispatcher.intentUntrustCellular())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addShortcut(with intent: INIntent) {
|
||||||
|
delegate?.shortcutsDidSelectIntent(intent: intent)
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,8 @@ import Intents
|
||||||
import IntentsUI
|
import IntentsUI
|
||||||
import Passepartout_Core
|
import Passepartout_Core
|
||||||
|
|
||||||
class ShortcutsConnectToViewController: UITableViewController, TableModelHost {
|
@available(iOS 12, *)
|
||||||
|
class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewControllerDelegate, TableModelHost {
|
||||||
private let service = TransientStore.shared.service
|
private let service = TransientStore.shared.service
|
||||||
|
|
||||||
private var providers: [String] = []
|
private var providers: [String] = []
|
||||||
|
@ -37,6 +38,8 @@ class ShortcutsConnectToViewController: UITableViewController, TableModelHost {
|
||||||
|
|
||||||
private var selectedProfile: ConnectionProfile?
|
private var selectedProfile: ConnectionProfile?
|
||||||
|
|
||||||
|
weak var delegate: ShortcutsIntentDelegate?
|
||||||
|
|
||||||
// MARK: TableModelHost
|
// MARK: TableModelHost
|
||||||
|
|
||||||
let model: TableModel<SectionType, RowType> = {
|
let model: TableModel<SectionType, RowType> = {
|
||||||
|
@ -65,7 +68,7 @@ class ShortcutsConnectToViewController: UITableViewController, TableModelHost {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
title = L10n.Shortcuts.Cells.Connect.caption
|
title = L10n.Shortcuts.Add.Cells.Connect.caption
|
||||||
reloadModel()
|
reloadModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,9 +92,9 @@ class ShortcutsConnectToViewController: UITableViewController, TableModelHost {
|
||||||
vc.pools = provider.sortedPools()
|
vc.pools = provider.sortedPools()
|
||||||
vc.delegate = self
|
vc.delegate = self
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extension ShortcutsConnectToViewController {
|
// MARK: UITableViewController
|
||||||
|
|
||||||
enum SectionType {
|
enum SectionType {
|
||||||
case providers
|
case providers
|
||||||
|
|
||||||
|
@ -130,9 +133,6 @@ extension ShortcutsConnectToViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
guard #available(iOS 12, *) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch model.row(at: indexPath) {
|
switch model.row(at: indexPath) {
|
||||||
case .providerShortcut:
|
case .providerShortcut:
|
||||||
selectedProfile = service.profile(withContext: .provider, id: providers[indexPath.row])
|
selectedProfile = service.profile(withContext: .provider, id: providers[indexPath.row])
|
||||||
|
@ -143,68 +143,34 @@ extension ShortcutsConnectToViewController {
|
||||||
addConnect()
|
addConnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Actions
|
// MARK: Actions
|
||||||
|
|
||||||
@available(iOS 12, *)
|
|
||||||
extension ShortcutsConnectToViewController {
|
|
||||||
private func addConnect() {
|
private func addConnect() {
|
||||||
guard let host = selectedProfile as? HostConnectionProfile else {
|
guard let host = selectedProfile as? HostConnectionProfile else {
|
||||||
fatalError("Not a HostConnectionProfile")
|
fatalError("Not a HostConnectionProfile")
|
||||||
}
|
}
|
||||||
let intent = ConnectVPNIntent()
|
addShortcut(with: IntentDispatcher.intentConnect(profile: host))
|
||||||
intent.context = host.context.rawValue
|
|
||||||
intent.profileId = host.id
|
|
||||||
addShortcut(with: intent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addMoveToLocation(pool: Pool) {
|
private func addMoveToLocation(pool: Pool) {
|
||||||
guard let provider = selectedProfile as? ProviderConnectionProfile else {
|
guard let provider = selectedProfile as? ProviderConnectionProfile else {
|
||||||
fatalError("Not a ProviderConnectionProfile")
|
fatalError("Not a ProviderConnectionProfile")
|
||||||
}
|
}
|
||||||
let intent = MoveToLocationIntent()
|
addShortcut(with: IntentDispatcher.intentMoveTo(profile: provider, pool: pool))
|
||||||
intent.providerId = provider.id
|
|
||||||
intent.poolId = pool.id
|
|
||||||
intent.poolName = pool.localizedName
|
|
||||||
addShortcut(with: intent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addShortcut(with intent: INIntent) {
|
private func addShortcut(with intent: INIntent) {
|
||||||
guard let shortcut = INShortcut(intent: intent) else {
|
delegate?.shortcutsDidSelectIntent(intent: intent)
|
||||||
return
|
|
||||||
}
|
|
||||||
let vc = INUIAddVoiceShortcutViewController(shortcut: shortcut)
|
|
||||||
vc.delegate = self
|
|
||||||
present(vc, animated: true, completion: nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func pickProviderLocation() {
|
private func pickProviderLocation() {
|
||||||
perform(segue: StoryboardSegue.Shortcuts.pickLocationSegueIdentifier)
|
perform(segue: StoryboardSegue.Shortcuts.pickLocationSegueIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction private func done() {
|
// MARK: ProviderPoolViewControllerDelegate
|
||||||
dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ShortcutsConnectToViewController: ProviderPoolViewControllerDelegate {
|
|
||||||
func providerPoolController(_: ProviderPoolViewController, didSelectPool pool: Pool) {
|
func providerPoolController(_: ProviderPoolViewController, didSelectPool pool: Pool) {
|
||||||
guard #available(iOS 12, *) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
addMoveToLocation(pool: pool)
|
addMoveToLocation(pool: pool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 12, *)
|
|
||||||
extension ShortcutsConnectToViewController: INUIAddVoiceShortcutViewControllerDelegate {
|
|
||||||
func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
|
|
||||||
navigationController?.popViewController(animated: true)
|
|
||||||
dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
|
|
||||||
dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// ShortcutsViewController.swift
|
// ShortcutsViewController.swift
|
||||||
// Passepartout-iOS
|
// Passepartout-iOS
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 3/18/19.
|
// Created by Davide De Rosa on 3/27/19.
|
||||||
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
|
@ -24,28 +24,66 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Intents
|
||||||
import IntentsUI
|
import IntentsUI
|
||||||
import Passepartout_Core
|
import Passepartout_Core
|
||||||
|
|
||||||
class ShortcutsViewController: UITableViewController, TableModelHost {
|
@available(iOS 12, *)
|
||||||
|
protocol ShortcutsIntentDelegate: class {
|
||||||
|
func shortcutsDidSelectIntent(intent: INIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 12, *)
|
||||||
|
private struct ShortcutWrapper: Comparable {
|
||||||
|
let phrase: String
|
||||||
|
|
||||||
|
let intentDescription: String?
|
||||||
|
|
||||||
|
let original: INVoiceShortcut
|
||||||
|
|
||||||
|
static func from(_ vs: INVoiceShortcut) -> ShortcutWrapper {
|
||||||
|
return ShortcutWrapper(
|
||||||
|
phrase: vs.invocationPhrase,
|
||||||
|
intentDescription: vs.shortcut.intent?.intentDescription,
|
||||||
|
original: vs
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Equatable
|
||||||
|
|
||||||
|
static func ==(lhs: ShortcutWrapper, rhs: ShortcutWrapper) -> Bool {
|
||||||
|
return lhs.phrase == rhs.phrase
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Comparable
|
||||||
|
|
||||||
|
static func <(lhs: ShortcutWrapper, rhs: ShortcutWrapper) -> Bool {
|
||||||
|
return lhs.phrase < rhs.phrase
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 12, *)
|
||||||
|
class ShortcutsViewController: UITableViewController, INUIAddVoiceShortcutViewControllerDelegate, INUIEditVoiceShortcutViewControllerDelegate, ShortcutsIntentDelegate, TableModelHost {
|
||||||
|
private var wrappers: [ShortcutWrapper]?
|
||||||
|
|
||||||
|
private var pendingShortcut: INShortcut?
|
||||||
|
|
||||||
|
private var editedIndexPath: IndexPath?
|
||||||
|
|
||||||
// MARK: TableModel
|
// MARK: TableModel
|
||||||
|
|
||||||
let model: TableModel<SectionType, RowType> = {
|
let model: TableModel<SectionType, RowType> = {
|
||||||
let model: TableModel<SectionType, RowType> = TableModel()
|
let model: TableModel<SectionType, RowType> = TableModel()
|
||||||
model.add(.vpn)
|
model.add(.all)
|
||||||
model.add(.wifi)
|
model.setHeader(L10n.Shortcuts.Edit.Sections.All.header, for: .all)
|
||||||
model.add(.cellular)
|
model.set([], in: .all)
|
||||||
model.set([.connect, .enableVPN, .disableVPN], in: .vpn)
|
|
||||||
model.set([.trustCurrentWiFi, .untrustCurrentWiFi], in: .wifi)
|
|
||||||
model.set([.trustCellular, .untrustCellular], in: .cellular)
|
|
||||||
model.setHeader(L10n.Shortcuts.Sections.Vpn.header, for: .vpn)
|
|
||||||
model.setHeader(L10n.Shortcuts.Sections.Wifi.header, for: .wifi)
|
|
||||||
model.setHeader(L10n.Shortcuts.Sections.Cellular.header, for: .cellular)
|
|
||||||
return model
|
return model
|
||||||
}()
|
}()
|
||||||
|
|
||||||
func reloadModel() {
|
func reloadModel() {
|
||||||
|
var rows = [RowType](repeating: .shortcut, count: wrappers?.count ?? 0)
|
||||||
|
rows.append(.addShortcut)
|
||||||
|
model.set(rows, in: .all)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: UIViewController
|
// MARK: UIViewController
|
||||||
|
@ -54,32 +92,76 @@ class ShortcutsViewController: UITableViewController, TableModelHost {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
title = L10n.Organizer.Cells.SiriShortcuts.caption
|
title = L10n.Organizer.Cells.SiriShortcuts.caption
|
||||||
|
|
||||||
|
INVoiceShortcutCenter.shared.getAllVoiceShortcuts { [weak self] (shortcuts, error) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
guard let shortcuts = shortcuts else {
|
||||||
|
self?.handleShortcutsFetchError(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self?.handleShortcuts(shortcuts)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
extension ShortcutsViewController {
|
guard let shortcut = pendingShortcut else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pendingShortcut = nil
|
||||||
|
let vc = INUIAddVoiceShortcutViewController(shortcut: shortcut)
|
||||||
|
vc.delegate = self
|
||||||
|
present(vc, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Actions
|
||||||
|
|
||||||
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||||
|
if let vc = segue.destination as? ShortcutsAddViewController {
|
||||||
|
vc.delegate = self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addShortcut() {
|
||||||
|
perform(segue: StoryboardSegue.Shortcuts.shortcutAddSegueIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleShortcutsFetchError(_ error: Error?) {
|
||||||
|
|
||||||
|
// TODO: really show it?
|
||||||
|
// let alert = Macros.alert(
|
||||||
|
// title,
|
||||||
|
// L10n.Shortcuts.Edit.message(error?.localizedDescription ?? "")
|
||||||
|
// )
|
||||||
|
// alert.addCancelAction(L10n.Global.ok) {
|
||||||
|
// self.close()
|
||||||
|
// }
|
||||||
|
// present(alert, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleShortcuts(_ shortcuts: [INVoiceShortcut]) {
|
||||||
|
wrappers = shortcuts.map { ShortcutWrapper.from($0) }
|
||||||
|
wrappers?.sort()
|
||||||
|
reloadModel()
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction private func close() {
|
||||||
|
dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: UITableViewController
|
||||||
|
|
||||||
enum SectionType {
|
enum SectionType {
|
||||||
case vpn
|
case all
|
||||||
|
|
||||||
case wifi
|
|
||||||
|
|
||||||
case cellular
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RowType {
|
enum RowType {
|
||||||
case connect // host or provider+location
|
case shortcut
|
||||||
|
|
||||||
case enableVPN
|
case addShortcut
|
||||||
|
|
||||||
case disableVPN
|
|
||||||
|
|
||||||
case trustCurrentWiFi
|
|
||||||
|
|
||||||
case untrustCurrentWiFi
|
|
||||||
|
|
||||||
case trustCellular
|
|
||||||
|
|
||||||
case untrustCellular
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
@ -97,127 +179,95 @@ extension ShortcutsViewController {
|
||||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
||||||
switch model.row(at: indexPath) {
|
switch model.row(at: indexPath) {
|
||||||
case .connect:
|
case .shortcut:
|
||||||
cell.leftText = L10n.Shortcuts.Cells.Connect.caption
|
guard let wrapper = wrappers?[indexPath.row] else {
|
||||||
|
break
|
||||||
case .enableVPN:
|
}
|
||||||
cell.leftText = L10n.Shortcuts.Cells.EnableVpn.caption
|
cell.apply(Theme.current)
|
||||||
|
cell.leftText = wrapper.phrase
|
||||||
case .disableVPN:
|
cell.rightText = wrapper.intentDescription
|
||||||
cell.leftText = L10n.Shortcuts.Cells.DisableVpn.caption
|
|
||||||
|
case .addShortcut:
|
||||||
case .trustCurrentWiFi:
|
cell.applyAction(Theme.current)
|
||||||
cell.leftText = L10n.Shortcuts.Cells.TrustCurrentWifi.caption
|
cell.leftText = L10n.Shortcuts.Edit.Cells.AddShortcut.caption
|
||||||
|
cell.accessoryType = .none
|
||||||
case .untrustCurrentWiFi:
|
cell.isTappable = true
|
||||||
cell.leftText = L10n.Shortcuts.Cells.UntrustCurrentWifi.caption
|
|
||||||
|
|
||||||
case .trustCellular:
|
|
||||||
cell.leftText = L10n.Shortcuts.Cells.TrustCellular.caption
|
|
||||||
|
|
||||||
case .untrustCellular:
|
|
||||||
cell.leftText = L10n.Shortcuts.Cells.UntrustCellular.caption
|
|
||||||
}
|
}
|
||||||
cell.apply(Theme.current)
|
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
guard #available(iOS 12, *) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch model.row(at: indexPath) {
|
switch model.row(at: indexPath) {
|
||||||
case .connect:
|
case .shortcut:
|
||||||
addConnect()
|
guard let wrapper = wrappers?[indexPath.row] else {
|
||||||
|
break
|
||||||
case .enableVPN:
|
|
||||||
addEnable()
|
|
||||||
|
|
||||||
case .disableVPN:
|
|
||||||
addDisable()
|
|
||||||
|
|
||||||
case .trustCurrentWiFi:
|
|
||||||
addTrustWiFi()
|
|
||||||
|
|
||||||
case .untrustCurrentWiFi:
|
|
||||||
addUntrustWiFi()
|
|
||||||
|
|
||||||
case .trustCellular:
|
|
||||||
addTrustCellular()
|
|
||||||
|
|
||||||
case .untrustCellular:
|
|
||||||
addUntrustCellular()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Actions
|
|
||||||
|
|
||||||
@available(iOS 12, *)
|
|
||||||
extension ShortcutsViewController {
|
|
||||||
private func addConnect() {
|
|
||||||
guard TransientStore.shared.service.hasProfiles() else {
|
|
||||||
let alert = Macros.alert(
|
|
||||||
L10n.Shortcuts.Cells.Connect.caption,
|
|
||||||
L10n.Shortcuts.Alerts.NoProfiles.message
|
|
||||||
)
|
|
||||||
alert.addAction(L10n.Global.ok) {
|
|
||||||
if let ip = self.tableView.indexPathForSelectedRow {
|
|
||||||
self.tableView.deselectRow(at: ip, animated: true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
present(alert, animated: true, completion: nil)
|
let vc = INUIEditVoiceShortcutViewController(voiceShortcut: wrapper.original)
|
||||||
return
|
vc.delegate = self
|
||||||
|
editedIndexPath = indexPath
|
||||||
|
present(vc, animated: true, completion: nil)
|
||||||
|
|
||||||
|
case .addShortcut:
|
||||||
|
addShortcut()
|
||||||
}
|
}
|
||||||
perform(segue: StoryboardSegue.Shortcuts.connectToSegueIdentifier)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addEnable() {
|
// MARK: ShortcutsIntentDelegate
|
||||||
addShortcut(with: EnableVPNIntent())
|
|
||||||
}
|
func shortcutsDidSelectIntent(intent: INIntent) {
|
||||||
|
pendingShortcut = INShortcut(intent: intent)
|
||||||
private func addDisable() {
|
navigationController?.popToViewController(self, animated: true)
|
||||||
addShortcut(with: DisableVPNIntent())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addTrustWiFi() {
|
// MARK: INUIAddVoiceShortcutViewControllerDelegate
|
||||||
addShortcut(with: TrustCurrentNetworkIntent())
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addUntrustWiFi() {
|
|
||||||
addShortcut(with: UntrustCurrentNetworkIntent())
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addTrustCellular() {
|
|
||||||
addShortcut(with: TrustCellularNetworkIntent())
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addUntrustCellular() {
|
|
||||||
addShortcut(with: UntrustCellularNetworkIntent())
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addShortcut(with intent: INIntent) {
|
|
||||||
guard let shortcut = INShortcut(intent: intent) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let vc = INUIAddVoiceShortcutViewController(shortcut: shortcut)
|
|
||||||
vc.delegate = self
|
|
||||||
present(vc, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@IBAction private func close() {
|
|
||||||
dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(iOS 12, *)
|
|
||||||
extension ShortcutsViewController: INUIAddVoiceShortcutViewControllerDelegate {
|
|
||||||
func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
|
func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
|
||||||
|
guard let voiceShortcut = voiceShortcut else {
|
||||||
|
dismiss(animated: true, completion: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wrappers?.append(ShortcutWrapper.from(voiceShortcut))
|
||||||
|
wrappers?.sort()
|
||||||
|
reloadModel()
|
||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
|
|
||||||
dismiss(animated: true, completion: nil)
|
dismiss(animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
|
func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
|
||||||
dismiss(animated: true, completion: nil)
|
dismiss(animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: INUIEditVoiceShortcutViewControllerDelegate
|
||||||
|
|
||||||
|
func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didUpdate voiceShortcut: INVoiceShortcut?, error: Error?) {
|
||||||
|
guard let indexPath = editedIndexPath, let voiceShortcut = voiceShortcut else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
editedIndexPath = nil
|
||||||
|
wrappers?[indexPath.row] = ShortcutWrapper.from(voiceShortcut)
|
||||||
|
wrappers?.sort()
|
||||||
|
tableView.reloadData()
|
||||||
|
|
||||||
|
dismiss(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID) {
|
||||||
|
guard let indexPath = editedIndexPath else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
editedIndexPath = nil
|
||||||
|
wrappers?.remove(at: indexPath.row)
|
||||||
|
reloadModel()
|
||||||
|
|
||||||
|
dismiss(animated: true) {
|
||||||
|
self.tableView.deleteRows(at: [indexPath], with: .automatic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) {
|
||||||
|
editedIndexPath = nil
|
||||||
|
dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,7 +631,7 @@
|
||||||
<viewControllerPlaceholder storyboardName="Shortcuts" id="BIO-UT-cpg" sceneMemberID="viewController"/>
|
<viewControllerPlaceholder storyboardName="Shortcuts" id="BIO-UT-cpg" sceneMemberID="viewController"/>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Pbd-BC-bBJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="Pbd-BC-bBJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="-2449" y="-280"/>
|
<point key="canvasLocation" x="-2552" y="-280"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
@ -1,39 +1,35 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5sh-GP-KYT">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Dh1-Xv-FiO">
|
||||||
<device id="retina4_7" orientation="portrait">
|
|
||||||
<adaptation id="fullscreen"/>
|
|
||||||
</device>
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--Shortcuts View Controller-->
|
<!--Shortcuts Add View Controller-->
|
||||||
<scene sceneID="F0m-Xp-5pf">
|
<scene sceneID="F0m-Xp-5pf">
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="mG2-gQ-aPy" customClass="ShortcutsViewController" customModule="Passepartout" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="mG2-gQ-aPy" customClass="ShortcutsAddViewController" customModule="Passepartout" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="Iib-qS-k2f">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="Iib-qS-k2f">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SettingTableViewCell" textLabel="uM1-Q0-TNy" detailTextLabel="3qI-Ca-OLt" style="IBUITableViewCellStyleValue1" id="fOB-T2-oQ9" customClass="SettingTableViewCell" customModule="Passepartout" customModuleProvider="target">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SettingTableViewCell" textLabel="uM1-Q0-TNy" detailTextLabel="3qI-Ca-OLt" style="IBUITableViewCellStyleValue1" id="fOB-T2-oQ9" customClass="SettingTableViewCell" customModule="Passepartout" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="55.5" width="600" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fOB-T2-oQ9" id="lKF-U0-Np6">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fOB-T2-oQ9" id="lKF-U0-Np6">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uM1-Q0-TNy">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uM1-Q0-TNy">
|
||||||
<rect key="frame" x="16" y="12" width="33.5" height="20.5"/>
|
<rect key="frame" x="20" y="12" width="33.5" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="3qI-Ca-OLt">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="3qI-Ca-OLt">
|
||||||
<rect key="frame" x="315" y="12" width="44" height="20.5"/>
|
<rect key="frame" x="536" y="12" width="44" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
|
@ -48,13 +44,7 @@
|
||||||
<outlet property="delegate" destination="mG2-gQ-aPy" id="wNK-aT-dNi"/>
|
<outlet property="delegate" destination="mG2-gQ-aPy" id="wNK-aT-dNi"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<navigationItem key="navigationItem" id="Yck-NS-FzJ">
|
<navigationItem key="navigationItem" id="Yck-NS-FzJ"/>
|
||||||
<barButtonItem key="leftBarButtonItem" systemItem="stop" id="8HE-Ax-VIa">
|
|
||||||
<connections>
|
|
||||||
<action selector="close" destination="mG2-gQ-aPy" id="Eua-Wd-kuz"/>
|
|
||||||
</connections>
|
|
||||||
</barButtonItem>
|
|
||||||
</navigationItem>
|
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="zpj-mS-isI" kind="show" identifier="ConnectToSegueIdentifier" id="Qer-qI-Oyn"/>
|
<segue destination="zpj-mS-isI" kind="show" identifier="ConnectToSegueIdentifier" id="Qer-qI-Oyn"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
@ -68,26 +58,26 @@
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="zpj-mS-isI" customClass="ShortcutsConnectToViewController" customModule="Passepartout" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="zpj-mS-isI" customClass="ShortcutsConnectToViewController" customModule="Passepartout" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="srP-K7-dae">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="srP-K7-dae">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SettingTableViewCell" textLabel="4LM-xw-0Rx" detailTextLabel="4RM-B9-uCO" style="IBUITableViewCellStyleValue1" id="aw4-ca-yyE" customClass="SettingTableViewCell" customModule="Passepartout" customModuleProvider="target">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SettingTableViewCell" textLabel="4LM-xw-0Rx" detailTextLabel="4RM-B9-uCO" style="IBUITableViewCellStyleValue1" id="aw4-ca-yyE" customClass="SettingTableViewCell" customModule="Passepartout" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="55.5" width="600" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aw4-ca-yyE" id="HBB-Gp-iw2">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aw4-ca-yyE" id="HBB-Gp-iw2">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4LM-xw-0Rx">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4LM-xw-0Rx">
|
||||||
<rect key="frame" x="16" y="12" width="33.5" height="20.5"/>
|
<rect key="frame" x="20" y="12" width="33.5" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4RM-B9-uCO">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4RM-B9-uCO">
|
||||||
<rect key="frame" x="315" y="12" width="44" height="20.5"/>
|
<rect key="frame" x="536" y="12" width="44" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
|
@ -102,13 +92,7 @@
|
||||||
<outlet property="delegate" destination="zpj-mS-isI" id="zex-yh-op8"/>
|
<outlet property="delegate" destination="zpj-mS-isI" id="zex-yh-op8"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<navigationItem key="navigationItem" id="kUu-WC-MJQ">
|
<navigationItem key="navigationItem" id="kUu-WC-MJQ"/>
|
||||||
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="m8u-XK-MLx">
|
|
||||||
<connections>
|
|
||||||
<action selector="done" destination="zpj-mS-isI" id="f5U-ko-QS3"/>
|
|
||||||
</connections>
|
|
||||||
</barButtonItem>
|
|
||||||
</navigationItem>
|
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="bPc-ex-Jwe" kind="show" identifier="PickLocationSegueIdentifier" id="ah9-pc-zoh"/>
|
<segue destination="bPc-ex-Jwe" kind="show" identifier="PickLocationSegueIdentifier" id="ah9-pc-zoh"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
@ -126,20 +110,74 @@
|
||||||
<point key="canvasLocation" x="3024" y="-816"/>
|
<point key="canvasLocation" x="3024" y="-816"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Navigation Controller-->
|
<!--Navigation Controller-->
|
||||||
<scene sceneID="qTb-wr-bYf">
|
<scene sceneID="vDf-qD-Fry">
|
||||||
<objects>
|
<objects>
|
||||||
<navigationController id="5sh-GP-KYT" sceneMemberID="viewController">
|
<navigationController storyboardIdentifier="ShortcutsViewController" id="Dh1-Xv-FiO" sceneMemberID="viewController">
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="l2p-Xo-gm2">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="udB-Be-iBH">
|
||||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="mG2-gQ-aPy" kind="relationship" relationship="rootViewController" id="vcT-cA-gf6"/>
|
<segue destination="br5-OH-3al" kind="relationship" relationship="rootViewController" id="YoV-2z-krF"/>
|
||||||
</connections>
|
</connections>
|
||||||
</navigationController>
|
</navigationController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dqv-Kz-2i6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iIj-K9-Skm" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="674" y="-815"/>
|
<point key="canvasLocation" x="673" y="-1639"/>
|
||||||
|
</scene>
|
||||||
|
<!--Shortcuts View Controller-->
|
||||||
|
<scene sceneID="ZRc-t3-Lf5">
|
||||||
|
<objects>
|
||||||
|
<tableViewController id="br5-OH-3al" customClass="ShortcutsViewController" customModule="Passepartout" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="dtc-j9-MHJ">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||||
|
<prototypes>
|
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SettingTableViewCell" textLabel="QvK-JJ-pYE" detailTextLabel="Df7-oa-jnK" rowHeight="64" style="IBUITableViewCellStyleSubtitle" id="9v0-YX-ro9" customClass="SettingTableViewCell" customModule="Passepartout" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="55.5" width="600" height="64"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="9v0-YX-ro9" id="Ubx-m0-uOE">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="63.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QvK-JJ-pYE">
|
||||||
|
<rect key="frame" x="20" y="12" width="33.5" height="20.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Df7-oa-jnK">
|
||||||
|
<rect key="frame" x="20" y="35.5" width="33" height="14.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
</tableViewCell>
|
||||||
|
</prototypes>
|
||||||
|
<connections>
|
||||||
|
<outlet property="dataSource" destination="br5-OH-3al" id="0aZ-df-Q8C"/>
|
||||||
|
<outlet property="delegate" destination="br5-OH-3al" id="wAP-cr-724"/>
|
||||||
|
</connections>
|
||||||
|
</tableView>
|
||||||
|
<navigationItem key="navigationItem" id="bYj-QP-dCh">
|
||||||
|
<barButtonItem key="leftBarButtonItem" systemItem="stop" id="sJJ-Ac-fsA">
|
||||||
|
<connections>
|
||||||
|
<action selector="close" destination="br5-OH-3al" id="aDO-9u-n6v"/>
|
||||||
|
</connections>
|
||||||
|
</barButtonItem>
|
||||||
|
</navigationItem>
|
||||||
|
<connections>
|
||||||
|
<segue destination="mG2-gQ-aPy" kind="show" identifier="ShortcutAddSegueIdentifier" id="tmC-OL-AXU"/>
|
||||||
|
</connections>
|
||||||
|
</tableViewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="s4j-l7-Hi8" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="1494" y="-1640"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
0E3152DD223FA06100F61841 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E05C5DF20D198B9006EE732 /* Localizable.strings */; };
|
0E3152DD223FA06100F61841 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E05C5DF20D198B9006EE732 /* Localizable.strings */; };
|
||||||
0E3152DE223FA06400F61841 /* Web in Resources */ = {isa = PBXBuildFile; fileRef = 0E0EABC721DF853C0069DAE7 /* Web */; };
|
0E3152DE223FA06400F61841 /* Web in Resources */ = {isa = PBXBuildFile; fileRef = 0E0EABC721DF853C0069DAE7 /* Web */; };
|
||||||
0E3152DF223FA1DD00F61841 /* ConnectionService.json in Resources */ = {isa = PBXBuildFile; fileRef = 0EBBE8F121822B4D00106008 /* ConnectionService.json */; };
|
0E3152DF223FA1DD00F61841 /* ConnectionService.json in Resources */ = {isa = PBXBuildFile; fileRef = 0EBBE8F121822B4D00106008 /* ConnectionService.json */; };
|
||||||
0E36D24D2240234B006AF062 /* ShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D24C2240234B006AF062 /* ShortcutsViewController.swift */; };
|
0E36D24D2240234B006AF062 /* ShortcutsAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D24C2240234B006AF062 /* ShortcutsAddViewController.swift */; };
|
||||||
0E36D25822403469006AF062 /* Shortcuts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E36D25A22403469006AF062 /* Shortcuts.storyboard */; };
|
0E36D25822403469006AF062 /* Shortcuts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E36D25A22403469006AF062 /* Shortcuts.storyboard */; };
|
||||||
0E36D25C224034AD006AF062 /* ShortcutsConnectToViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */; };
|
0E36D25C224034AD006AF062 /* ShortcutsConnectToViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */; };
|
||||||
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */; };
|
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */; };
|
||||||
|
@ -75,6 +75,7 @@
|
||||||
0E58BF65224152F9006FB157 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0E58BD9122404EF1006FB157 /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; };
|
0E58BF65224152F9006FB157 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0E58BD9122404EF1006FB157 /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; };
|
||||||
0E58BF68224305A8006FB157 /* Countries.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E58BF6A224305A8006FB157 /* Countries.strings */; };
|
0E58BF68224305A8006FB157 /* Countries.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E58BF6A224305A8006FB157 /* Countries.strings */; };
|
||||||
0E6BE13F20CFBAB300A6DD36 /* DebugLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */; };
|
0E6BE13F20CFBAB300A6DD36 /* DebugLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */; };
|
||||||
|
0E773BF8224BF37600CDDC8E /* ShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E773BF7224BF37600CDDC8E /* ShortcutsViewController.swift */; };
|
||||||
0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; };
|
0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; };
|
||||||
0EA068F4218475F800C320AD /* ParsingResult+Alerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA068F3218475F800C320AD /* ParsingResult+Alerts.swift */; };
|
0EA068F4218475F800C320AD /* ParsingResult+Alerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA068F3218475F800C320AD /* ParsingResult+Alerts.swift */; };
|
||||||
0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; };
|
0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; };
|
||||||
|
@ -177,7 +178,7 @@
|
||||||
0E31529E223F9EF500F61841 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
0E31529E223F9EF500F61841 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
0E3152A3223F9EF500F61841 /* Passepartout-CoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Passepartout-CoreTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
0E3152A3223F9EF500F61841 /* Passepartout-CoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Passepartout-CoreTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
0E3152AC223F9EF500F61841 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
0E3152AC223F9EF500F61841 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
0E36D24C2240234B006AF062 /* ShortcutsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsViewController.swift; sourceTree = "<group>"; };
|
0E36D24C2240234B006AF062 /* ShortcutsAddViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsAddViewController.swift; sourceTree = "<group>"; };
|
||||||
0E36D25922403469006AF062 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Shortcuts.storyboard; sourceTree = "<group>"; };
|
0E36D25922403469006AF062 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Shortcuts.storyboard; sourceTree = "<group>"; };
|
||||||
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConnectToViewController.swift; sourceTree = "<group>"; };
|
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConnectToViewController.swift; sourceTree = "<group>"; };
|
||||||
0E39BCEF214B9EF10035E9DE /* WebServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebServices.swift; sourceTree = "<group>"; };
|
0E39BCEF214B9EF10035E9DE /* WebServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebServices.swift; sourceTree = "<group>"; };
|
||||||
|
@ -202,6 +203,7 @@
|
||||||
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>"; };
|
||||||
|
0E773BF7224BF37600CDDC8E /* ShortcutsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsViewController.swift; sourceTree = "<group>"; };
|
||||||
0E78179E21BE852200950C58 /* Reviewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reviewer.swift; sourceTree = "<group>"; };
|
0E78179E21BE852200950C58 /* Reviewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reviewer.swift; sourceTree = "<group>"; };
|
||||||
0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderConnectionProfile.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>"; };
|
0E79D14021919F5600BB5FB2 /* ProfileKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileKey.swift; sourceTree = "<group>"; };
|
||||||
|
@ -416,8 +418,9 @@
|
||||||
0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */,
|
0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */,
|
||||||
0EFD943F215BED8E00529B64 /* LabelViewController.swift */,
|
0EFD943F215BED8E00529B64 /* LabelViewController.swift */,
|
||||||
0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */,
|
0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */,
|
||||||
|
0E36D24C2240234B006AF062 /* ShortcutsAddViewController.swift */,
|
||||||
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */,
|
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */,
|
||||||
0E36D24C2240234B006AF062 /* ShortcutsViewController.swift */,
|
0E773BF7224BF37600CDDC8E /* ShortcutsViewController.swift */,
|
||||||
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */,
|
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */,
|
||||||
0ED38AD8213F33150004D387 /* WizardHostViewController.swift */,
|
0ED38AD8213F33150004D387 /* WizardHostViewController.swift */,
|
||||||
0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */,
|
0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */,
|
||||||
|
@ -1006,6 +1009,7 @@
|
||||||
0EF56BBB2185AC8500B0C8AB /* SwiftGen+Segues.swift in Sources */,
|
0EF56BBB2185AC8500B0C8AB /* SwiftGen+Segues.swift in Sources */,
|
||||||
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */,
|
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */,
|
||||||
0E05C5D620D1645F006EE732 /* SwiftGen+Scenes.swift in Sources */,
|
0E05C5D620D1645F006EE732 /* SwiftGen+Scenes.swift in Sources */,
|
||||||
|
0E773BF8224BF37600CDDC8E /* ShortcutsViewController.swift in Sources */,
|
||||||
0EFD9440215BED8E00529B64 /* LabelViewController.swift in Sources */,
|
0EFD9440215BED8E00529B64 /* LabelViewController.swift in Sources */,
|
||||||
0ED31C2C20CF2D6F0027975F /* ProviderPoolViewController.swift in Sources */,
|
0ED31C2C20CF2D6F0027975F /* ProviderPoolViewController.swift in Sources */,
|
||||||
0E2B494020FCFF990094784C /* Theme+Titles.swift in Sources */,
|
0E2B494020FCFF990094784C /* Theme+Titles.swift in Sources */,
|
||||||
|
@ -1019,7 +1023,7 @@
|
||||||
0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */,
|
0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */,
|
||||||
0EB67D6B2184581E00BA6200 /* ImportedHostsViewController.swift in Sources */,
|
0EB67D6B2184581E00BA6200 /* ImportedHostsViewController.swift in Sources */,
|
||||||
0E57F63E20C83FC5008323CF /* ServiceViewController.swift in Sources */,
|
0E57F63E20C83FC5008323CF /* ServiceViewController.swift in Sources */,
|
||||||
0E36D24D2240234B006AF062 /* ShortcutsViewController.swift in Sources */,
|
0E36D24D2240234B006AF062 /* ShortcutsAddViewController.swift in Sources */,
|
||||||
0EA068F4218475F800C320AD /* ParsingResult+Alerts.swift in Sources */,
|
0EA068F4218475F800C320AD /* ParsingResult+Alerts.swift in Sources */,
|
||||||
0E57F63C20C83FC5008323CF /* AppDelegate.swift in Sources */,
|
0E57F63C20C83FC5008323CF /* AppDelegate.swift in Sources */,
|
||||||
0ED31C2920CF2A340027975F /* AccountViewController.swift in Sources */,
|
0ED31C2920CF2A340027975F /* AccountViewController.swift in Sources */,
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
"organizer.cells.profile.value.current" = "In use";
|
"organizer.cells.profile.value.current" = "In use";
|
||||||
"organizer.cells.add_provider.caption" = "Add new network";
|
"organizer.cells.add_provider.caption" = "Add new network";
|
||||||
"organizer.cells.add_host.caption" = "Add new host";
|
"organizer.cells.add_host.caption" = "Add new host";
|
||||||
"organizer.cells.siri_shortcuts.caption" = "Add shortcuts";
|
"organizer.cells.siri_shortcuts.caption" = "Manage shortcuts";
|
||||||
"organizer.cells.about.caption" = "About %@";
|
"organizer.cells.about.caption" = "About %@";
|
||||||
"organizer.cells.uninstall.caption" = "Remove VPN configuration";
|
"organizer.cells.uninstall.caption" = "Remove VPN configuration";
|
||||||
"organizer.alerts.exhausted_providers.message" = "You have created profiles for any available network.";
|
"organizer.alerts.exhausted_providers.message" = "You have created profiles for any available network.";
|
||||||
|
@ -204,17 +204,22 @@
|
||||||
"issue_reporter.email.body" = "Hi,\n\n%@\n\n%@\n\nRegards";
|
"issue_reporter.email.body" = "Hi,\n\n%@\n\n%@\n\nRegards";
|
||||||
"issue_reporter.email.description" = "description of the issue:";
|
"issue_reporter.email.description" = "description of the issue:";
|
||||||
|
|
||||||
"shortcuts.sections.vpn.header" = "VPN";
|
"shortcuts.add.title" = "Add shortcut";
|
||||||
"shortcuts.sections.wifi.header" = "Wi-Fi";
|
"shortcuts.add.sections.vpn.header" = "VPN";
|
||||||
"shortcuts.sections.cellular.header" = "Cellular";
|
"shortcuts.add.sections.wifi.header" = "Wi-Fi";
|
||||||
"shortcuts.cells.connect.caption" = "Connect to";
|
"shortcuts.add.sections.cellular.header" = "Cellular";
|
||||||
"shortcuts.cells.enable_vpn.caption" = "Enable VPN";
|
"shortcuts.add.cells.connect.caption" = "Connect to";
|
||||||
"shortcuts.cells.disable_vpn.caption" = "Disable VPN";
|
"shortcuts.add.cells.enable_vpn.caption" = "Enable VPN";
|
||||||
"shortcuts.cells.trust_current_wifi.caption" = "Trust current Wi-Fi";
|
"shortcuts.add.cells.disable_vpn.caption" = "Disable VPN";
|
||||||
"shortcuts.cells.untrust_current_wifi.caption" = "Untrust current Wi-Fi";
|
"shortcuts.add.cells.trust_current_wifi.caption" = "Trust current Wi-Fi";
|
||||||
"shortcuts.cells.trust_cellular.caption" = "Trust cellular network";
|
"shortcuts.add.cells.untrust_current_wifi.caption" = "Untrust current Wi-Fi";
|
||||||
"shortcuts.cells.untrust_cellular.caption" = "Untrust cellular network";
|
"shortcuts.add.cells.trust_cellular.caption" = "Trust cellular network";
|
||||||
"shortcuts.alerts.no_profiles.message" = "There is no profile to connect to.";
|
"shortcuts.add.cells.untrust_cellular.caption" = "Untrust cellular network";
|
||||||
|
"shortcuts.add.alerts.no_profiles.message" = "There is no profile to connect to.";
|
||||||
|
|
||||||
|
"shortcuts.edit.title" = "Manage shortcuts";
|
||||||
|
"shortcuts.edit.sections.all.header" = "Existing shortcuts";
|
||||||
|
"shortcuts.edit.cells.add_shortcut.caption" = "Add shortcut";
|
||||||
|
|
||||||
"about.title" = "About";
|
"about.title" = "About";
|
||||||
"about.sections.web.header" = "Web";
|
"about.sections.web.header" = "Web";
|
||||||
|
|
|
@ -41,72 +41,94 @@ public class IntentDispatcher {
|
||||||
static let trust = "Trust"
|
static let trust = "Trust"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Intents
|
||||||
|
|
||||||
|
public static func intentConnect(profile: ConnectionProfile) -> ConnectVPNIntent {
|
||||||
|
let intent = ConnectVPNIntent()
|
||||||
|
intent.context = profile.context.rawValue
|
||||||
|
intent.profileId = profile.id
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentMoveTo(profile: ProviderConnectionProfile, pool: Pool) -> MoveToLocationIntent {
|
||||||
|
let intent = MoveToLocationIntent()
|
||||||
|
intent.providerId = profile.id
|
||||||
|
intent.poolId = pool.id
|
||||||
|
intent.poolName = pool.localizedName
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentEnable() -> EnableVPNIntent {
|
||||||
|
return EnableVPNIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentDisable() -> DisableVPNIntent {
|
||||||
|
return DisableVPNIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentTrustWiFi() -> TrustCurrentNetworkIntent {
|
||||||
|
return TrustCurrentNetworkIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentUntrustWiFi() -> UntrustCurrentNetworkIntent {
|
||||||
|
return UntrustCurrentNetworkIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentTrustCellular() -> TrustCellularNetworkIntent {
|
||||||
|
return TrustCellularNetworkIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func intentUntrustCellular() -> UntrustCellularNetworkIntent {
|
||||||
|
return UntrustCellularNetworkIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Donations
|
||||||
|
|
||||||
public static func donateConnection(with profile: ConnectionProfile) {
|
public static func donateConnection(with profile: ConnectionProfile) {
|
||||||
let profileKey = ProfileKey(profile)
|
|
||||||
let genericIntent: INIntent
|
let genericIntent: INIntent
|
||||||
|
|
||||||
if let provider = profile as? ProviderConnectionProfile, let pool = provider.pool {
|
if let provider = profile as? ProviderConnectionProfile, let pool = provider.pool {
|
||||||
let intent = MoveToLocationIntent()
|
genericIntent = intentMoveTo(profile: provider, pool: pool)
|
||||||
intent.providerId = profile.id
|
|
||||||
intent.poolId = pool.id
|
|
||||||
intent.poolName = pool.localizedName
|
|
||||||
genericIntent = intent
|
|
||||||
} else {
|
} else {
|
||||||
let intent = ConnectVPNIntent()
|
genericIntent = intentConnect(profile: profile)
|
||||||
intent.context = profileKey.context.rawValue
|
|
||||||
intent.profileId = profileKey.id
|
|
||||||
genericIntent = intent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let interaction = INInteraction(intent: genericIntent, response: nil)
|
let interaction = INInteraction(intent: genericIntent, response: nil)
|
||||||
interaction.groupIdentifier = profileKey.rawValue
|
interaction.groupIdentifier = ProfileKey(profile).rawValue
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func donateEnableVPN() {
|
public static func donateEnableVPN() {
|
||||||
let intent = EnableVPNIntent()
|
let interaction = INInteraction(intent: intentEnable(), response: nil)
|
||||||
|
|
||||||
let interaction = INInteraction(intent: intent, response: nil)
|
|
||||||
interaction.groupIdentifier = Groups.vpn
|
interaction.groupIdentifier = Groups.vpn
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func donateDisableVPN() {
|
public static func donateDisableVPN() {
|
||||||
let intent = DisableVPNIntent()
|
let interaction = INInteraction(intent: intentDisable(), response: nil)
|
||||||
|
|
||||||
let interaction = INInteraction(intent: intent, response: nil)
|
|
||||||
interaction.groupIdentifier = Groups.vpn
|
interaction.groupIdentifier = Groups.vpn
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func donateTrustCurrentNetwork() {
|
public static func donateTrustCurrentNetwork() {
|
||||||
let intent = TrustCurrentNetworkIntent()
|
let interaction = INInteraction(intent: intentTrustWiFi(), response: nil)
|
||||||
|
|
||||||
let interaction = INInteraction(intent: intent, response: nil)
|
|
||||||
interaction.groupIdentifier = Groups.trust
|
interaction.groupIdentifier = Groups.trust
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func donateUntrustCurrentNetwork() {
|
public static func donateUntrustCurrentNetwork() {
|
||||||
let intent = UntrustCurrentNetworkIntent()
|
let interaction = INInteraction(intent: intentUntrustWiFi(), response: nil)
|
||||||
|
|
||||||
let interaction = INInteraction(intent: intent, response: nil)
|
|
||||||
interaction.groupIdentifier = Groups.trust
|
interaction.groupIdentifier = Groups.trust
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func donateTrustCellularNetwork() {
|
public static func donateTrustCellularNetwork() {
|
||||||
let intent = TrustCellularNetworkIntent()
|
let interaction = INInteraction(intent: intentTrustCellular(), response: nil)
|
||||||
|
|
||||||
let interaction = INInteraction(intent: intent, response: nil)
|
|
||||||
interaction.groupIdentifier = Groups.trust
|
interaction.groupIdentifier = Groups.trust
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func donateUntrustCellularNetwork() {
|
public static func donateUntrustCellularNetwork() {
|
||||||
let intent = UntrustCellularNetworkIntent()
|
let interaction = INInteraction(intent: intentUntrustCellular(), response: nil)
|
||||||
|
|
||||||
let interaction = INInteraction(intent: intent, response: nil)
|
|
||||||
interaction.groupIdentifier = Groups.trust
|
interaction.groupIdentifier = Groups.trust
|
||||||
interaction.donateAndLog()
|
interaction.donateAndLog()
|
||||||
}
|
}
|
||||||
|
@ -178,7 +200,7 @@ public class IntentDispatcher {
|
||||||
completionHandler?(nil)
|
completionHandler?(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.info("Move to provider location: \(providerId) @ [\(poolId)]")
|
log.info("Connect to provider location: \(providerId) @ [\(poolId)]")
|
||||||
|
|
||||||
let vpn = VPN.shared
|
let vpn = VPN.shared
|
||||||
guard !(service.isActiveProfile(providerProfile) && (providerProfile.poolId == poolId) && (vpn.status == .connected)) else {
|
guard !(service.isActiveProfile(providerProfile) && (providerProfile.poolId == poolId) && (vpn.status == .connected)) else {
|
||||||
|
|
|
@ -493,7 +493,7 @@
|
||||||
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
|
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>INIntentParameterCombinationTitle</key>
|
<key>INIntentParameterCombinationTitle</key>
|
||||||
<string>Move to ${poolName}</string>
|
<string>Connect to ${poolName}</string>
|
||||||
<key>INIntentParameterCombinationTitleID</key>
|
<key>INIntentParameterCombinationTitleID</key>
|
||||||
<string>WnTPFg</string>
|
<string>WnTPFg</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
@ -570,7 +570,7 @@
|
||||||
<key>INIntentRestrictions</key>
|
<key>INIntentRestrictions</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>INIntentTitle</key>
|
<key>INIntentTitle</key>
|
||||||
<string>Move to provider location</string>
|
<string>Connect to provider location</string>
|
||||||
<key>INIntentTitleID</key>
|
<key>INIntentTitleID</key>
|
||||||
<string>qo3Szz</string>
|
<string>qo3Szz</string>
|
||||||
<key>INIntentType</key>
|
<key>INIntentType</key>
|
||||||
|
|
|
@ -373,7 +373,7 @@ public enum L10n {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public enum SiriShortcuts {
|
public enum SiriShortcuts {
|
||||||
/// Add shortcuts
|
/// Manage shortcuts
|
||||||
public static let caption = L10n.tr("Localizable", "organizer.cells.siri_shortcuts.caption")
|
public static let caption = L10n.tr("Localizable", "organizer.cells.siri_shortcuts.caption")
|
||||||
}
|
}
|
||||||
public enum Uninstall {
|
public enum Uninstall {
|
||||||
|
@ -697,54 +697,74 @@ public enum L10n {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Shortcuts {
|
public enum Shortcuts {
|
||||||
public enum Alerts {
|
public enum Add {
|
||||||
public enum NoProfiles {
|
/// Add shortcut
|
||||||
/// There is no profile to connect to.
|
public static let title = L10n.tr("Localizable", "shortcuts.add.title")
|
||||||
public static let message = L10n.tr("Localizable", "shortcuts.alerts.no_profiles.message")
|
public enum Alerts {
|
||||||
|
public enum NoProfiles {
|
||||||
|
/// There is no profile to connect to.
|
||||||
|
public static let message = L10n.tr("Localizable", "shortcuts.add.alerts.no_profiles.message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public enum Cells {
|
||||||
|
public enum Connect {
|
||||||
|
/// Connect to
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.connect.caption")
|
||||||
|
}
|
||||||
|
public enum DisableVpn {
|
||||||
|
/// Disable VPN
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.disable_vpn.caption")
|
||||||
|
}
|
||||||
|
public enum EnableVpn {
|
||||||
|
/// Enable VPN
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.enable_vpn.caption")
|
||||||
|
}
|
||||||
|
public enum TrustCellular {
|
||||||
|
/// Trust cellular network
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.trust_cellular.caption")
|
||||||
|
}
|
||||||
|
public enum TrustCurrentWifi {
|
||||||
|
/// Trust current Wi-Fi
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.trust_current_wifi.caption")
|
||||||
|
}
|
||||||
|
public enum UntrustCellular {
|
||||||
|
/// Untrust cellular network
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.untrust_cellular.caption")
|
||||||
|
}
|
||||||
|
public enum UntrustCurrentWifi {
|
||||||
|
/// Untrust current Wi-Fi
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.untrust_current_wifi.caption")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public enum Sections {
|
||||||
|
public enum Cellular {
|
||||||
|
/// Cellular
|
||||||
|
public static let header = L10n.tr("Localizable", "shortcuts.add.sections.cellular.header")
|
||||||
|
}
|
||||||
|
public enum Vpn {
|
||||||
|
/// VPN
|
||||||
|
public static let header = L10n.tr("Localizable", "shortcuts.add.sections.vpn.header")
|
||||||
|
}
|
||||||
|
public enum Wifi {
|
||||||
|
/// Wi-Fi
|
||||||
|
public static let header = L10n.tr("Localizable", "shortcuts.add.sections.wifi.header")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public enum Cells {
|
public enum Edit {
|
||||||
public enum Connect {
|
/// Manage shortcuts
|
||||||
/// Connect to
|
public static let title = L10n.tr("Localizable", "shortcuts.edit.title")
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.connect.caption")
|
public enum Cells {
|
||||||
|
public enum AddShortcut {
|
||||||
|
/// Add shortcut
|
||||||
|
public static let caption = L10n.tr("Localizable", "shortcuts.edit.cells.add_shortcut.caption")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public enum DisableVpn {
|
public enum Sections {
|
||||||
/// Disable VPN
|
public enum All {
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.disable_vpn.caption")
|
/// Existing shortcuts
|
||||||
}
|
public static let header = L10n.tr("Localizable", "shortcuts.edit.sections.all.header")
|
||||||
public enum EnableVpn {
|
}
|
||||||
/// Enable VPN
|
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.enable_vpn.caption")
|
|
||||||
}
|
|
||||||
public enum TrustCellular {
|
|
||||||
/// Trust cellular network
|
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.trust_cellular.caption")
|
|
||||||
}
|
|
||||||
public enum TrustCurrentWifi {
|
|
||||||
/// Trust current Wi-Fi
|
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.trust_current_wifi.caption")
|
|
||||||
}
|
|
||||||
public enum UntrustCellular {
|
|
||||||
/// Untrust cellular network
|
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.untrust_cellular.caption")
|
|
||||||
}
|
|
||||||
public enum UntrustCurrentWifi {
|
|
||||||
/// Untrust current Wi-Fi
|
|
||||||
public static let caption = L10n.tr("Localizable", "shortcuts.cells.untrust_current_wifi.caption")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public enum Sections {
|
|
||||||
public enum Cellular {
|
|
||||||
/// Cellular
|
|
||||||
public static let header = L10n.tr("Localizable", "shortcuts.sections.cellular.header")
|
|
||||||
}
|
|
||||||
public enum Vpn {
|
|
||||||
/// VPN
|
|
||||||
public static let header = L10n.tr("Localizable", "shortcuts.sections.vpn.header")
|
|
||||||
}
|
|
||||||
public enum Wifi {
|
|
||||||
/// Wi-Fi
|
|
||||||
public static let header = L10n.tr("Localizable", "shortcuts.sections.wifi.header")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue