summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-12-05 11:10:48 +0100
committerAndrej Mihajlov <and@mullvad.net>2022-12-05 11:10:48 +0100
commit4e7baa1f1a194877a6cfcf9d193cd54f83be202b (patch)
treea39de241a3324436cb692474b9663da5ad754b25
parent423fdbcf086aa076a260c49682268e369cc0b08e (diff)
parentf14081c8afe513df060293d3362c10eaf8ab349a (diff)
downloadmullvadvpn-4e7baa1f1a194877a6cfcf9d193cd54f83be202b.tar.xz
mullvadvpn-4e7baa1f1a194877a6cfcf9d193cd54f83be202b.zip
Merge branch 'drop-intents-support'
-rw-r--r--ios/CHANGELOG.md3
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj24
-rw-r--r--ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme2
-rw-r--r--ios/MullvadVPN/AppDelegate.swift14
-rw-r--r--ios/MullvadVPN/Info.plist14
-rw-r--r--ios/MullvadVPN/IntentHandlers.swift89
-rw-r--r--ios/MullvadVPN/Intents.intentdefinition163
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift2
-rw-r--r--ios/MullvadVPN/SettingsDataSource.swift20
-rw-r--r--ios/MullvadVPN/SettingsNavigationController.swift4
-rw-r--r--ios/MullvadVPN/SettingsViewController.swift2
-rw-r--r--ios/MullvadVPN/ShortcutsDataSource.swift234
-rw-r--r--ios/MullvadVPN/ShortcutsDataSourceDelegate.swift14
-rw-r--r--ios/MullvadVPN/ShortcutsManager.swift64
-rw-r--r--ios/MullvadVPN/ShortcutsViewController.swift116
15 files changed, 3 insertions, 762 deletions
diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md
index 0cb7b673df..e8751c1985 100644
--- a/ios/CHANGELOG.md
+++ b/ios/CHANGELOG.md
@@ -30,9 +30,6 @@ Line wrap the file at 100 chars. Th
- Add revoked device view displayed when the app detects that device is no longer registered on
backend.
- Add ability to manage registered devices if too many devices detected during log-in.
-- Add intents: start VPN, stop VPN, reconnect VPN (acts as start VPN when the tunnel is down,
- otherwise picks new relay).
-- Add menu item to control shortcuts.
- Add continuous monitoring of tunnel connection. Verify ping replies to detect whether traffic is
really flowing.
- Check if device is revoked or account has expired when the tunnel fails to connect on each second
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 042c517930..244617b56f 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -163,8 +163,6 @@
5871167F2910035700D41AAC /* PreferencesInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871167E2910035700D41AAC /* PreferencesInteractor.swift */; };
5871FB96254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871FB95254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift */; };
5871FBA0254C26C00051A0A4 /* NSRegularExpression+IPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871FB9F254C26BF0051A0A4 /* NSRegularExpression+IPAddress.swift */; };
- 5872631B283F6EAB00E14ADF /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 5872631A283F6EAB00E14ADF /* Intents.intentdefinition */; };
- 5872631D283F755900E14ADF /* IntentHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5872631C283F755900E14ADF /* IntentHandlers.swift */; };
58727283265D173C00F315B2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 58727282265D173C00F315B2 /* LaunchScreen.storyboard */; };
5872D6E8286304DE00DB5F4E /* TermsOfService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5872D6E7286304DE00DB5F4E /* TermsOfService.swift */; };
587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587425C02299833500CA2045 /* RootContainerViewController.swift */; };
@@ -323,10 +321,6 @@
58FEEB46260A028D00A621A8 /* GeoJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FEEB45260A028D00A621A8 /* GeoJSON.swift */; };
58FEEB58260B662E00A621A8 /* AutomaticKeyboardResponder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FEEB57260B662E00A621A8 /* AutomaticKeyboardResponder.swift */; };
58FF2C03281BDE02009EF542 /* SettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FF2C02281BDE02009EF542 /* SettingsManager.swift */; };
- 753D6C0C28B4BF3E0052D9E1 /* ShortcutsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753D6C0B28B4BF3E0052D9E1 /* ShortcutsManager.swift */; };
- 75FD0C2128B108570021E33E /* ShortcutsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75FD0C2028B108570021E33E /* ShortcutsDataSource.swift */; };
- 75FD0C2328B109860021E33E /* ShortcutsDataSourceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75FD0C2228B109860021E33E /* ShortcutsDataSourceDelegate.swift */; };
- 75FD0C2528B117D30021E33E /* ShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75FD0C2428B117D30021E33E /* ShortcutsViewController.swift */; };
E1187ABC289BBB850024E748 /* OutOfTimeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1187ABA289BBB850024E748 /* OutOfTimeViewController.swift */; };
E1187ABD289BBB850024E748 /* OutOfTimeContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1187ABB289BBB850024E748 /* OutOfTimeContentView.swift */; };
E158B360285381C60002F069 /* StringFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E158B35F285381C60002F069 /* StringFormatter.swift */; };
@@ -672,8 +666,6 @@
5871167E2910035700D41AAC /* PreferencesInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesInteractor.swift; sourceTree = "<group>"; };
5871FB95254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsolidatedApplicationLog.swift; sourceTree = "<group>"; };
5871FB9F254C26BF0051A0A4 /* NSRegularExpression+IPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+IPAddress.swift"; sourceTree = "<group>"; };
- 5872631A283F6EAB00E14ADF /* Intents.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = Intents.intentdefinition; sourceTree = "<group>"; };
- 5872631C283F755900E14ADF /* IntentHandlers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandlers.swift; sourceTree = "<group>"; };
58727282265D173C00F315B2 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
5872D6E7286304DE00DB5F4E /* TermsOfService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfService.swift; sourceTree = "<group>"; };
587425C02299833500CA2045 /* RootContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootContainerViewController.swift; sourceTree = "<group>"; };
@@ -826,10 +818,6 @@
58FEEB45260A028D00A621A8 /* GeoJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJSON.swift; sourceTree = "<group>"; };
58FEEB57260B662E00A621A8 /* AutomaticKeyboardResponder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutomaticKeyboardResponder.swift; sourceTree = "<group>"; };
58FF2C02281BDE02009EF542 /* SettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsManager.swift; sourceTree = "<group>"; };
- 753D6C0B28B4BF3E0052D9E1 /* ShortcutsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsManager.swift; sourceTree = "<group>"; };
- 75FD0C2028B108570021E33E /* ShortcutsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsDataSource.swift; sourceTree = "<group>"; };
- 75FD0C2228B109860021E33E /* ShortcutsDataSourceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsDataSourceDelegate.swift; sourceTree = "<group>"; };
- 75FD0C2428B117D30021E33E /* ShortcutsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsViewController.swift; sourceTree = "<group>"; };
E1187ABA289BBB850024E748 /* OutOfTimeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutOfTimeViewController.swift; sourceTree = "<group>"; };
E1187ABB289BBB850024E748 /* OutOfTimeContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutOfTimeContentView.swift; sourceTree = "<group>"; };
E158B35F285381C60002F069 /* StringFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringFormatter.swift; sourceTree = "<group>"; };
@@ -1332,8 +1320,6 @@
58F3C0A3249CB069003E76BE /* HeaderBarView.swift */,
58FD5BF32428C67600112C88 /* InAppPurchaseButton.swift */,
58CE5E6F224146210008646E /* Info.plist */,
- 5872631C283F755900E14ADF /* IntentHandlers.swift */,
- 5872631A283F6EAB00E14ADF /* Intents.intentdefinition */,
58727282265D173C00F315B2 /* LaunchScreen.storyboard */,
58E20770274672CA00DE5D77 /* LaunchViewController.swift */,
583DA21325FA4B5C00318683 /* LocationDataSource.swift */,
@@ -1388,10 +1374,6 @@
58ACF64A26553C3F00ACE4B7 /* SettingsSwitchCell.swift */,
58CCA01122424D11004F3011 /* SettingsViewController.swift */,
58677711290976FB006F721F /* SettingsInteractor.swift */,
- 75FD0C2028B108570021E33E /* ShortcutsDataSource.swift */,
- 75FD0C2228B109860021E33E /* ShortcutsDataSourceDelegate.swift */,
- 753D6C0B28B4BF3E0052D9E1 /* ShortcutsManager.swift */,
- 75FD0C2428B117D30021E33E /* ShortcutsViewController.swift */,
58BA693023EADA6A009DC256 /* SimulatorTunnelProvider.swift */,
587A01FB23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift */,
58FD5BEF24238EB300112C88 /* SKProduct+Formatting.swift */,
@@ -2192,7 +2174,6 @@
588527B2276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift in Sources */,
58F1311527E0B2AB007AC5BC /* Result+Extensions.swift in Sources */,
5867770E29096984006F721F /* OutOfTimeInteractor.swift in Sources */,
- 5872631B283F6EAB00E14ADF /* Intents.intentdefinition in Sources */,
58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */,
5878A27129091CF20096FC88 /* AccountInteractor.swift in Sources */,
068CE5742927B7A400A068BB /* Migration.swift in Sources */,
@@ -2222,7 +2203,6 @@
5878A279290954790096FC88 /* ConnectInteractor.swift in Sources */,
582AE3102440A6CA00E6733A /* AccountTokenInput.swift in Sources */,
5820EDAB288FF0D2006BF4E4 /* DeviceRowView.swift in Sources */,
- 75FD0C2128B108570021E33E /* ShortcutsDataSource.swift in Sources */,
5846227726E22A7C0035F7C2 /* StorePaymentManagerDelegate.swift in Sources */,
58EF581125D69DB400AEBA94 /* StatusImageView.swift in Sources */,
58907D9524D17B4E00CFC3F5 /* DisconnectSplitButton.swift in Sources */,
@@ -2240,7 +2220,6 @@
E1187ABD289BBB850024E748 /* OutOfTimeContentView.swift in Sources */,
58CC40EF24A601900019D96E /* ObserverList.swift in Sources */,
58CCA01822426713004F3011 /* AccountViewController.swift in Sources */,
- 75FD0C2528B117D30021E33E /* ShortcutsViewController.swift in Sources */,
5871FBA0254C26C00051A0A4 /* NSRegularExpression+IPAddress.swift in Sources */,
58F7CA882692E34000FC59FD /* WireguardKeysContentView.swift in Sources */,
5878A27729093A4F0096FC88 /* StorePaymentBlockObserver.swift in Sources */,
@@ -2276,7 +2255,6 @@
586A950D290125F0007BAF2B /* PresentAlertOperation.swift in Sources */,
58B93A1326C3F13600A55733 /* TunnelState.swift in Sources */,
58FEEB46260A028D00A621A8 /* GeoJSON.swift in Sources */,
- 753D6C0C28B4BF3E0052D9E1 /* ShortcutsManager.swift in Sources */,
58CE5E64224146200008646E /* AppDelegate.swift in Sources */,
5878A27329091D6D0096FC88 /* TunnelBlockObserver.swift in Sources */,
5872D6E8286304DE00DB5F4E /* TermsOfService.swift in Sources */,
@@ -2288,7 +2266,6 @@
06410E04292D0F7100AFC18C /* SettingsParser.swift in Sources */,
5878A27D2909657C0096FC88 /* RevokedDeviceInteractor.swift in Sources */,
58677710290975E9006F721F /* SettingsInteractorFactory.swift in Sources */,
- 5872631D283F755900E14ADF /* IntentHandlers.swift in Sources */,
58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */,
06410DFE292CE18F00AFC18C /* KeychainSettingsStore.swift in Sources */,
580F8B8628197958002E0998 /* DNSSettings.swift in Sources */,
@@ -2298,7 +2275,6 @@
58293FAE2510CA58005D0BB5 /* ProblemReportViewController.swift in Sources */,
58B9EB152489139B00095626 /* DisplayChainedError.swift in Sources */,
587B753F2668E5A700DEF7E9 /* NotificationContainerView.swift in Sources */,
- 75FD0C2328B109860021E33E /* ShortcutsDataSourceDelegate.swift in Sources */,
58421034282E4B1500F24E46 /* TunnelSettingsV2+REST.swift in Sources */,
58F2E144276A13F300A79513 /* StartTunnelOperation.swift in Sources */,
5868BD33261DCD2600E6027F /* CustomSplitViewController.swift in Sources */,
diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme
index dc70ad4ec7..c0ec326af9 100644
--- a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme
+++ b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPN.xcscheme
@@ -88,7 +88,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- launchStyle = "0"
+ launchStyle = "1"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 1721f80261..27515a798e 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -7,7 +7,6 @@
//
import BackgroundTasks
-import Intents
import MullvadLogging
import MullvadREST
import Operations
@@ -156,19 +155,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
return true
}
- func application(_ application: UIApplication, handlerFor intent: INIntent) -> Any? {
- switch intent {
- case is StartVPNIntent:
- return StartVPNIntentHandler(tunnelManager: tunnelManager)
- case is StopVPNIntent:
- return StopVPNIntentHandler(tunnelManager: tunnelManager)
- case is ReconnectVPNIntent:
- return ReconnectVPNIntentHandler(tunnelManager: tunnelManager)
- default:
- return nil
- }
- }
-
// MARK: - UISceneSession lifecycle
func application(
diff --git a/ios/MullvadVPN/Info.plist b/ios/MullvadVPN/Info.plist
index 7fb1defbcf..9c9b1744e4 100644
--- a/ios/MullvadVPN/Info.plist
+++ b/ios/MullvadVPN/Info.plist
@@ -28,18 +28,6 @@
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
- <key>INIntentsRestrictedWhileLocked</key>
- <array>
- <string>StartVPNIntent</string>
- <string>StopVPNIntent</string>
- <string>ReconnectVPNIntent</string>
- </array>
- <key>INIntentsSupported</key>
- <array>
- <string>StartVPNIntent</string>
- <string>StopVPNIntent</string>
- <string>ReconnectVPNIntent</string>
- </array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
@@ -53,7 +41,7 @@
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
- <true/>
+ <false/>
</dict>
<key>UIBackgroundModes</key>
<array>
diff --git a/ios/MullvadVPN/IntentHandlers.swift b/ios/MullvadVPN/IntentHandlers.swift
deleted file mode 100644
index 434f09b8fe..0000000000
--- a/ios/MullvadVPN/IntentHandlers.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// IntentHandlers.swift
-// MullvadVPN
-//
-// Created by pronebird on 26/05/2022.
-// Copyright © 2022 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-final class StartVPNIntentHandler: NSObject, StartVPNIntentHandling {
- private let tunnelManager: TunnelManager
-
- init(tunnelManager: TunnelManager) {
- self.tunnelManager = tunnelManager
- }
-
- func handle(intent: StartVPNIntent, completion: @escaping (StartVPNIntentResponse) -> Void) {
- tunnelManager.startTunnel { operationCompletion in
- let code: StartVPNIntentResponseCode = operationCompletion.isSuccess
- ? .success
- : .failure
- let response = StartVPNIntentResponse(code: code, userActivity: nil)
-
- completion(response)
- }
- }
-}
-
-final class StopVPNIntentHandler: NSObject, StopVPNIntentHandling {
- private let tunnelManager: TunnelManager
-
- init(tunnelManager: TunnelManager) {
- self.tunnelManager = tunnelManager
- }
-
- func handle(intent: StopVPNIntent, completion: @escaping (StopVPNIntentResponse) -> Void) {
- tunnelManager.stopTunnel { operationCompletion in
- let code: StopVPNIntentResponseCode = operationCompletion.isSuccess
- ? .success
- : .failure
- let response = StopVPNIntentResponse(code: code, userActivity: nil)
-
- completion(response)
- }
- }
-}
-
-final class ReconnectVPNIntentHandler: NSObject, ReconnectVPNIntentHandling {
- private let tunnelManager: TunnelManager
-
- init(tunnelManager: TunnelManager) {
- self.tunnelManager = tunnelManager
- }
-
- func handle(
- intent: ReconnectVPNIntent,
- completion: @escaping (ReconnectVPNIntentResponse) -> Void
- ) {
- tunnelManager.reconnectTunnel(selectNewRelay: true) { operationCompletion in
- let error = operationCompletion.error
-
- let shouldStartTunnel: Bool
- if case .tunnelDown = error as? SendTunnelProviderMessageError {
- shouldStartTunnel = true
- } else {
- shouldStartTunnel = error is UnsetTunnelError
- }
-
- if shouldStartTunnel {
- self.tunnelManager.startTunnel { operationCompletion in
- completion(
- ReconnectVPNIntentResponse(
- code: operationCompletion.isSuccess ? .success : .failure,
- userActivity: nil
- )
- )
- }
- } else {
- completion(
- ReconnectVPNIntentResponse(
- code: operationCompletion.isSuccess ? .success : .failure,
- userActivity: nil
- )
- )
- }
- }
- }
-}
diff --git a/ios/MullvadVPN/Intents.intentdefinition b/ios/MullvadVPN/Intents.intentdefinition
deleted file mode 100644
index c05dda03cc..0000000000
--- a/ios/MullvadVPN/Intents.intentdefinition
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>INEnums</key>
- <array/>
- <key>INIntentDefinitionModelVersion</key>
- <string>1.2</string>
- <key>INIntentDefinitionNamespace</key>
- <string>5pIysl</string>
- <key>INIntentDefinitionSystemVersion</key>
- <string>21F79</string>
- <key>INIntentDefinitionToolsBuildVersion</key>
- <string>13F100</string>
- <key>INIntentDefinitionToolsVersion</key>
- <string>13.4.1</string>
- <key>INIntents</key>
- <array>
- <dict>
- <key>INIntentCategory</key>
- <string>generic</string>
- <key>INIntentConfigurable</key>
- <true/>
- <key>INIntentDescriptionID</key>
- <string>jBv2Ko</string>
- <key>INIntentIneligibleForSuggestions</key>
- <true/>
- <key>INIntentManagedParameterCombinations</key>
- <dict>
- <key></key>
- <dict>
- <key>INIntentParameterCombinationSupportsBackgroundExecution</key>
- <true/>
- <key>INIntentParameterCombinationUpdatesLinked</key>
- <true/>
- </dict>
- </dict>
- <key>INIntentName</key>
- <string>StartVPN</string>
- <key>INIntentResponse</key>
- <dict>
- <key>INIntentResponseCodes</key>
- <array>
- <dict>
- <key>INIntentResponseCodeName</key>
- <string>success</string>
- <key>INIntentResponseCodeSuccess</key>
- <true/>
- </dict>
- <dict>
- <key>INIntentResponseCodeName</key>
- <string>failure</string>
- </dict>
- </array>
- <key>INIntentResponseLastParameterTag</key>
- <integer>1</integer>
- </dict>
- <key>INIntentTitle</key>
- <string>Start VPN</string>
- <key>INIntentTitleID</key>
- <string>EpurV0</string>
- <key>INIntentType</key>
- <string>Custom</string>
- <key>INIntentVerb</key>
- <string>Do</string>
- </dict>
- <dict>
- <key>INIntentCategory</key>
- <string>generic</string>
- <key>INIntentConfigurable</key>
- <true/>
- <key>INIntentDescriptionID</key>
- <string>uwGwEw</string>
- <key>INIntentIneligibleForSuggestions</key>
- <true/>
- <key>INIntentManagedParameterCombinations</key>
- <dict>
- <key></key>
- <dict>
- <key>INIntentParameterCombinationSupportsBackgroundExecution</key>
- <true/>
- <key>INIntentParameterCombinationUpdatesLinked</key>
- <true/>
- </dict>
- </dict>
- <key>INIntentName</key>
- <string>StopVPN</string>
- <key>INIntentResponse</key>
- <dict>
- <key>INIntentResponseCodes</key>
- <array>
- <dict>
- <key>INIntentResponseCodeName</key>
- <string>success</string>
- <key>INIntentResponseCodeSuccess</key>
- <true/>
- </dict>
- <dict>
- <key>INIntentResponseCodeName</key>
- <string>failure</string>
- </dict>
- </array>
- </dict>
- <key>INIntentTitle</key>
- <string>Stop VPN</string>
- <key>INIntentTitleID</key>
- <string>4GnhAo</string>
- <key>INIntentType</key>
- <string>Custom</string>
- <key>INIntentVerb</key>
- <string>Do</string>
- </dict>
- <dict>
- <key>INIntentCategory</key>
- <string>generic</string>
- <key>INIntentConfigurable</key>
- <true/>
- <key>INIntentDescriptionID</key>
- <string>SPC7AD</string>
- <key>INIntentIneligibleForSuggestions</key>
- <true/>
- <key>INIntentManagedParameterCombinations</key>
- <dict>
- <key></key>
- <dict>
- <key>INIntentParameterCombinationSupportsBackgroundExecution</key>
- <true/>
- <key>INIntentParameterCombinationUpdatesLinked</key>
- <true/>
- </dict>
- </dict>
- <key>INIntentName</key>
- <string>ReconnectVPN</string>
- <key>INIntentResponse</key>
- <dict>
- <key>INIntentResponseCodes</key>
- <array>
- <dict>
- <key>INIntentResponseCodeName</key>
- <string>success</string>
- <key>INIntentResponseCodeSuccess</key>
- <true/>
- </dict>
- <dict>
- <key>INIntentResponseCodeName</key>
- <string>failure</string>
- </dict>
- </array>
- </dict>
- <key>INIntentTitle</key>
- <string>Reconnect VPN</string>
- <key>INIntentTitleID</key>
- <string>puJvsb</string>
- <key>INIntentType</key>
- <string>Custom</string>
- <key>INIntentVerb</key>
- <string>Do</string>
- </dict>
- </array>
- <key>INTypes</key>
- <array/>
-</dict>
-</plist>
diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift
index 03f6bc3674..b022aa2772 100644
--- a/ios/MullvadVPN/SceneDelegate.swift
+++ b/ios/MullvadVPN/SceneDelegate.swift
@@ -155,8 +155,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDe
)
}
- ShortcutsManager.shared.updateVoiceShortcuts()
-
setShowsPrivacyOverlay(false)
}
diff --git a/ios/MullvadVPN/SettingsDataSource.swift b/ios/MullvadVPN/SettingsDataSource.swift
index ed4bf23c3d..e2510baf20 100644
--- a/ios/MullvadVPN/SettingsDataSource.swift
+++ b/ios/MullvadVPN/SettingsDataSource.swift
@@ -43,7 +43,6 @@ final class SettingsDataSource: NSObject, UITableViewDataSource, UITableViewDele
enum Item: String {
case account
case preferences
- case shortcuts
case version
case problemReport
case faq
@@ -98,7 +97,7 @@ final class SettingsDataSource: NSObject, UITableViewDataSource, UITableViewDele
if interactor.deviceState.isLoggedIn {
newSnapshot.appendSections([.main])
- newSnapshot.appendItems([.account, .preferences, .shortcuts], in: .main)
+ newSnapshot.appendItems([.account, .preferences], in: .main)
}
newSnapshot.appendSections([.version, .problemReport])
@@ -158,23 +157,6 @@ final class SettingsDataSource: NSObject, UITableViewDataSource, UITableViewDele
return cell
- case .shortcuts:
- let cell = tableView.dequeueReusableCell(
- withIdentifier: CellReuseIdentifiers.basicCell.rawValue,
- for: indexPath
- ) as! SettingsCell
- cell.titleLabel.text = NSLocalizedString(
- "SHORTCUTS_CELL_LABEL",
- tableName: "Settings",
- value: "Shortcuts",
- comment: ""
- )
- cell.detailTitleLabel.text = nil
- cell.accessibilityIdentifier = nil
- cell.disclosureType = .chevron
-
- return cell
-
case .version:
let cell = tableView.dequeueReusableCell(
withIdentifier: CellReuseIdentifiers.basicCell.rawValue,
diff --git a/ios/MullvadVPN/SettingsNavigationController.swift b/ios/MullvadVPN/SettingsNavigationController.swift
index 6656eb2acb..c43da954cc 100644
--- a/ios/MullvadVPN/SettingsNavigationController.swift
+++ b/ios/MullvadVPN/SettingsNavigationController.swift
@@ -12,7 +12,6 @@ enum SettingsNavigationRoute {
case root
case account
case preferences
- case shortcuts
case problemReport
}
@@ -123,9 +122,6 @@ class SettingsNavigationController: CustomNavigationController, SettingsViewCont
interactor: interactorFactory.makePreferencesInteractor()
)
- case .shortcuts:
- return ShortcutsViewController()
-
case .problemReport:
return ProblemReportViewController(
interactor: interactorFactory.makeProblemReportInteractor()
diff --git a/ios/MullvadVPN/SettingsViewController.swift b/ios/MullvadVPN/SettingsViewController.swift
index 3f5ce245df..2dd09d4d20 100644
--- a/ios/MullvadVPN/SettingsViewController.swift
+++ b/ios/MullvadVPN/SettingsViewController.swift
@@ -104,8 +104,6 @@ extension SettingsDataSource.Item {
return .account
case .preferences:
return .preferences
- case .shortcuts:
- return .shortcuts
case .version:
return nil
case .problemReport:
diff --git a/ios/MullvadVPN/ShortcutsDataSource.swift b/ios/MullvadVPN/ShortcutsDataSource.swift
deleted file mode 100644
index 429d196246..0000000000
--- a/ios/MullvadVPN/ShortcutsDataSource.swift
+++ /dev/null
@@ -1,234 +0,0 @@
-//
-// ShortcutsDataSource.swift
-// MullvadVPN
-//
-// Created by Nikolay Davydov on 20.08.2022.
-// Copyright © 2022 Mullvad VPN AB. All rights reserved.
-//
-
-import IntentsUI
-import UIKit
-
-final class ShortcutsDataSource: NSObject,
- UITableViewDataSource,
- UITableViewDelegate,
- ShortcutsManagerDelegate
-{
- private enum CellReuseIdentifiers: String, CaseIterable {
- case basicCell
-
- var reusableViewClass: AnyClass {
- switch self {
- case .basicCell:
- return SettingsCell.self
- }
- }
- }
-
- private enum HeaderFooterReuseIdentifier: String, CaseIterable {
- case spacer
-
- var reusableViewClass: AnyClass {
- switch self {
- case .spacer:
- return EmptyTableViewHeaderFooterView.self
- }
- }
- }
-
- enum Section: String {
- case shortcuts
- }
-
- struct Item: Hashable {
- let title: String
- let shortcut: INShortcut
- let voiceShortcut: INVoiceShortcut?
-
- var isAdded: Bool {
- return voiceShortcut != nil
- }
- }
-
- private var snapshot = DataSourceSnapshot<Section, Item>()
-
- weak var delegate: ShortcutsDataSourceDelegate?
-
- weak var tableView: UITableView? {
- didSet {
- tableView?.delegate = self
- tableView?.dataSource = self
-
- registerClasses()
- }
- }
-
- override init() {
- super.init()
- updateDataSnapshot(voiceShortcuts: [])
- ShortcutsManager.shared.delegate = self
- ShortcutsManager.shared.updateVoiceShortcuts()
- }
-
- private func registerClasses() {
- CellReuseIdentifiers.allCases.forEach { cellIdentifier in
- tableView?.register(
- cellIdentifier.reusableViewClass,
- forCellReuseIdentifier: cellIdentifier.rawValue
- )
- }
-
- HeaderFooterReuseIdentifier.allCases.forEach { reuseIdentifier in
- tableView?.register(
- reuseIdentifier.reusableViewClass,
- forHeaderFooterViewReuseIdentifier: reuseIdentifier.rawValue
- )
- }
- }
-
- private func updateDataSnapshot(voiceShortcuts: [INVoiceShortcut]) {
- var items = [Item]()
-
- for data in ShortcutData.allCases {
- guard let shortcut = data.shortcut else { continue }
- let voiceShortcut = voiceShortcuts.first(where: { voiceShortcut in
- isVoiceShortcut(voiceShortcut, invokes: shortcut)
- })
- let item = Item(
- title: data.title,
- shortcut: shortcut,
- voiceShortcut: voiceShortcut
- )
- items.append(item)
- }
-
- var newSnapshot = DataSourceSnapshot<Section, Item>()
- newSnapshot.appendSections([.shortcuts])
- newSnapshot.appendItems(items, in: .shortcuts)
-
- snapshot = newSnapshot
- }
-
- /// Returns whether the voice shortcut performs the same action as the specified shortcut.
- private func isVoiceShortcut(
- _ voiceShortcut: INVoiceShortcut,
- invokes shortcut: INShortcut
- ) -> Bool {
- if let a = voiceShortcut.shortcut.intent, let b = shortcut.intent {
- return type(of: a) == type(of: b)
- }
- return false
- }
-
- // MARK: - UITableViewDataSource
-
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- let sectionIdentifier = snapshot.section(at: section)!
- return snapshot.numberOfItems(in: sectionIdentifier) ?? 0
- }
-
- func numberOfSections(in tableView: UITableView) -> Int {
- return snapshot.numberOfSections()
- }
-
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let item = snapshot.itemForIndexPath(indexPath)!
- let cell = tableView.dequeueReusableCell(
- withIdentifier: CellReuseIdentifiers.basicCell.rawValue,
- for: indexPath
- )
- if let cell = cell as? SettingsCell {
- cell.titleLabel.text = item.title
- cell.disclosureType = item.isAdded ? .tick : .none
- }
- return cell
- }
-
- // MARK: - UITableViewDelegate
-
- func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- guard let item = snapshot.itemForIndexPath(indexPath) else { return }
- delegate?.shortcutsDataSource(self, didSelectItem: item)
- tableView.deselectRow(at: indexPath, animated: true)
- }
-
- func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
- return tableView.dequeueReusableHeaderFooterView(
- withIdentifier: HeaderFooterReuseIdentifier.spacer.rawValue
- )
- }
-
- func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
- return nil
- }
-
- func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
- return UIMetrics.sectionSpacing
- }
-
- func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
- return 0
- }
-
- // MARK: - ShortcutsManagerDelegate
-
- func shortcutsManager(
- _ shortcutsManager: ShortcutsManager,
- didReceiveVoiceShortcuts voiceShortcuts: [INVoiceShortcut]
- ) {
- updateDataSnapshot(voiceShortcuts: voiceShortcuts)
- tableView?.reloadData()
- }
-}
-
-private extension ShortcutsDataSource {
- enum ShortcutData: CaseIterable {
- case start
- case reconnect
- case stop
-
- var title: String {
- switch self {
- case .start:
- return NSLocalizedString(
- "SHORTCUTS_NAME_START_VPN",
- tableName: "Shortcuts",
- value: "Start VPN",
- comment: ""
- )
- case .reconnect:
- return NSLocalizedString(
- "SHORTCUTS_NAME_RECONNECT_VPN",
- tableName: "Shortcuts",
- value: "Reconnect VPN",
- comment: ""
- )
- case .stop:
- return NSLocalizedString(
- "SHORTCUTS_NAME_STOP_VPN",
- tableName: "Shortcuts",
- value: "Stop VPN",
- comment: ""
- )
- }
- }
-
- var shortcut: INShortcut? {
- let intent: INIntent
- switch self {
- case .start:
- intent = StartVPNIntent()
- case .reconnect:
- intent = ReconnectVPNIntent()
- case .stop:
- intent = StopVPNIntent()
- }
- intent.suggestedInvocationPhrase = title
- guard let shortcut = INShortcut(intent: intent) else {
- assertionFailure("The shortcut has an invalid intent.")
- return nil
- }
- return shortcut
- }
- }
-}
diff --git a/ios/MullvadVPN/ShortcutsDataSourceDelegate.swift b/ios/MullvadVPN/ShortcutsDataSourceDelegate.swift
deleted file mode 100644
index 2fde666721..0000000000
--- a/ios/MullvadVPN/ShortcutsDataSourceDelegate.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// ShortcutsDataSourceDelegate.swift
-// MullvadVPN
-//
-// Created by Nikolay Davydov on 20.08.2022.
-// Copyright © 2022 Mullvad VPN AB. All rights reserved.
-//
-
-protocol ShortcutsDataSourceDelegate: AnyObject {
- func shortcutsDataSource(
- _ dataSource: ShortcutsDataSource,
- didSelectItem item: ShortcutsDataSource.Item
- )
-}
diff --git a/ios/MullvadVPN/ShortcutsManager.swift b/ios/MullvadVPN/ShortcutsManager.swift
deleted file mode 100644
index a991c38c65..0000000000
--- a/ios/MullvadVPN/ShortcutsManager.swift
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// ShortcutsManager.swift
-// MullvadVPN
-//
-// Created by Nikolay Davydov on 23.08.2022.
-// Copyright © 2022 Mullvad VPN AB. All rights reserved.
-//
-
-import IntentsUI
-import MullvadLogging
-
-protocol ShortcutsManagerDelegate: AnyObject {
- func shortcutsManager(
- _ shortcutsManager: ShortcutsManager,
- didReceiveVoiceShortcuts voiceShortcuts: [INVoiceShortcut]
- )
-}
-
-final class ShortcutsManager {
- static let shared = ShortcutsManager()
-
- private init() {}
-
- private let logger = Logger(label: "ShortcutsManager")
-
- private var voiceShortcutsByID = [UUID: INVoiceShortcut]() {
- didSet {
- let voiceShortcuts = voiceShortcutsByID.map { $0.value }
- delegate?.shortcutsManager(self, didReceiveVoiceShortcuts: voiceShortcuts)
- }
- }
-
- weak var delegate: ShortcutsManagerDelegate?
-
- func updateVoiceShortcuts() {
- guard delegate != nil else { return }
- INVoiceShortcutCenter.shared.getAllVoiceShortcuts { [weak self] voiceShortcuts, error in
- guard let self = self else { return }
- if let error = error {
- self.logger.error(
- error: error,
- message: "Failed to fetch voice shortcuts."
- )
- return
- }
- let voiceShortcuts = voiceShortcuts ?? []
- let voiceShortcutsByID = voiceShortcuts
- .reduce(into: [UUID: INVoiceShortcut]()) { result, voiceShortcut in
- result[voiceShortcut.identifier] = voiceShortcut
- }
- DispatchQueue.main.async {
- self.voiceShortcutsByID = voiceShortcutsByID
- }
- }
- }
-
- func addVoiceShortcut(_ voiceShortcut: INVoiceShortcut) {
- voiceShortcutsByID[voiceShortcut.identifier] = voiceShortcut
- }
-
- func deleteVoiceShortcut(withIdentifier identifier: UUID) {
- voiceShortcutsByID[identifier] = nil
- }
-}
diff --git a/ios/MullvadVPN/ShortcutsViewController.swift b/ios/MullvadVPN/ShortcutsViewController.swift
deleted file mode 100644
index 953639dca3..0000000000
--- a/ios/MullvadVPN/ShortcutsViewController.swift
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-// ShortcutsViewController.swift
-// MullvadVPN
-//
-// Created by Nikolay Davydov on 20.08.2022.
-// Copyright © 2022 Mullvad VPN AB. All rights reserved.
-//
-
-import IntentsUI
-import UIKit
-
-final class ShortcutsViewController: UITableViewController,
- ShortcutsDataSourceDelegate,
- INUIAddVoiceShortcutViewControllerDelegate,
- INUIEditVoiceShortcutViewControllerDelegate
-{
- private let dataSource = ShortcutsDataSource()
-
- override var preferredStatusBarStyle: UIStatusBarStyle {
- return .lightContent
- }
-
- init() {
- super.init(style: .grouped)
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- tableView.backgroundColor = .secondaryColor
- tableView.separatorColor = .secondaryColor
- tableView.rowHeight = UITableView.automaticDimension
- tableView.estimatedRowHeight = 60
-
- dataSource.tableView = tableView
- dataSource.delegate = self
-
- navigationItem.title = NSLocalizedString(
- "NAVIGATION_TITLE",
- tableName: "Shortcuts",
- value: "Shortcuts",
- comment: ""
- )
- }
-
- // MARK: - ShortcutsDataSourceDelegate
-
- func shortcutsDataSource(
- _ dataSource: ShortcutsDataSource,
- didSelectItem item: ShortcutsDataSource.Item
- ) {
- let controller: UIViewController
- if let voiceShortcut = item.voiceShortcut {
- let editShortcutController = INUIEditVoiceShortcutViewController(
- voiceShortcut: voiceShortcut
- )
- editShortcutController.delegate = self
- controller = editShortcutController
- } else {
- let addShortcutController = INUIAddVoiceShortcutViewController(
- shortcut: item.shortcut
- )
- addShortcutController.delegate = self
- controller = addShortcutController
- }
- controller.modalPresentationStyle = .formSheet
- present(controller, animated: true)
- }
-
- // MARK: - INUIAddVoiceShortcutViewControllerDelegate
-
- func addVoiceShortcutViewController(
- _ controller: INUIAddVoiceShortcutViewController,
- didFinishWith voiceShortcut: INVoiceShortcut?,
- error: Error?
- ) {
- if let voiceShortcut = voiceShortcut {
- ShortcutsManager.shared.addVoiceShortcut(voiceShortcut)
- }
- controller.dismiss(animated: true)
- }
-
- func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
- controller.dismiss(animated: true)
- }
-
- // MARK: - INUIEditVoiceShortcutViewControllerDelegate
-
- func editVoiceShortcutViewController(
- _ controller: INUIEditVoiceShortcutViewController,
- didUpdate voiceShortcut: INVoiceShortcut?,
- error: Error?
- ) {
- controller.dismiss(animated: true)
- }
-
- func editVoiceShortcutViewController(
- _ controller: INUIEditVoiceShortcutViewController,
- didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID
- ) {
- ShortcutsManager.shared.deleteVoiceShortcut(
- withIdentifier: deletedVoiceShortcutIdentifier
- )
- controller.dismiss(animated: true)
- }
-
- func editVoiceShortcutViewControllerDidCancel(
- _ controller: INUIEditVoiceShortcutViewController
- ) {
- controller.dismiss(animated: true)
- }
-}