Show existing Siri shortcuts as first controller

This commit is contained in:
Davide De Rosa 2019-03-27 20:23:53 +01:00
parent b459495e90
commit d5b7a1e576
10 changed files with 368 additions and 99 deletions

View File

@ -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 shortcutsEditViewController = SceneType<UIKit.UINavigationController>(storyboard: Shortcuts.self, identifier: "ShortcutsEditViewController")
} }
} }
// 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

View File

@ -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

View File

@ -1,5 +1,5 @@
// //
// ShortcutsViewController.swift // ShortcutsAddViewController.swift
// Passepartout-iOS // Passepartout-iOS
// //
// Created by Davide De Rosa on 3/18/19. // Created by Davide De Rosa on 3/18/19.
@ -27,7 +27,7 @@ import UIKit
import IntentsUI import IntentsUI
import Passepartout_Core import Passepartout_Core
class ShortcutsViewController: UITableViewController, TableModelHost { class ShortcutsAddViewController: UITableViewController, TableModelHost {
// MARK: TableModel // MARK: TableModel
@ -39,9 +39,9 @@ class ShortcutsViewController: UITableViewController, TableModelHost {
model.set([.connect, .enableVPN, .disableVPN], in: .vpn) model.set([.connect, .enableVPN, .disableVPN], in: .vpn)
model.set([.trustCurrentWiFi, .untrustCurrentWiFi], in: .wifi) model.set([.trustCurrentWiFi, .untrustCurrentWiFi], in: .wifi)
model.set([.trustCellular, .untrustCellular], in: .cellular) model.set([.trustCellular, .untrustCellular], in: .cellular)
model.setHeader(L10n.Shortcuts.Sections.Vpn.header, for: .vpn) model.setHeader(L10n.Shortcuts.Add.Sections.Vpn.header, for: .vpn)
model.setHeader(L10n.Shortcuts.Sections.Wifi.header, for: .wifi) model.setHeader(L10n.Shortcuts.Add.Sections.Wifi.header, for: .wifi)
model.setHeader(L10n.Shortcuts.Sections.Cellular.header, for: .cellular) model.setHeader(L10n.Shortcuts.Add.Sections.Cellular.header, for: .cellular)
return model return model
}() }()
@ -53,11 +53,11 @@ class ShortcutsViewController: UITableViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Organizer.Cells.SiriShortcuts.caption title = L10n.Shortcuts.Add.title
} }
} }
extension ShortcutsViewController { extension ShortcutsAddViewController {
enum SectionType { enum SectionType {
case vpn case vpn
@ -98,25 +98,25 @@ extension ShortcutsViewController {
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 .connect:
cell.leftText = L10n.Shortcuts.Cells.Connect.caption cell.leftText = L10n.Shortcuts.Add.Cells.Connect.caption
case .enableVPN: case .enableVPN:
cell.leftText = L10n.Shortcuts.Cells.EnableVpn.caption cell.leftText = L10n.Shortcuts.Add.Cells.EnableVpn.caption
case .disableVPN: case .disableVPN:
cell.leftText = L10n.Shortcuts.Cells.DisableVpn.caption cell.leftText = L10n.Shortcuts.Add.Cells.DisableVpn.caption
case .trustCurrentWiFi: case .trustCurrentWiFi:
cell.leftText = L10n.Shortcuts.Cells.TrustCurrentWifi.caption cell.leftText = L10n.Shortcuts.Add.Cells.TrustCurrentWifi.caption
case .untrustCurrentWiFi: case .untrustCurrentWiFi:
cell.leftText = L10n.Shortcuts.Cells.UntrustCurrentWifi.caption cell.leftText = L10n.Shortcuts.Add.Cells.UntrustCurrentWifi.caption
case .trustCellular: case .trustCellular:
cell.leftText = L10n.Shortcuts.Cells.TrustCellular.caption cell.leftText = L10n.Shortcuts.Add.Cells.TrustCellular.caption
case .untrustCellular: case .untrustCellular:
cell.leftText = L10n.Shortcuts.Cells.UntrustCellular.caption cell.leftText = L10n.Shortcuts.Add.Cells.UntrustCellular.caption
} }
cell.apply(Theme.current) cell.apply(Theme.current)
return cell return cell
@ -154,12 +154,12 @@ extension ShortcutsViewController {
// MARK: Actions // MARK: Actions
@available(iOS 12, *) @available(iOS 12, *)
extension ShortcutsViewController { extension ShortcutsAddViewController {
private func addConnect() { private func addConnect() {
guard TransientStore.shared.service.hasProfiles() else { guard TransientStore.shared.service.hasProfiles() else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Shortcuts.Cells.Connect.caption, L10n.Shortcuts.Add.Cells.Connect.caption,
L10n.Shortcuts.Alerts.NoProfiles.message L10n.Shortcuts.Add.Alerts.NoProfiles.message
) )
alert.addAction(L10n.Global.ok) { alert.addAction(L10n.Global.ok) {
if let ip = self.tableView.indexPathForSelectedRow { if let ip = self.tableView.indexPathForSelectedRow {
@ -211,7 +211,7 @@ extension ShortcutsViewController {
} }
@available(iOS 12, *) @available(iOS 12, *)
extension ShortcutsViewController: INUIAddVoiceShortcutViewControllerDelegate { extension ShortcutsAddViewController: INUIAddVoiceShortcutViewControllerDelegate {
func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) { func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
tableView.reloadData() tableView.reloadData()
dismiss(animated: true, completion: nil) dismiss(animated: true, completion: nil)

View File

@ -65,7 +65,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()
} }

View File

@ -0,0 +1,196 @@
//
// ShortcutsEditViewController.swift
// Passepartout-iOS
//
// Created by Davide De Rosa on 3/27/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
private struct ShortcutWrapper {
let phrase: String
let intentDescription: String?
let original: Any?
@available(iOS 12, *)
static func from(_ vs: INVoiceShortcut) -> ShortcutWrapper {
return ShortcutWrapper(
phrase: vs.invocationPhrase,
intentDescription: vs.shortcut.intent?.suggestedInvocationPhrase,
original: vs
)
}
}
class ShortcutsEditViewController: UITableViewController, TableModelHost {
private var wrappers: [ShortcutWrapper]?
private var editedIndexPath: IndexPath?
// MARK: TableModel
let model: TableModel<SectionType, RowType> = {
let model: TableModel<SectionType, RowType> = TableModel()
model.add(.all)
model.setHeader(L10n.Shortcuts.Edit.Sections.All.header, for: .all)
model.set([], in: .all)
return model
}()
func reloadModel() {
model.set(.shortcut, count: wrappers?.count ?? 0, in: .all)
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
title = L10n.Organizer.Cells.SiriShortcuts.caption
guard #available(iOS 12, *) else {
return
}
INVoiceShortcutCenter.shared.getAllVoiceShortcuts { [weak self] (shortcuts, error) in
DispatchQueue.main.async {
guard let shortcuts = shortcuts else {
self?.handleShortcutsFetchError(error)
return
}
self?.handleShortcuts(shortcuts)
}
}
}
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)
}
@available(iOS 12, *)
private func handleShortcuts(_ shortcuts: [INVoiceShortcut]) {
wrappers = shortcuts.map { ShortcutWrapper.from($0) }
reloadModel()
tableView.reloadData()
}
@IBAction private func close() {
dismiss(animated: true, completion: nil)
}
}
extension ShortcutsEditViewController {
enum SectionType {
case all
}
enum RowType {
case shortcut
}
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 .shortcut:
guard let wrapper = wrappers?[indexPath.row] else {
break
}
cell.leftText = wrapper.phrase
cell.rightText = wrapper.intentDescription
}
cell.apply(Theme.current)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard #available(iOS 12, *) else {
return
}
switch model.row(at: indexPath) {
case .shortcut:
guard let wrapper = wrappers?[indexPath.row], let shortcut = wrapper.original as? INVoiceShortcut else {
break
}
let vc = INUIEditVoiceShortcutViewController(voiceShortcut: shortcut)
vc.delegate = self
editedIndexPath = indexPath
present(vc, animated: true, completion: nil)
}
}
}
@available(iOS 12, *)
extension ShortcutsEditViewController: INUIEditVoiceShortcutViewControllerDelegate {
func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) {
editedIndexPath = nil
dismiss(animated: true, completion: nil)
}
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)
dismiss(animated: true) {
self.tableView.reloadData()
}
}
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)
}
}
}

View File

@ -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>

View File

@ -1,5 +1,5 @@
<?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"> <device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/> <adaptation id="fullscreen"/>
</device> </device>
@ -9,10 +9,10 @@
<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="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -48,13 +48,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>
@ -126,20 +120,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="ShortcutsEditViewController" 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 Edit View Controller-->
<scene sceneID="ZRc-t3-Lf5">
<objects>
<tableViewController id="br5-OH-3al" customClass="ShortcutsEditViewController" 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="375" height="667"/>
<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="375" 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="375" 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="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="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Df7-oa-jnK">
<rect key="frame" x="16" 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>

View File

@ -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 /* ShortcutsEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E773BF7224BF37600CDDC8E /* ShortcutsEditViewController.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 /* ShortcutsEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsEditViewController.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>"; };
@ -417,7 +419,8 @@
0EFD943F215BED8E00529B64 /* LabelViewController.swift */, 0EFD943F215BED8E00529B64 /* LabelViewController.swift */,
0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */, 0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */,
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */, 0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */,
0E36D24C2240234B006AF062 /* ShortcutsViewController.swift */, 0E36D24C2240234B006AF062 /* ShortcutsAddViewController.swift */,
0E773BF7224BF37600CDDC8E /* ShortcutsEditViewController.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 /* ShortcutsEditViewController.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 */,

View File

@ -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,21 @@
"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";
"about.title" = "About"; "about.title" = "About";
"about.sections.web.header" = "Web"; "about.sections.web.header" = "Web";

View File

@ -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,68 @@ public enum L10n {
} }
public enum Shortcuts { public enum Shortcuts {
public enum Add {
/// Add shortcut
public static let title = L10n.tr("Localizable", "shortcuts.add.title")
public enum Alerts { public enum Alerts {
public enum NoProfiles { public enum NoProfiles {
/// There is no profile to connect to. /// There is no profile to connect to.
public static let message = L10n.tr("Localizable", "shortcuts.alerts.no_profiles.message") public static let message = L10n.tr("Localizable", "shortcuts.add.alerts.no_profiles.message")
} }
} }
public enum Cells { public enum Cells {
public enum Connect { public enum Connect {
/// Connect to /// Connect to
public static let caption = L10n.tr("Localizable", "shortcuts.cells.connect.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.connect.caption")
} }
public enum DisableVpn { public enum DisableVpn {
/// Disable VPN /// Disable VPN
public static let caption = L10n.tr("Localizable", "shortcuts.cells.disable_vpn.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.disable_vpn.caption")
} }
public enum EnableVpn { public enum EnableVpn {
/// Enable VPN /// Enable VPN
public static let caption = L10n.tr("Localizable", "shortcuts.cells.enable_vpn.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.enable_vpn.caption")
} }
public enum TrustCellular { public enum TrustCellular {
/// Trust cellular network /// Trust cellular network
public static let caption = L10n.tr("Localizable", "shortcuts.cells.trust_cellular.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.trust_cellular.caption")
} }
public enum TrustCurrentWifi { public enum TrustCurrentWifi {
/// Trust current Wi-Fi /// Trust current Wi-Fi
public static let caption = L10n.tr("Localizable", "shortcuts.cells.trust_current_wifi.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.trust_current_wifi.caption")
} }
public enum UntrustCellular { public enum UntrustCellular {
/// Untrust cellular network /// Untrust cellular network
public static let caption = L10n.tr("Localizable", "shortcuts.cells.untrust_cellular.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.untrust_cellular.caption")
} }
public enum UntrustCurrentWifi { public enum UntrustCurrentWifi {
/// Untrust current Wi-Fi /// Untrust current Wi-Fi
public static let caption = L10n.tr("Localizable", "shortcuts.cells.untrust_current_wifi.caption") public static let caption = L10n.tr("Localizable", "shortcuts.add.cells.untrust_current_wifi.caption")
} }
} }
public enum Sections { public enum Sections {
public enum Cellular { public enum Cellular {
/// Cellular /// Cellular
public static let header = L10n.tr("Localizable", "shortcuts.sections.cellular.header") public static let header = L10n.tr("Localizable", "shortcuts.add.sections.cellular.header")
} }
public enum Vpn { public enum Vpn {
/// VPN /// VPN
public static let header = L10n.tr("Localizable", "shortcuts.sections.vpn.header") public static let header = L10n.tr("Localizable", "shortcuts.add.sections.vpn.header")
} }
public enum Wifi { public enum Wifi {
/// Wi-Fi /// Wi-Fi
public static let header = L10n.tr("Localizable", "shortcuts.sections.wifi.header") public static let header = L10n.tr("Localizable", "shortcuts.add.sections.wifi.header")
}
}
}
public enum Edit {
/// Manage shortcuts
public static let title = L10n.tr("Localizable", "shortcuts.edit.title")
public enum Sections {
public enum All {
/// Existing shortcuts
public static let header = L10n.tr("Localizable", "shortcuts.edit.sections.all.header")
}
} }
} }
} }