From 196f6416e91056a40a2f8a19c140605abd5bd52b Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Thu, 22 Aug 2024 15:48:43 -0700 Subject: [PATCH] Clean up legacy VPN navigation (#3266) Task/Issue URL: https://app.asana.com/0/414235014887631/1208118450361001/f Tech Design URL: CC: Description: This PR removes some cases where the VPN UI could possibly be blank: 1. The settings navigation logic was technically using an EmptyView if you try to navigate to the VPN with it 2. The VPN root view was checking the feature flag and only showing the UI if it's enabled, so if that flag was disabled for any reason the UI would be blank - since this flag is no longer necessary, I've removed the check --- DuckDuckGo.xcodeproj/project.pbxproj | 4 -- DuckDuckGo/AppDelegate.swift | 6 +-- DuckDuckGo/MainViewController+Segues.swift | 8 +++ DuckDuckGo/NetworkProtectionRootView.swift | 13 +++-- .../NetworkProtectionRootViewController.swift | 50 ------------------- DuckDuckGo/SettingsLegacyViewProvider.swift | 5 +- DuckDuckGo/SettingsRootView.swift | 16 +----- DuckDuckGo/SettingsSubscriptionView.swift | 14 +++--- DuckDuckGo/SettingsViewModel.swift | 13 +---- 9 files changed, 31 insertions(+), 98 deletions(-) delete mode 100644 DuckDuckGo/NetworkProtectionRootViewController.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 28dbca7736..b6ffc9bca9 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -955,7 +955,6 @@ EE01EB402AFBD0000096AAC9 /* NetworkProtectionVPNSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE01EB3F2AFBD0000096AAC9 /* NetworkProtectionVPNSettingsViewModel.swift */; }; EE01EB432AFC1E0A0096AAC9 /* NetworkProtectionVPNLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE01EB422AFC1E0A0096AAC9 /* NetworkProtectionVPNLocationView.swift */; }; EE0798C52B179936000A4F64 /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0798C42B179936000A4F64 /* NetworkProtectionVPNCountryLabelsModel.swift */; }; - EE276BEA2A77F823009167B6 /* NetworkProtectionRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE276BE92A77F823009167B6 /* NetworkProtectionRootViewController.swift */; }; EE3766DE2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */; }; EE3B226B29DE0F110082298A /* MockInternalUserStoring.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3B226A29DE0F110082298A /* MockInternalUserStoring.swift */; }; EE3B226C29DE0FD30082298A /* MockInternalUserStoring.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3B226A29DE0F110082298A /* MockInternalUserStoring.swift */; }; @@ -2716,7 +2715,6 @@ EE01EB3F2AFBD0000096AAC9 /* NetworkProtectionVPNSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionVPNSettingsViewModel.swift; sourceTree = ""; }; EE01EB422AFC1E0A0096AAC9 /* NetworkProtectionVPNLocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionVPNLocationView.swift; sourceTree = ""; }; EE0798C42B179936000A4F64 /* NetworkProtectionVPNCountryLabelsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionVPNCountryLabelsModel.swift; sourceTree = ""; }; - EE276BE92A77F823009167B6 /* NetworkProtectionRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionRootViewController.swift; sourceTree = ""; }; EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionUNNotificationPresenter.swift; sourceTree = ""; }; EE3B226A29DE0F110082298A /* MockInternalUserStoring.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockInternalUserStoring.swift; sourceTree = ""; }; EE3B98EA2A9634CC002F63A0 /* DuckDuckGoAlpha.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DuckDuckGoAlpha.entitlements; sourceTree = ""; }; @@ -5194,7 +5192,6 @@ isa = PBXGroup; children = ( EE0153EC2A6FF9E6002A8B26 /* NetworkProtectionRootView.swift */, - EE276BE92A77F823009167B6 /* NetworkProtectionRootViewController.swift */, ); name = Root; sourceTree = ""; @@ -7139,7 +7136,6 @@ 6F691CCA2C4979EC002E9553 /* FavoritesTooltip.swift in Sources */, D65625952C22D382006EF297 /* TabViewController.swift in Sources */, 8C4838B5221C8F7F008A6739 /* GestureToolbarButton.swift in Sources */, - EE276BEA2A77F823009167B6 /* NetworkProtectionRootViewController.swift in Sources */, 310ECFDD282A8BB0005029B3 /* EnableAutofillSettingsTableViewCell.swift in Sources */, 6F9FFE2A2C57ADB100A238BE /* EditableShortcutsView.swift in Sources */, 1E908BF329827C480008C8F3 /* AutoconsentManagement.swift in Sources */, diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index a3b5df16eb..8c5da72457 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -1031,10 +1031,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate { func presentNetworkProtectionStatusSettingsModal() { Task { - if case .success(let hasEntitlements) = await accountManager.hasEntitlement(forProductName: .networkProtection), - hasEntitlements { - let networkProtectionRoot = NetworkProtectionRootViewController() - presentSettings(with: networkProtectionRoot) + if case .success(let hasEntitlements) = await accountManager.hasEntitlement(forProductName: .networkProtection), hasEntitlements { + (window?.rootViewController as? MainViewController)?.segueToVPN() } else { (window?.rootViewController as? MainViewController)?.segueToPrivacyPro() } diff --git a/DuckDuckGo/MainViewController+Segues.swift b/DuckDuckGo/MainViewController+Segues.swift index 47ff957de8..b64f38cde1 100644 --- a/DuckDuckGo/MainViewController+Segues.swift +++ b/DuckDuckGo/MainViewController+Segues.swift @@ -254,6 +254,14 @@ extension MainViewController { } } + func segueToVPN() { + os_log(#function, log: .generalLog, type: .debug) + hideAllHighlightsIfNeeded() + launchSettings { + $0.triggerDeepLinkNavigation(to: .netP) + } + } + func segueToDebugSettings() { os_log(#function, log: .generalLog, type: .debug) hideAllHighlightsIfNeeded() diff --git a/DuckDuckGo/NetworkProtectionRootView.swift b/DuckDuckGo/NetworkProtectionRootView.swift index 70a936e10f..99a8f29244 100644 --- a/DuckDuckGo/NetworkProtectionRootView.swift +++ b/DuckDuckGo/NetworkProtectionRootView.swift @@ -20,8 +20,10 @@ import SwiftUI import NetworkProtection import Subscription +import Core struct NetworkProtectionRootView: View { + let statusViewModel: NetworkProtectionStatusViewModel init() { @@ -33,11 +35,12 @@ struct NetworkProtectionRootView: View { serverInfoObserver: AppDependencyProvider.shared.serverInfoObserver, locationListRepository: locationListRepository) } + var body: some View { - if AppDependencyProvider.shared.vpnFeatureVisibility.isPrivacyProLaunched() { - NetworkProtectionStatusView( - statusModel: statusViewModel - ) - } + NetworkProtectionStatusView(statusModel: statusViewModel) + .navigationTitle(UserText.netPNavTitle) + .onFirstAppear { + Pixel.fire(pixel: .privacyProVPNSettings) + } } } diff --git a/DuckDuckGo/NetworkProtectionRootViewController.swift b/DuckDuckGo/NetworkProtectionRootViewController.swift deleted file mode 100644 index 07467a8bf1..0000000000 --- a/DuckDuckGo/NetworkProtectionRootViewController.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// NetworkProtectionRootViewController.swift -// DuckDuckGo -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -final class NetworkProtectionRootViewController: UIHostingController { - - init() { - let rootView = NetworkProtectionRootView() - super.init(rootView: rootView) - } - - override func viewDidLoad() { - super.viewDidLoad() - decorate() - self.title = UserText.netPNavTitle - } - - @MainActor required dynamic init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -extension NetworkProtectionRootViewController { - - private func decorate() { - let theme = ThemeManager.shared.currentTheme - view.backgroundColor = theme.backgroundColor - - navigationController?.navigationBar.barTintColor = theme.barBackgroundColor - navigationController?.navigationBar.tintColor = theme.navigationBarTintColor - } - -} diff --git a/DuckDuckGo/SettingsLegacyViewProvider.swift b/DuckDuckGo/SettingsLegacyViewProvider.swift index 9ebab1a8f3..af40a39ab6 100644 --- a/DuckDuckGo/SettingsLegacyViewProvider.swift +++ b/DuckDuckGo/SettingsLegacyViewProvider.swift @@ -61,8 +61,8 @@ class SettingsLegacyViewProvider: ObservableObject { fireproofSites, autoclearData, keyboard, - netP, - feedback, debug + feedback, + debug } private func instantiate(_ identifier: String, fromStoryboard name: String) -> UIViewController { @@ -81,7 +81,6 @@ class SettingsLegacyViewProvider: ObservableObject { var autoclearData: UIViewController { instantiate("AutoClearSettingsViewController", fromStoryboard: "Settings") } var keyboard: UIViewController { instantiate("Keyboard", fromStoryboard: "Settings") } var feedback: UIViewController { instantiate("Feedback", fromStoryboard: "Feedback") } - var netP: UIViewController { NetworkProtectionRootViewController() } @MainActor var syncSettings: UIViewController { diff --git a/DuckDuckGo/SettingsRootView.swift b/DuckDuckGo/SettingsRootView.swift index 83c9f1acf9..7bb093b578 100644 --- a/DuckDuckGo/SettingsRootView.swift +++ b/DuckDuckGo/SettingsRootView.swift @@ -91,10 +91,6 @@ struct SettingsRootView: View { DispatchQueue.main.async { self.shouldDisplayDeepLinkPush = true } - case.UIKitView: - DispatchQueue.main.async { - triggerLegacyLink(link) - } } }) @@ -129,19 +125,11 @@ struct SettingsRootView: View { onDisappear: {}) case .duckPlayer: SettingsDuckPlayerView().environmentObject(viewModel) - default: - EmptyView() - } - } - - private func triggerLegacyLink(_ link: SettingsViewModel.SettingsDeepLinkSection) { - switch link { case .netP: - viewModel.presentLegacyView(.netP) - default: - return + NetworkProtectionRootView() } } + } struct InsetGroupedListStyleModifier: ViewModifier { diff --git a/DuckDuckGo/SettingsSubscriptionView.swift b/DuckDuckGo/SettingsSubscriptionView.swift index af39a0cc0a..67fa9f4faa 100644 --- a/DuckDuckGo/SettingsSubscriptionView.swift +++ b/DuckDuckGo/SettingsSubscriptionView.swift @@ -38,6 +38,7 @@ struct SettingsSubscriptionView: View { @EnvironmentObject var subscriptionNavigationCoordinator: SubscriptionNavigationCoordinator @State var isShowingDBP = false @State var isShowingITP = false + @State var isShowingVPN = false @State var isShowingRestoreFlow = false @State var isShowingGoogleView = false @State var isShowingStripeView = false @@ -155,12 +156,13 @@ struct SettingsSubscriptionView: View { private var subscriptionDetailsView: some View { if viewModel.state.subscription.entitlements.contains(.networkProtection) { - SettingsCellView(label: UserText.settingsPProVPNTitle, - image: Image("SettingsPrivacyProVPN"), - action: { viewModel.presentLegacyView(.netP) }, - statusIndicator: StatusIndicatorView(status: viewModel.state.networkProtectionConnected ? .on : .off), - disclosureIndicator: true, - isButton: true) + NavigationLink(destination: NetworkProtectionRootView(), isActive: $isShowingVPN) { + SettingsCellView( + label: UserText.settingsPProVPNTitle, + image: Image("SettingsPrivacyProVPN"), + statusIndicator: StatusIndicatorView(status: viewModel.state.networkProtectionConnected ? .on : .off) + ) + } } if viewModel.state.subscription.entitlements.contains(.dataBrokerProtection) { diff --git a/DuckDuckGo/SettingsViewModel.swift b/DuckDuckGo/SettingsViewModel.swift index 2de260a871..0f98bad108 100644 --- a/DuckDuckGo/SettingsViewModel.swift +++ b/DuckDuckGo/SettingsViewModel.swift @@ -598,10 +598,6 @@ extension SettingsViewModel { case .autoconsent: pushViewController(legacyViewProvider.autoConsent) - - case .netP: - firePixel(.privacyProVPNSettings) - pushViewController(legacyViewProvider.netP) } } @@ -654,13 +650,7 @@ extension SettingsViewModel { // Default to .sheet, specify .push where needed var type: DeepLinkType { switch self { - // Specify cases that require .push presentation - // Example: - // case .dbp: - // return .sheet - case .netP: - return .UIKitView - default: + case .netP, .dbp, .itr, .subscriptionFlow, .restoreFlow, .duckPlayer: return .navigationLink } } @@ -670,7 +660,6 @@ extension SettingsViewModel { enum DeepLinkType { case sheet case navigationLink - case UIKitView } // Navigate to a section in settings