Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an “Open VPN Settings” quick action #2089

Merged
merged 9 commits into from
Oct 27, 2023
Merged
10 changes: 0 additions & 10 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,6 @@
6AC6DAB228804F97002723C0 /* BarsAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarsAnimator.swift; sourceTree = "<group>"; };
6AC98418288055C1005FA9CA /* BarsAnimatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarsAnimatorTests.swift; sourceTree = "<group>"; };
6FB030C7234331B400A10DB9 /* Configuration.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Configuration.xcconfig; path = Configuration/Configuration.xcconfig; sourceTree = "<group>"; };
7B5E1F9D2AB9E1E900DA1172 /* NetworkProtectionDebugFeatures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDebugFeatures.swift; sourceTree = "<group>"; };
83004E7F2193BB8200DA013C /* WKNavigationExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKNavigationExtension.swift; sourceTree = "<group>"; };
83004E832193E14C00DA013C /* UIAlertControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = UIAlertControllerExtension.swift; path = ../Core/UIAlertControllerExtension.swift; sourceTree = "<group>"; };
83004E852193E5ED00DA013C /* TabViewControllerBrowsingMenuExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabViewControllerBrowsingMenuExtension.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3535,7 +3534,6 @@
83ED3B8D1FA8E63700B47556 /* README.md */,
83ED3B8C1FA8E61D00B47556 /* ManualTestsScript.md */,
85A313962028E78A00327D00 /* release_notes.txt */,
EEF0F8CA2ABC82E100630031 /* Recovered References */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -4446,14 +4444,6 @@
name = Status;
sourceTree = "<group>";
};
EEF0F8CA2ABC82E100630031 /* Recovered References */ = {
isa = PBXGroup;
children = (
7B5E1F9D2AB9E1E900DA1172 /* NetworkProtectionDebugFeatures.swift */,
);
name = "Recovered References";
sourceTree = "<group>";
};
EEFD562D2A65B68B00DAEC48 /* Invite */ = {
isa = PBXGroup;
children = (
Expand Down
58 changes: 56 additions & 2 deletions DuckDuckGo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import Networking
import DDGSync
import SyncDataProviders

#if NETWORK_PROTECTION
import NetworkProtection
#endif

// swiftlint:disable file_length
// swiftlint:disable type_body_length

Expand All @@ -45,6 +49,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

private struct ShortcutKey {
static let clipboard = "com.duckduckgo.mobile.ios.clipboard"

#if NETWORK_PROTECTION
static let openVPNSettings = "com.duckduckgo.mobile.ios.vpn.open-settings"
#endif
}

private var testing = false
Expand Down Expand Up @@ -329,6 +337,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

syncService.scheduler.notifyAppLifecycleEvent()
fireFailedCompilationsPixelIfNeeded()
refreshShortcuts()
}

func applicationWillResignActive(_ application: UIApplication) {
refreshShortcuts()
}

private func fireAppLaunchPixel() {
Expand Down Expand Up @@ -591,11 +604,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

private func handleShortCutItem(_ shortcutItem: UIApplicationShortcutItem) {
os_log("Handling shortcut item: %s", log: .generalLog, type: .debug, shortcutItem.type)
mainViewController?.clearNavigationStack()

autoClear?.applicationWillMoveToForeground()
if shortcutItem.type == ShortcutKey.clipboard, let query = UIPasteboard.general.string {

if shortcutItem.type == ShortcutKey.clipboard, let query = UIPasteboard.general.string {
mainViewController?.clearNavigationStack()
mainViewController?.loadQueryInNewTab(query)
return
}

#if NETWORK_PROTECTION
if shortcutItem.type == ShortcutKey.openVPNSettings {
presentNetworkProtectionStatusSettingsModal()
}
#endif
}

private func removeEmailWaitlistState() {
Expand Down Expand Up @@ -623,6 +645,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private var mainViewController: MainViewController? {
return window?.rootViewController as? MainViewController
}

func refreshShortcuts() {
#if NETWORK_PROTECTION
guard NetworkProtectionKeychainTokenStore().isFeatureActivated else {
return
}

let items = [
UIApplicationShortcutItem(type: ShortcutKey.openVPNSettings,
localizedTitle: UserText.netPOpenVPNQuickAction,
localizedSubtitle: nil,
icon: UIApplicationShortcutIcon(templateImageName: "VPN-16"),
userInfo: nil)
]

UIApplication.shared.shortcutItems = items
#endif
}

}

extension AppDelegate: BlankSnapshotViewRecoveringDelegate {
Expand Down Expand Up @@ -708,6 +749,19 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
private func presentSettings(with viewController: UIViewController) {
guard let window = window, let rootViewController = window.rootViewController as? MainViewController else { return }

if let navigationController = rootViewController.presentedViewController as? UINavigationController {
if let lastViewController = navigationController.viewControllers.last, lastViewController.isKind(of: type(of: viewController)) {
// Avoid presenting dismissing and re-presenting the view controller if it's already visible:
return
} else {
// Otherwise, replace existing view controllers with the presented one:
navigationController.popToRootViewController(animated: false)
navigationController.pushViewController(viewController, animated: false)
return
}
}

// If the previous checks failed, make sure the nav stack is reset and present the view controller from scratch:
rootViewController.clearNavigationStack()

// Give the `clearNavigationStack` call time to complete.
Expand Down
15 changes: 15 additions & 0 deletions DuckDuckGo/Assets.xcassets/VPN-16.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "VPN-16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Binary file not shown.
2 changes: 2 additions & 0 deletions DuckDuckGo/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,8 @@ In addition to the details entered into this form, your app issue report will co
static let netPSecureDNSSettingTitle = NSLocalizedString("network.protection.vpn.secure.dns.setting.title", value: "Secure DNS", comment: "Title for the Always on VPN setting item.")
static let netPSecureDNSSettingFooter = NSLocalizedString("network.protection.vpn.secure.dns.setting.footer", value: "Network Protection prevents DNS leaks to your Internet Service Provider by routing DNS queries though the VPN tunnel to our own resolver.", comment: "Footer text for the Always on VPN setting item.")

static let netPOpenVPNQuickAction = NSLocalizedString("network.protection.quick-action.open-vpn", value: "Open VPN", comment: "Title text for an iOS quick action that opens VPN settings")

static let inviteDialogContinueButton = NSLocalizedString("invite.dialog.continue.button", value: "Continue", comment: "Continue button on an invite dialog")
static let inviteDialogGetStartedButton = NSLocalizedString("invite.dialog.get.started.button", value: "Get Started", comment: "Get Started button on an invite dialog")
static let inviteDialogUnrecognizedCodeMessage = NSLocalizedString("invite.dialog.unrecognized.code.message", value: "We didn’t recognize this Invite Code.", comment: "Message to show after user enters an unrecognized invite code")
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGo/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,9 @@ https://duckduckgo.com/mac";
/* Title for the network protection invite success view */
"network.protection.invite.success.title" = "Success! You’re in.";

/* Title text for an iOS quick action that opens VPN settings */
"network.protection.quick-action.open-vpn" = "Open VPN";

/* The label for when NetP VPN is connected plus the length of time connected as a formatter HH:MM:SS string */
"network.protection.status.connected.format" = "Connected - %@";

Expand Down