Skip to content

Commit

Permalink
Merge pull request #457 from ivpn/bugfix/ios18-shortcuts
Browse files Browse the repository at this point in the history
[iOS 18] IVPN shortcuts are not available
  • Loading branch information
jurajhilje authored Sep 17, 2024
2 parents 3ba9026 + c1363c4 commit 3d4d3a8
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 106 deletions.
16 changes: 8 additions & 8 deletions IVPNClient.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
8206BAFF29ED6FFF00F916B7 /* ConnectionInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206BAFE29ED6FFF00F916B7 /* ConnectionInfoView.swift */; };
8206BB0129ED7BEE00F916B7 /* ConnectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206BB0029ED7BEE00F916B7 /* ConnectionInfo.swift */; };
8206BB0329ED7C3700F916B7 /* ConnectionInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206BB0229ED7C3700F916B7 /* ConnectionInfoViewModel.swift */; };
8206E5D022967E37003119AF /* UserActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206E5CF22967E37003119AF /* UserActivityType.swift */; };
8206E5D222967EAF003119AF /* UserActivityTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206E5D122967EAF003119AF /* UserActivityTitle.swift */; };
8206F32124347A8F0056B465 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206F32024347A8F0056B465 /* MainView.swift */; };
8206F32324367A240056B465 /* VPNErrorObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8206F32224367A240056B465 /* VPNErrorObserver.swift */; };
8208525623FD56870008C112 /* FloatingPanelMainLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8208525523FD56870008C112 /* FloatingPanelMainLayout.swift */; };
Expand Down Expand Up @@ -151,6 +149,7 @@
828772F7221C008100D5E330 /* ServerConfigurationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828772F6221C008100D5E330 /* ServerConfigurationCell.swift */; };
828772F9221C01C300D5E330 /* ServersConfigurationTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828772F8221C01C300D5E330 /* ServersConfigurationTableViewController.swift */; };
828772FB221C28E000D5E330 /* FlagImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828772FA221C28E000D5E330 /* FlagImageView.swift */; };
828C45692C88772E0064F365 /* AppIntentsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828C45682C8877290064F365 /* AppIntentsHandler.swift */; };
828D8A6D258245AD00CB0E5B /* TwoFactorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828D8A6C258245AD00CB0E5B /* TwoFactorViewController.swift */; };
828E9C95231E5780001E1FCF /* Data+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828E9C94231E5780001E1FCF /* Data+Ext.swift */; };
828E9C96231E5780001E1FCF /* Data+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828E9C94231E5780001E1FCF /* Data+Ext.swift */; };
Expand Down Expand Up @@ -267,6 +266,7 @@
82DB75EE239E766A0073E846 /* NEVPNStatusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DB75ED239E766A0073E846 /* NEVPNStatusTests.swift */; };
82DC75BC22B277D200D3C73C /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DC75BB22B277D200D3C73C /* APIClient.swift */; };
82DC75BD22B7647500D3C73C /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DC75BB22B277D200D3C73C /* APIClient.swift */; };
82DE85712C8861CB00501935 /* AppIntents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DE85702C8861CB00501935 /* AppIntents.swift */; };
82DEF01E244714D900CCB5CD /* ScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DEF01D244714D900CCB5CD /* ScannerViewController.swift */; };
82DEF021244714F000CCB5CD /* ScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DEF020244714F000CCB5CD /* ScannerView.swift */; };
82DEF0262447285F00CCB5CD /* CreateAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DEF0252447285F00CCB5CD /* CreateAccountViewController.swift */; };
Expand Down Expand Up @@ -471,8 +471,6 @@
8206BAFE29ED6FFF00F916B7 /* ConnectionInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionInfoView.swift; sourceTree = "<group>"; };
8206BB0029ED7BEE00F916B7 /* ConnectionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionInfo.swift; sourceTree = "<group>"; };
8206BB0229ED7C3700F916B7 /* ConnectionInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionInfoViewModel.swift; sourceTree = "<group>"; };
8206E5CF22967E37003119AF /* UserActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityType.swift; sourceTree = "<group>"; };
8206E5D122967EAF003119AF /* UserActivityTitle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityTitle.swift; sourceTree = "<group>"; };
8206F32024347A8F0056B465 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
8206F32224367A240056B465 /* VPNErrorObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNErrorObserver.swift; sourceTree = "<group>"; };
8208525523FD56870008C112 /* FloatingPanelMainLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPanelMainLayout.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -587,6 +585,7 @@
828772F6221C008100D5E330 /* ServerConfigurationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfigurationCell.swift; sourceTree = "<group>"; };
828772F8221C01C300D5E330 /* ServersConfigurationTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServersConfigurationTableViewController.swift; sourceTree = "<group>"; };
828772FA221C28E000D5E330 /* FlagImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagImageView.swift; sourceTree = "<group>"; };
828C45682C8877290064F365 /* AppIntentsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntentsHandler.swift; sourceTree = "<group>"; };
828D8A6C258245AD00CB0E5B /* TwoFactorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoFactorViewController.swift; sourceTree = "<group>"; };
828E9C94231E5780001E1FCF /* Data+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Ext.swift"; sourceTree = "<group>"; };
8290195E243CB27500777B6E /* ControlPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlPanelView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -674,6 +673,7 @@
82DB75EB239E75EB0073E846 /* NEVPNStatus+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NEVPNStatus+Ext.swift"; sourceTree = "<group>"; };
82DB75ED239E766A0073E846 /* NEVPNStatusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NEVPNStatusTests.swift; sourceTree = "<group>"; };
82DC75BB22B277D200D3C73C /* APIClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIClient.swift; sourceTree = "<group>"; };
82DE85702C8861CB00501935 /* AppIntents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntents.swift; sourceTree = "<group>"; };
82DEF01D244714D900CCB5CD /* ScannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannerViewController.swift; sourceTree = "<group>"; };
82DEF020244714F000CCB5CD /* ScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannerView.swift; sourceTree = "<group>"; };
82DEF0252447285F00CCB5CD /* CreateAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateAccountViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -925,6 +925,7 @@
82C1D5BD23FE8BD90059A915 /* ControlPanel */,
8208525723FD5EB20008C112 /* MainViewController.swift */,
8208525B23FD64160008C112 /* MainViewController+Ext.swift */,
828C45682C8877290064F365 /* AppIntentsHandler.swift */,
);
path = MainScreen;
sourceTree = "<group>";
Expand Down Expand Up @@ -1032,6 +1033,7 @@
827694F2263C04C40058B4DC /* LoginConfirmation.swift */,
821CA2DE288143470067F70D /* PortRange.swift */,
825ECB2B2A5582570032E986 /* AntiTrackerDns.swift */,
82DE85702C8861CB00501935 /* AppIntents.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -1192,8 +1194,6 @@
82E716832181E8E100D6B7C2 /* ProviderConfigurationKeys.swift */,
82D598B321A5A7A3000FABDE /* NetworkTrust.swift */,
82D598C721A6ADF1000FABDE /* NetworkType.swift */,
8206E5CF22967E37003119AF /* UserActivityType.swift */,
8206E5D122967EAF003119AF /* UserActivityTitle.swift */,
823FFB062338DF1800F91A5D /* Capability.swift */,
8229209F2480FA3600476FC1 /* ServersSort.swift */,
826FBDA22461847D00B9E464 /* ServiceType.swift */,
Expand Down Expand Up @@ -2285,7 +2285,6 @@
82D598BC21A6949F000FABDE /* StorageManager.swift in Sources */,
826FBDA32461847D00B9E464 /* ServiceType.swift in Sources */,
821429B922FC2EA40056B8FF /* ApiService+Ext.swift in Sources */,
8206E5D222967EAF003119AF /* UserActivityTitle.swift in Sources */,
82E716902181E90500D6B7C2 /* ConnectionSettings.swift in Sources */,
8223C54C22E9E93A00CD283D /* Session.swift in Sources */,
822563922431E03A00AE7F8D /* AccountView.swift in Sources */,
Expand Down Expand Up @@ -2334,6 +2333,7 @@
8292E1A92174C11600123538 /* Interface.swift in Sources */,
82F638CC217DC25600410318 /* CIDRAddress.swift in Sources */,
824B86D226D40E7800D0101A /* FileManager+Extension.swift in Sources */,
828C45692C88772E0064F365 /* AppIntentsHandler.swift in Sources */,
8208525A23FD5F670008C112 /* FloatingPanelController+Ext.swift in Sources */,
821429B722FC2BE90056B8FF /* Result.swift in Sources */,
827855B92472B27F00B3B6BD /* Account.swift in Sources */,
Expand All @@ -2357,7 +2357,6 @@
82A3422524AB6AF700761AB0 /* Double+Ext.swift in Sources */,
8221377B2227E75E001E1BF5 /* CustomDNSViewController.swift in Sources */,
9C3031351DB42EF900C38B0C /* Application.swift in Sources */,
8206E5D022967E37003119AF /* UserActivityType.swift in Sources */,
82A6D74A24A3780B00D6C0E1 /* ConnectToServerPopupView.swift in Sources */,
828772FB221C28E000D5E330 /* FlagImageView.swift in Sources */,
8228C8D22B1DE906005977D3 /* PurchaseManager.swift in Sources */,
Expand Down Expand Up @@ -2392,6 +2391,7 @@
82DEF01E244714D900CCB5CD /* ScannerViewController.swift in Sources */,
8270D268241BB3D100B17B65 /* InfoAlertViewModel.swift in Sources */,
826E614A242A1CA80064F195 /* AccountViewModel.swift in Sources */,
82DE85712C8861CB00501935 /* AppIntents.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
9 changes: 9 additions & 0 deletions IVPNClient/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,12 @@ extension AppDelegate: PurchaseManagerDelegate {
}

}

enum UserActivityType {
static let Connect = "net.ivpn.clients.ios.Connect"
static let Disconnect = "net.ivpn.clients.ios.Disconnect"
static let AntiTrackerEnable = "net.ivpn.clients.ios.AntiTracker.enable"
static let AntiTrackerDisable = "net.ivpn.clients.ios.AntiTracker.disable"
static let CustomDNSEnable = "net.ivpn.clients.ios.CustomDNS.enable"
static let CustomDNSDisable = "net.ivpn.clients.ios.CustomDNS.disable"
}
33 changes: 0 additions & 33 deletions IVPNClient/Enums/UserActivityTitle.swift

This file was deleted.

33 changes: 0 additions & 33 deletions IVPNClient/Enums/UserActivityType.swift

This file was deleted.

97 changes: 97 additions & 0 deletions IVPNClient/Models/AppIntents.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// AddNoteIntent.swift
// IVPN iOS app
// https://github.com/ivpn/ios-app
//
// Created by Juraj Hilje on 2024-09-04.
// Copyright (c) 2024 IVPN Limited.
//
// This file is part of the IVPN iOS app.
//
// The IVPN iOS app 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.
//
// The IVPN iOS app 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 the IVPN iOS app. If not, see <https://www.gnu.org/licenses/>.
//


import AppIntents

@available(iOS 16, *)
struct Connect: AppIntent {
static var title = LocalizedStringResource("Connect VPN")
static var description = IntentDescription("Connect to the VPN")

func perform() async throws -> some IntentResult {
log(.info, message: "App Intent handler: Connect")
NotificationCenter.default.post(name: Notification.Name.IntentConnect, object: nil)
return .result()
}
}

@available(iOS 16, *)
struct Disconnect: AppIntent {
static var title = LocalizedStringResource("Disconnect VPN")
static var description = IntentDescription("Disconnect from the VPN")

func perform() async throws -> some IntentResult {
log(.info, message: "App Intent handler: Disconnect")
NotificationCenter.default.post(name: Notification.Name.IntentDisconnect, object: nil)
return .result()
}
}

@available(iOS 16, *)
struct AntiTrackerEnable: AppIntent {
static var title = LocalizedStringResource("Enable AntiTracker")
static var description = IntentDescription("Enables the AntiTracker")

func perform() async throws -> some IntentResult {
log(.info, message: "App Intent handler: EnableAntiTracker")
NotificationCenter.default.post(name: Notification.Name.IntentAntiTrackerEnable, object: nil)
return .result()
}
}

@available(iOS 16, *)
struct AntiTrackerDisable: AppIntent {
static var title = LocalizedStringResource("Disable AntiTracker")
static var description = IntentDescription("Disables the AntiTracker")

func perform() async throws -> some IntentResult {
log(.info, message: "App Intent handler: DisableAntiTracker")
NotificationCenter.default.post(name: Notification.Name.IntentAntiTrackerDisable, object: nil)
return .result()
}
}

@available(iOS 16, *)
struct CustomDNSEnable: AppIntent {
static var title = LocalizedStringResource("Enable Custom DNS")
static var description = IntentDescription("Enables the Custom DNS")

func perform() async throws -> some IntentResult {
log(.info, message: "App Intent handler: EnableCustomDNS")
NotificationCenter.default.post(name: Notification.Name.IntentCustomDNSEnable, object: nil)
return .result()
}
}

@available(iOS 16, *)
struct CustomDNSDisable: AppIntent {
static var title = LocalizedStringResource("Disable Custom DNS")
static var description = IntentDescription("Disables the Custom DNS")

func perform() async throws -> some IntentResult {
log(.info, message: "App Intent handler: DisableCustomDNS")
NotificationCenter.default.post(name: Notification.Name.IntentCustomDNSDisable, object: nil)
return .result()
}
}
72 changes: 72 additions & 0 deletions IVPNClient/Scenes/MainScreen/AppIntentsHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// AppIntentsHandler.swift
// IVPNClient
//
// Created by Juraj Hilje on 04.09.2024..
// Copyright © 2024 IVPN. All rights reserved.
//

import UIKit

extension MainViewController {

// MARK: - App Intents -

@objc func intentConnect() {
Application.shared.connectionManager.resetRulesAndConnect()
}

@objc func intentDisconnect() {
Application.shared.connectionManager.resetRulesAndDisconnect()
}

@objc func intentAntiTrackerEnable() {
DispatchQueue.async {
if Application.shared.settings.connectionProtocol.tunnelType() == .ipsec {
self.showAlert(title: "IKEv2 not supported", message: "AntiTracker is supported only for OpenVPN and WireGuard protocols.") { _ in
}
return
}

UserDefaults.shared.set(true, forKey: UserDefaults.Key.isAntiTracker)
NotificationCenter.default.post(name: Notification.Name.AntiTrackerUpdated, object: nil)
self.evaluateReconnect(sender: self.view)
}
}

@objc func intentAntiTrackerDisable() {
DispatchQueue.async {
UserDefaults.shared.set(false, forKey: UserDefaults.Key.isAntiTracker)
NotificationCenter.default.post(name: Notification.Name.AntiTrackerUpdated, object: nil)
self.evaluateReconnect(sender: self.view)
}
}

@objc func intentCustomDNSEnable() {
DispatchQueue.async {
if Application.shared.settings.connectionProtocol.tunnelType() == .ipsec {
self.showAlert(title: "IKEv2 not supported", message: "Custom DNS is supported only for OpenVPN and WireGuard protocols.") { _ in
}
return
}

guard !UserDefaults.shared.customDNS.isEmpty else {
self.showAlert(title: "", message: "Please enter DNS server info")
return
}

UserDefaults.shared.set(true, forKey: UserDefaults.Key.isCustomDNS)
NotificationCenter.default.post(name: Notification.Name.CustomDNSUpdated, object: nil)
self.evaluateReconnect(sender: self.view)
}
}

@objc func intentCustomDNSDisable() {
DispatchQueue.async {
UserDefaults.shared.set(false, forKey: UserDefaults.Key.isCustomDNS)
NotificationCenter.default.post(name: Notification.Name.CustomDNSUpdated, object: nil)
self.evaluateReconnect(sender: self.view)
}
}

}
Loading

0 comments on commit 3d4d3a8

Please sign in to comment.