Commit efcc1085 authored by Jose Blaya's avatar Jose Blaya
Browse files

Siri Shortcuts for Connect and Disconnect the VPN

parent 22dacca1
This diff is collapsed.
......@@ -48,6 +48,11 @@ struct AppConstants {
static let adBlockerBundleIdentifier = "com.privateinternetaccess.ios.PIA-VPN.AdBlocker"
}
struct SiriShortcuts {
static let shortcutConnect = "com.privateinternetaccess.ios.PIA-VPN.connect"
static let shortcutDisconnect = "com.privateinternetaccess.ios.PIA-VPN.disconnect"
}
struct Web {
static let homeURL = URL(string: "https://www.privateinternetaccess.com/")!
......
......@@ -191,4 +191,24 @@ class AppDelegate: NSObject, UIApplicationDelegate {
}
}
//MARK: Siri Shortcuts
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
if userActivity.activityType == AppConstants.SiriShortcuts.shortcutConnect {
if AppPreferences.shared.useConnectSiriShortcuts {
Macros.dispatch(after: .milliseconds(200)) {
Client.providers.vpnProvider.connect(nil)
}
}
return AppPreferences.shared.useConnectSiriShortcuts
} else {
if AppPreferences.shared.useDisconnectSiriShortcuts {
Macros.dispatch(after: .milliseconds(200)) {
Client.providers.vpnProvider.disconnect(nil)
}
}
return AppPreferences.shared.useDisconnectSiriShortcuts
}
}
}
......@@ -10,6 +10,7 @@ import Foundation
import PIALibrary
import PIATunnel
import SwiftyBeaver
import Intents
private let log = SwiftyBeaver.self
......@@ -33,6 +34,13 @@ class AppPreferences {
static let favoriteServerIdentifiers = "FavoriteServerIdentifiers"
static let regionFilter = "RegionFilter"
static let useConnectSiriShortcuts = "UseConnectSiriShortcuts"
static let connectShortcut = "ConnectShortcut"
static let useDisconnectSiriShortcuts = "UseDisconnectSiriShortcuts"
static let disconnectShortcut = "disconnectShortcut"
}
static let shared = AppPreferences()
......@@ -132,6 +140,58 @@ class AppPreferences {
defaults.set(newValue.rawValue, forKey: Entries.regionFilter)
}
}
var useConnectSiriShortcuts: Bool {
get {
return defaults.bool(forKey: Entries.useConnectSiriShortcuts)
}
set {
defaults.set(newValue, forKey: Entries.useConnectSiriShortcuts)
}
}
var useDisconnectSiriShortcuts: Bool {
get {
return defaults.bool(forKey: Entries.useDisconnectSiriShortcuts)
}
set {
defaults.set(newValue, forKey: Entries.useDisconnectSiriShortcuts)
}
}
@available(iOS 12.0, *)
var connectShortcut: INVoiceShortcut? {
get {
if let data = defaults.object(forKey: Entries.connectShortcut) as? Data {
return NSKeyedUnarchiver.unarchiveObject(with: data) as? INVoiceShortcut
} else {
return nil
}
}
set {
if let newValue = newValue {
let encodedObject = NSKeyedArchiver.archivedData(withRootObject: newValue)
defaults.set(encodedObject, forKey: Entries.connectShortcut)
}
}
}
@available(iOS 12.0, *)
var disconnectShortcut: INVoiceShortcut? {
get {
if let data = defaults.object(forKey: Entries.disconnectShortcut) as? Data {
return NSKeyedUnarchiver.unarchiveObject(with: data) as? INVoiceShortcut
} else {
return nil
}
}
set {
if let newValue = newValue {
let encodedObject = NSKeyedArchiver.archivedData(withRootObject: newValue)
defaults.set(encodedObject, forKey: Entries.disconnectShortcut)
}
} }
private init() {
guard let defaults = UserDefaults(suiteName: AppConstants.appGroup) else {
......@@ -145,7 +205,9 @@ class AppPreferences {
Entries.regionFilter: RegionFilter.name.rawValue,
Entries.favoriteServerIdentifiers: [],
Entries.didAskToEnableNotifications: false,
Entries.themeCode: ThemeCode.light.rawValue
Entries.themeCode: ThemeCode.light.rawValue,
Entries.useConnectSiriShortcuts: false,
Entries.useDisconnectSiriShortcuts: false,
])
}
......@@ -234,11 +296,23 @@ class AppPreferences {
func reset() {
piaSocketType = nil
favoriteServerIdentifiers = []
useConnectSiriShortcuts = false
useDisconnectSiriShortcuts = false
if #available(iOS 12.0, *) {
connectShortcut = nil
disconnectShortcut = nil
}
transitionTheme(to: .light)
}
func clean() {
favoriteServerIdentifiers = []
useConnectSiriShortcuts = false
useDisconnectSiriShortcuts = false
if #available(iOS 12.0, *) {
connectShortcut = nil
disconnectShortcut = nil
}
}
// + (void)eraseForTesting;
......
......@@ -45,6 +45,11 @@
<string>Authenticate to reveal</string>
<key>NSCameraUsageDescription</key>
<string>We need camera access to scan a code from an gift card</string>
<key>NSUserActivityTypes</key>
<array>
<string>com.privateinternetaccess.ios.PIA-VPN.connect</string>
<string>com.privateinternetaccess.ios.PIA-VPN.disconnect</string>
</array>
<key>UIAppFonts</key>
<array>
<string>Roboto-Light.ttf</string>
......
......@@ -14,6 +14,8 @@
</array>
<key>com.apple.developer.networking.wifi-info</key>
<true/>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.privateinternetaccess</string>
......
......@@ -11,6 +11,8 @@ import PIALibrary
import PIATunnel
import SafariServices
import SwiftyBeaver
import Intents
import IntentsUI
private let log = SwiftyBeaver.self
......@@ -42,6 +44,10 @@ enum Setting: Int {
case trustedNetworks
case connectShortcut
case disconnectShortcut
case contentBlockerState
case contentBlockerRefreshRules
......@@ -175,6 +181,10 @@ class SettingsViewController: AutolayoutViewController {
private lazy var switchContentBlocker = FakeSwitch()
private lazy var switchDarkMode = UISwitch()
private lazy var switchConnectSiriShortcuts = UISwitch()
private lazy var switchDisconnectSiriShortcuts = UISwitch()
private lazy var imvSelectedOption = UIImageView(image: Asset.accessorySelected.image)
......@@ -235,6 +245,8 @@ class SettingsViewController: AutolayoutViewController {
// switchContentBlocker.isGrayed = true
switchContentBlocker.addTarget(self, action: #selector(showContentBlockerTutorial), for: .touchUpInside)
switchDarkMode.addTarget(self, action: #selector(toggleDarkMode(_:)), for: .valueChanged)
switchConnectSiriShortcuts.addTarget(self, action: #selector(toggleConnectSiriShortcuts(_:)), for: .valueChanged)
switchDisconnectSiriShortcuts.addTarget(self, action: #selector(toggleDisconnectSiriShortcuts(_:)), for: .valueChanged)
redisplaySettings()
NotificationCenter.default.addObserver(self, selector: #selector(refreshContentBlockerState), name: .UIApplicationDidBecomeActive, object: nil)
......@@ -295,6 +307,60 @@ class SettingsViewController: AutolayoutViewController {
AppPreferences.shared.transitionTheme(to: sender.isOn ? .dark : .light)
}
@objc private func toggleConnectSiriShortcuts(_ sender: UISwitch) {
if #available(iOS 12.0, *) {
if AppPreferences.shared.useConnectSiriShortcuts {
if let shortcut = AppPreferences.shared.connectShortcut {
let vc = INUIEditVoiceShortcutViewController(voiceShortcut: shortcut)
vc.delegate = self
present(vc, animated: true, completion: nil)
}
} else {
let connectActivity = NSUserActivity(activityType: AppConstants.SiriShortcuts.shortcutConnect)
connectActivity.title = L10n.Siri.Shortcuts.Connect.title
connectActivity.isEligibleForSearch = true
connectActivity.isEligibleForPrediction = true
connectActivity.persistentIdentifier = NSUserActivityPersistentIdentifier(AppConstants.SiriShortcuts.shortcutConnect)
let connectShortcut = INShortcut(userActivity: connectActivity)
let vc = INUIAddVoiceShortcutViewController(shortcut: connectShortcut)
vc.delegate = self
present(vc, animated: true, completion: nil)
}
tableView.reloadData()
}
}
@objc private func toggleDisconnectSiriShortcuts(_ sender: UISwitch) {
if #available(iOS 12.0, *) {
if AppPreferences.shared.useDisconnectSiriShortcuts {
if let shortcut = AppPreferences.shared.disconnectShortcut {
let vc = INUIEditVoiceShortcutViewController(voiceShortcut: shortcut)
vc.delegate = self
present(vc, animated: true, completion: nil)
}
} else {
let disconnectActivity = NSUserActivity(activityType: AppConstants.SiriShortcuts.shortcutDisconnect)
disconnectActivity.title = L10n.Siri.Shortcuts.Disconnect.title
disconnectActivity.isEligibleForSearch = true
disconnectActivity.isEligibleForPrediction = true
disconnectActivity.persistentIdentifier = NSUserActivityPersistentIdentifier(AppConstants.SiriShortcuts.shortcutDisconnect)
let disconnectShortcut = INShortcut(userActivity: disconnectActivity)
let vc = INUIAddVoiceShortcutViewController(shortcut: disconnectShortcut)
vc.delegate = self
present(vc, animated: true, completion: nil)
}
tableView.reloadData()
}
}
@objc private func showContentBlockerTutorial() {
perform(segue: StoryboardSegue.Main.contentBlockerSegueIdentifier)
}
......@@ -565,6 +631,11 @@ class SettingsViewController: AutolayoutViewController {
.automaticReconnection,
]
}
if #available(iOS 12.0, *) {
rowsBySection[.applicationSettings]?.insert(contentsOf: [.connectShortcut, .disconnectShortcut], at: 0)
}
if !Flags.shared.enablesContentBlockerSetting {
sections.remove(at: sections.index(of: .contentBlocker)!)
}
......@@ -859,6 +930,20 @@ extension SettingsViewController: UITableViewDataSource, UITableViewDelegate {
cell.selectionStyle = .none
switchDarkMode.isOn = (AppPreferences.shared.currentThemeCode == .dark)
case .connectShortcut:
cell.textLabel?.text = L10n.Siri.Shortcuts.Connect.Row.title
cell.detailTextLabel?.text = nil
cell.accessoryView = switchConnectSiriShortcuts
cell.selectionStyle = .none
switchConnectSiriShortcuts.isOn = AppPreferences.shared.useConnectSiriShortcuts
case .disconnectShortcut:
cell.textLabel?.text = L10n.Siri.Shortcuts.Disconnect.Row.title
cell.detailTextLabel?.text = nil
cell.accessoryView = switchDisconnectSiriShortcuts
cell.selectionStyle = .none
switchDisconnectSiriShortcuts.isOn = AppPreferences.shared.useDisconnectSiriShortcuts
case .sendDebugLog:
cell.textLabel?.text = L10n.Settings.ApplicationInformation.Debug.title
cell.detailTextLabel?.text = nil
......@@ -1368,3 +1453,64 @@ extension SettingsViewController: SettingsViewControllerDelegate {
}
}
@available(iOS 12.0, *)
extension SettingsViewController: INUIAddVoiceShortcutViewControllerDelegate {
func addVoiceShortcutViewController(
_ controller: INUIAddVoiceShortcutViewController,
didFinishWith voiceShortcut: INVoiceShortcut?,
error: Error?
) {
if let _ = error {
let message = L10n.Siri.Shortcuts.Add.error
let alert = Macros.alert(nil, message)
alert.addCancelActionWithTitle(L10n.Global.cancel) {
self.dismiss(animated: true, completion: nil)
}
self.present(alert, animated: true, completion: nil)
} else {
if let activityType = voiceShortcut?.shortcut.userActivity?.activityType {
if activityType == AppConstants.SiriShortcuts.shortcutConnect {
AppPreferences.shared.useConnectSiriShortcuts = true
AppPreferences.shared.connectShortcut = voiceShortcut
} else {
AppPreferences.shared.useDisconnectSiriShortcuts = true
AppPreferences.shared.disconnectShortcut = voiceShortcut
}
}
self.dismiss(animated: true, completion: nil)
}
}
func addVoiceShortcutViewControllerDidCancel(
_ controller: INUIAddVoiceShortcutViewController) {
dismiss(animated: true, completion: nil)
}
}
@available(iOS 12.0, *)
extension SettingsViewController: INUIEditVoiceShortcutViewControllerDelegate {
func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didUpdate voiceShortcut: INVoiceShortcut?, error: Error?) {
dismiss(animated: true, completion: nil)
}
func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID) {
if deletedVoiceShortcutIdentifier == AppPreferences.shared.connectShortcut?.identifier {
AppPreferences.shared.useConnectSiriShortcuts = false
AppPreferences.shared.connectShortcut = nil
} else {
AppPreferences.shared.useDisconnectSiriShortcuts = false
AppPreferences.shared.disconnectShortcut = nil
}
dismiss(animated: true, completion: nil)
}
func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) {
dismiss(animated: true, completion: nil)
}
}
......@@ -551,6 +551,31 @@ internal enum L10n {
internal static let selectRegion = L10n.tr("Localizable", "shortcuts.select_region")
}
internal enum Siri {
internal enum Shortcuts {
internal enum Add {
/// There was an error adding the Siri shortcut. Please, try it again.
internal static let error = L10n.tr("Localizable", "siri.shortcuts.add.error")
}
internal enum Connect {
/// Connect PIA VPN
internal static let title = L10n.tr("Localizable", "siri.shortcuts.connect.title")
internal enum Row {
/// 'Connect' Siri Shortcut
internal static let title = L10n.tr("Localizable", "siri.shortcuts.connect.row.title")
}
}
internal enum Disconnect {
/// Disconnect PIA VPN
internal static let title = L10n.tr("Localizable", "siri.shortcuts.disconnect.title")
internal enum Row {
/// 'Disconnect' Siri Shortcut
internal static let title = L10n.tr("Localizable", "siri.shortcuts.disconnect.row.title")
}
}
}
}
internal enum Tiles {
internal enum Nmt {
/// Cellular
......
......@@ -244,3 +244,9 @@
"tiles.nmt.accessibility.trusted" = "Trusted network";
"tiles.nmt.accessibility.untrusted" = "Untrusted network";
//SIRI SHORTCUTS
"siri.shortcuts.connect.row.title" = "'Connect' Siri Shortcut";
"siri.shortcuts.disconnect.row.title" = "'Disconnect' Siri Shortcut";
"siri.shortcuts.connect.title" = "Connect PIA VPN";
"siri.shortcuts.disconnect.title" = "Disconnect PIA VPN";
"siri.shortcuts.add.error" = "There was an error adding the Siri shortcut. Please, try it again.";
......@@ -52,8 +52,8 @@ end
def shared_main_pods
pod 'AlamofireImage'
library_by_path('/Users/ueshiba/Desktop/PIA')
#library_by_git('00efd81')
#library_by_path('')
library_by_git('acb3ee4')
#library_by_version('~> 1.1.3')
end
......
......@@ -114,10 +114,10 @@ DEPENDENCIES:
- FXPageControl
- HockeySDK
- iRate
- PIALibrary/Library (from `/Users/ueshiba/Desktop/PIA/client-library-apple`)
- PIALibrary/Mock (from `/Users/ueshiba/Desktop/PIA/client-library-apple`)
- PIALibrary/UI (from `/Users/ueshiba/Desktop/PIA/client-library-apple`)
- PIALibrary/VPN (from `/Users/ueshiba/Desktop/PIA/client-library-apple`)
- PIALibrary/Library (from `https://github.com/pia-foss/client-library-apple`, commit `acb3ee4`)
- PIALibrary/Mock (from `https://github.com/pia-foss/client-library-apple`, commit `acb3ee4`)
- PIALibrary/UI (from `https://github.com/pia-foss/client-library-apple`, commit `acb3ee4`)
- PIALibrary/VPN (from `https://github.com/pia-foss/client-library-apple`, commit `acb3ee4`)
- PIATunnel (from `https://github.com/pia-foss/tunnel-apple`, commit `bd53e0a`)
- PopupDialog
- SideMenu (= 3.1.5)
......@@ -154,12 +154,16 @@ SPEC REPOS:
EXTERNAL SOURCES:
PIALibrary:
:path: "/Users/ueshiba/Desktop/PIA/client-library-apple"
:commit: acb3ee4
:git: https://github.com/pia-foss/client-library-apple
PIATunnel:
:commit: bd53e0a
:git: https://github.com/pia-foss/tunnel-apple
CHECKOUT OPTIONS:
PIALibrary:
:commit: acb3ee4
:git: https://github.com/pia-foss/client-library-apple
PIATunnel:
:commit: bd53e0a
:git: https://github.com/pia-foss/tunnel-apple
......@@ -184,7 +188,7 @@ SPEC CHECKSUMS:
lottie-ios: 3fef45d3fabe63e3c7c2eb603dd64ddfffc73062
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
OpenSSL-Apple: cd153d705ef350eb834ae7ff5f21f792b51ed208
PIALibrary: ca9c4b28af7bd5012e5f66da5c7dab3c01b35f24
PIALibrary: 49067d695fe3597be7ce9561a635bbd47f0e6b48
PIATunnel: c0a1e40d198ebca00d192c5266c055f1ec5d4bab
PopupDialog: 03985b669c29802661c187513bf827340db1ae4d
QuickLayout: a730730b646b231fd4ef7cffaeb1e81fe0e1ca92
......@@ -194,6 +198,6 @@ SPEC CHECKSUMS:
SwiftyBeaver: ccfcdf85a04d429f1633f668650b0ce8020bda3a
TPKeyboardAvoiding: cb69d5ddbe90ce0170e4bc2db1e5e41d4a3ad9a4
PODFILE CHECKSUM: 358343444675ab4bef665969dc91f035756ed4c1
PODFILE CHECKSUM: f6c2e5e6a9dc42fe47d9678244cc0ee4f2d3871e
COCOAPODS: 1.5.3
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment