Pick profile/location for connection intent
- Host: ConnectVPN intent - Provider: requires Pool selection
This commit is contained in:
parent
1ea85ff32e
commit
15602f7dc9
|
@ -21,6 +21,8 @@ internal enum StoryboardScene {
|
||||||
|
|
||||||
internal static let configurationIdentifier = SceneType<ConfigurationViewController>(storyboard: Main.self, identifier: "ConfigurationIdentifier")
|
internal static let configurationIdentifier = SceneType<ConfigurationViewController>(storyboard: Main.self, identifier: "ConfigurationIdentifier")
|
||||||
|
|
||||||
|
internal static let providerPoolViewController = SceneType<ProviderPoolViewController>(storyboard: Main.self, identifier: "ProviderPoolViewController")
|
||||||
|
|
||||||
internal static let serviceIdentifier = SceneType<UIKit.UINavigationController>(storyboard: Main.self, identifier: "ServiceIdentifier")
|
internal static let serviceIdentifier = SceneType<UIKit.UINavigationController>(storyboard: Main.self, identifier: "ServiceIdentifier")
|
||||||
}
|
}
|
||||||
internal enum Organizer: StoryboardType {
|
internal enum Organizer: StoryboardType {
|
||||||
|
@ -32,6 +34,11 @@ internal enum StoryboardScene {
|
||||||
|
|
||||||
internal static let wizardHostIdentifier = SceneType<UIKit.UINavigationController>(storyboard: Organizer.self, identifier: "WizardHostIdentifier")
|
internal static let wizardHostIdentifier = SceneType<UIKit.UINavigationController>(storyboard: Organizer.self, identifier: "WizardHostIdentifier")
|
||||||
}
|
}
|
||||||
|
internal enum Shortcuts: StoryboardType {
|
||||||
|
internal static let storyboardName = "Shortcuts"
|
||||||
|
|
||||||
|
internal static let initialScene = InitialSceneType<UIKit.UINavigationController>(storyboard: Shortcuts.self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@ internal enum StoryboardSegue {
|
||||||
case siriShortcutsSegueIdentifier = "SiriShortcutsSegueIdentifier"
|
case siriShortcutsSegueIdentifier = "SiriShortcutsSegueIdentifier"
|
||||||
case versionSegueIdentifier = "VersionSegueIdentifier"
|
case versionSegueIdentifier = "VersionSegueIdentifier"
|
||||||
}
|
}
|
||||||
|
internal enum Shortcuts: String, SegueType {
|
||||||
|
case connectToSegueIdentifier = "ConnectToSegueIdentifier"
|
||||||
|
case pickLocationSegueIdentifier = "PickLocationSegueIdentifier"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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,205 @@
|
||||||
|
//
|
||||||
|
// ShortcutsConnectToViewController.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 IntentsUI
|
||||||
|
import Passepartout_Core
|
||||||
|
|
||||||
|
class ShortcutsConnectToViewController: UITableViewController, TableModelHost {
|
||||||
|
private let service = TransientStore.shared.service
|
||||||
|
|
||||||
|
private var providers: [String] = []
|
||||||
|
|
||||||
|
private var hosts: [String] = []
|
||||||
|
|
||||||
|
private var selectedProfile: ConnectionProfile?
|
||||||
|
|
||||||
|
// MARK: TableModelHost
|
||||||
|
|
||||||
|
let model: TableModel<SectionType, RowType> = {
|
||||||
|
let model: TableModel<SectionType, RowType> = TableModel()
|
||||||
|
model.setHeader(L10n.Organizer.Sections.Providers.header, for: .providers)
|
||||||
|
model.setHeader(L10n.Organizer.Sections.Hosts.header, for: .hosts)
|
||||||
|
return model
|
||||||
|
}()
|
||||||
|
|
||||||
|
func reloadModel() {
|
||||||
|
providers = service.ids(forContext: .provider).sorted()
|
||||||
|
hosts = service.ids(forContext: .host).sortedCaseInsensitive()
|
||||||
|
|
||||||
|
if !providers.isEmpty {
|
||||||
|
model.add(.providers)
|
||||||
|
model.set(.providerShortcut, count: providers.count, in: .providers)
|
||||||
|
}
|
||||||
|
if !hosts.isEmpty {
|
||||||
|
model.add(.hosts)
|
||||||
|
model.set(.hostShortcut, count: hosts.count, in: .hosts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: UIViewController
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
title = L10n.Shortcuts.Cells.Connect.caption
|
||||||
|
reloadModel()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||||
|
guard identifier == StoryboardSegue.Shortcuts.pickLocationSegueIdentifier.rawValue else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
guard let _ = selectedProfile as? ProviderConnectionProfile else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||||
|
guard let vc = segue.destination as? ProviderPoolViewController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let provider = selectedProfile as? ProviderConnectionProfile else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vc.pools = provider.sortedPools()
|
||||||
|
vc.delegate = self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ShortcutsConnectToViewController {
|
||||||
|
enum SectionType {
|
||||||
|
case providers
|
||||||
|
|
||||||
|
case hosts
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RowType {
|
||||||
|
case providerShortcut
|
||||||
|
|
||||||
|
case hostShortcut
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
cell.apply(Theme.current)
|
||||||
|
switch model.row(at: indexPath) {
|
||||||
|
case .providerShortcut:
|
||||||
|
cell.leftText = providers[indexPath.row]
|
||||||
|
|
||||||
|
case .hostShortcut:
|
||||||
|
cell.leftText = hosts[indexPath.row]
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
guard #available(iOS 12, *) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch model.row(at: indexPath) {
|
||||||
|
case .providerShortcut:
|
||||||
|
selectedProfile = service.profile(withContext: .provider, id: providers[indexPath.row])
|
||||||
|
pickProviderLocation()
|
||||||
|
|
||||||
|
case .hostShortcut:
|
||||||
|
selectedProfile = service.profile(withContext: .host, id: hosts[indexPath.row])
|
||||||
|
addConnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Actions
|
||||||
|
|
||||||
|
@available(iOS 12, *)
|
||||||
|
extension ShortcutsConnectToViewController {
|
||||||
|
private func addConnect() {
|
||||||
|
guard let host = selectedProfile as? HostConnectionProfile else {
|
||||||
|
fatalError("Not a HostConnectionProfile")
|
||||||
|
}
|
||||||
|
let intent = ConnectVPNIntent()
|
||||||
|
intent.context = host.context.rawValue
|
||||||
|
intent.profileId = host.id
|
||||||
|
addShortcut(with: intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addMoveToLocation(pool: Pool) {
|
||||||
|
guard let provider = selectedProfile as? ProviderConnectionProfile else {
|
||||||
|
fatalError("Not a ProviderConnectionProfile")
|
||||||
|
}
|
||||||
|
let intent = MoveToLocationIntent()
|
||||||
|
intent.providerId = provider.id
|
||||||
|
intent.poolId = pool.id
|
||||||
|
intent.poolName = pool.name
|
||||||
|
addShortcut(with: intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func pickProviderLocation() {
|
||||||
|
perform(segue: StoryboardSegue.Shortcuts.pickLocationSegueIdentifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ShortcutsConnectToViewController: ProviderPoolViewControllerDelegate {
|
||||||
|
func providerPoolController(_: ProviderPoolViewController, didSelectPool pool: Pool) {
|
||||||
|
guard #available(iOS 12, *) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addMoveToLocation(pool: pool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 12, *)
|
||||||
|
extension ShortcutsConnectToViewController: INUIAddVoiceShortcutViewControllerDelegate {
|
||||||
|
func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
|
||||||
|
dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
|
||||||
|
dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,14 +152,20 @@ extension ShortcutsViewController {
|
||||||
@available(iOS 12, *)
|
@available(iOS 12, *)
|
||||||
extension ShortcutsViewController {
|
extension ShortcutsViewController {
|
||||||
private func addConnect() {
|
private func addConnect() {
|
||||||
// FIXME: show hosts and providers, host delegates selection, provider requires location
|
guard TransientStore.shared.service.hasProfiles() else {
|
||||||
let intent = ConnectVPNIntent()
|
let alert = Macros.alert(
|
||||||
guard let profileKey = TransientStore.shared.service.activeProfileKey else {
|
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)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
intent.context = profileKey.context.rawValue
|
perform(segue: StoryboardSegue.Shortcuts.connectToSegueIdentifier)
|
||||||
intent.profileId = profileKey.id
|
|
||||||
addShortcut(with: intent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addEnable() {
|
private func addEnable() {
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="zpj-mS-isI" kind="show" id="Qer-qI-Oyn"/>
|
<segue destination="zpj-mS-isI" kind="show" identifier="ConnectToSegueIdentifier" id="Qer-qI-Oyn"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="0dW-yk-veP" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="0dW-yk-veP" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
<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" textLabel="4LM-xw-0Rx" style="IBUITableViewCellStyleDefault" id="aw4-ca-yyE">
|
<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="375" 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">
|
||||||
|
@ -80,7 +80,14 @@
|
||||||
<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="0.0" width="343" height="43.5"/>
|
<rect key="frame" x="16" 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="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4RM-B9-uCO">
|
||||||
|
<rect key="frame" x="315" 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"/>
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
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 /* ShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D24C2240234B006AF062 /* ShortcutsViewController.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 */; };
|
||||||
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */; };
|
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */; };
|
||||||
0E4C9CBB20DCF0D600A0C59C /* DestructiveTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */; };
|
0E4C9CBB20DCF0D600A0C59C /* DestructiveTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */; };
|
||||||
0E4FD7F120D58618002221FF /* Macros.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7F020D58618002221FF /* Macros.swift */; };
|
0E4FD7F120D58618002221FF /* Macros.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7F020D58618002221FF /* Macros.swift */; };
|
||||||
|
@ -176,6 +177,7 @@
|
||||||
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 /* ShortcutsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsViewController.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>"; };
|
||||||
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>"; };
|
||||||
0E39BCF2214DA9310035E9DE /* AppConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = "<group>"; };
|
0E39BCF2214DA9310035E9DE /* AppConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = "<group>"; };
|
||||||
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionViewController.swift; sourceTree = "<group>"; };
|
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -411,6 +413,7 @@
|
||||||
0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */,
|
0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */,
|
||||||
0EFD943F215BED8E00529B64 /* LabelViewController.swift */,
|
0EFD943F215BED8E00529B64 /* LabelViewController.swift */,
|
||||||
0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */,
|
0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */,
|
||||||
|
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */,
|
||||||
0E36D24C2240234B006AF062 /* ShortcutsViewController.swift */,
|
0E36D24C2240234B006AF062 /* ShortcutsViewController.swift */,
|
||||||
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */,
|
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */,
|
||||||
0ED38AD8213F33150004D387 /* WizardHostViewController.swift */,
|
0ED38AD8213F33150004D387 /* WizardHostViewController.swift */,
|
||||||
|
@ -989,6 +992,7 @@
|
||||||
0EF5CF252141CE58004FF1BD /* HUD.swift in Sources */,
|
0EF5CF252141CE58004FF1BD /* HUD.swift in Sources */,
|
||||||
0E05C5D720D1645F006EE732 /* ToggleTableViewCell.swift in Sources */,
|
0E05C5D720D1645F006EE732 /* ToggleTableViewCell.swift in Sources */,
|
||||||
0E05C5D420D1645F006EE732 /* FieldTableViewCell.swift in Sources */,
|
0E05C5D420D1645F006EE732 /* FieldTableViewCell.swift in Sources */,
|
||||||
|
0E36D25C224034AD006AF062 /* ShortcutsConnectToViewController.swift in Sources */,
|
||||||
0E05C61D20D27C82006EE732 /* Theme.swift in Sources */,
|
0E05C61D20D27C82006EE732 /* Theme.swift in Sources */,
|
||||||
0ED38AEC2141260D0004D387 /* ConfigurationModificationDelegate.swift in Sources */,
|
0ED38AEC2141260D0004D387 /* ConfigurationModificationDelegate.swift in Sources */,
|
||||||
0ECEE45020E1182E00A6BB43 /* Theme+Cells.swift in Sources */,
|
0ECEE45020E1182E00A6BB43 /* Theme+Cells.swift in Sources */,
|
||||||
|
|
|
@ -201,6 +201,7 @@
|
||||||
"shortcuts.cells.untrust_wifi.caption" = "Untrust current Wi-Fi";
|
"shortcuts.cells.untrust_wifi.caption" = "Untrust current Wi-Fi";
|
||||||
"shortcuts.cells.trust_cellular.caption" = "Trust cellular network";
|
"shortcuts.cells.trust_cellular.caption" = "Trust cellular network";
|
||||||
"shortcuts.cells.untrust_cellular.caption" = "Untrust cellular network";
|
"shortcuts.cells.untrust_cellular.caption" = "Untrust cellular network";
|
||||||
|
"shortcuts.alerts.no_profiles.message" = "There is no profile to connect to.";
|
||||||
|
|
||||||
"about.title" = "About";
|
"about.title" = "About";
|
||||||
"about.sections.web.header" = "Web";
|
"about.sections.web.header" = "Web";
|
||||||
|
|
|
@ -291,6 +291,10 @@ public class ConnectionService: Codable {
|
||||||
|
|
||||||
// MARK: Profiles
|
// MARK: Profiles
|
||||||
|
|
||||||
|
public func hasProfiles() -> Bool {
|
||||||
|
return !cache.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
public func addProfile(_ profile: ConnectionProfile, credentials: Credentials?) -> Bool {
|
public func addProfile(_ profile: ConnectionProfile, credentials: Credentials?) -> Bool {
|
||||||
guard cache.index(forKey: ProfileKey(profile)) == nil else {
|
guard cache.index(forKey: ProfileKey(profile)) == nil else {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -651,6 +651,12 @@ public enum L10n {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Shortcuts {
|
public enum Shortcuts {
|
||||||
|
public enum Alerts {
|
||||||
|
public enum NoProfiles {
|
||||||
|
/// There is no profile to connect to.
|
||||||
|
public static let message = L10n.tr("Localizable", "shortcuts.alerts.no_profiles.message")
|
||||||
|
}
|
||||||
|
}
|
||||||
public enum Cells {
|
public enum Cells {
|
||||||
public enum Connect {
|
public enum Connect {
|
||||||
/// Connect to
|
/// Connect to
|
||||||
|
|
Loading…
Reference in New Issue