From 0d3aa6f92264de52cfc4de3d7947a0af5330ec8f Mon Sep 17 00:00:00 2001 From: Bug Magnet Date: Mon, 29 Jul 2024 16:20:54 +0200 Subject: [PATCH 1/2] Do not warn users about multihop extra latency, add info button instead --- ios/MullvadVPN.xcodeproj/project.pbxproj | 14 ++--- .../VPNSettings/VPNSettingsCellFactory.swift | 4 ++ .../VPNSettings/VPNSettingsDataSource.swift | 15 +----- .../VPNSettingsDataSourceDelegate.swift | 1 - .../VPNSettingsInfoButtonItem.swift | 1 + .../VPNSettingsViewController.swift | 52 +++---------------- .../Pages/MultihopPromptAlert.swift | 29 ----------- .../Pages/VPNSettingsPage.swift | 10 ---- 8 files changed, 20 insertions(+), 106 deletions(-) delete mode 100644 ios/MullvadVPNUITests/Pages/MultihopPromptAlert.swift diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index b2075950efbc..f0f0a145aa02 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -954,7 +954,6 @@ F0DA87492A9CBA9F006044F1 /* AccountDeviceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DA87482A9CBA9F006044F1 /* AccountDeviceRow.swift */; }; F0DA874B2A9CBACB006044F1 /* AccountNumberRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DA874A2A9CBACB006044F1 /* AccountNumberRow.swift */; }; F0DAC8AD2C16EFE400F80144 /* TunnelSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04DD3D72C130DF600E03E28 /* TunnelSettingsManager.swift */; }; - F0DAC8AF2C1712C300F80144 /* MultihopPromptAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DAC8AE2C1712C300F80144 /* MultihopPromptAlert.swift */; }; F0DDE4152B220458006B57A7 /* ShadowsocksConfigurationCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DDE4102B220458006B57A7 /* ShadowsocksConfigurationCache.swift */; }; F0DDE4162B220458006B57A7 /* TransportProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DDE4112B220458006B57A7 /* TransportProvider.swift */; }; F0DDE4182B220458006B57A7 /* ShadowsocksConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DDE4132B220458006B57A7 /* ShadowsocksConfiguration.swift */; }; @@ -2129,7 +2128,6 @@ F0DA87462A9CB9A2006044F1 /* AccountExpiryRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountExpiryRow.swift; sourceTree = ""; }; F0DA87482A9CBA9F006044F1 /* AccountDeviceRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDeviceRow.swift; sourceTree = ""; }; F0DA874A2A9CBACB006044F1 /* AccountNumberRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountNumberRow.swift; sourceTree = ""; }; - F0DAC8AE2C1712C300F80144 /* MultihopPromptAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultihopPromptAlert.swift; sourceTree = ""; }; F0DDE40F2B220458006B57A7 /* ShadowSocksProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowSocksProxy.swift; sourceTree = ""; }; F0DDE4102B220458006B57A7 /* ShadowsocksConfigurationCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowsocksConfigurationCache.swift; sourceTree = ""; }; F0DDE4112B220458006B57A7 /* TransportProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransportProvider.swift; sourceTree = ""; }; @@ -3911,33 +3909,32 @@ children = ( 85FB5A0F2B6960A30015DCED /* AccountDeletionPage.swift */, 85557B1F2B5FBBD700795FE1 /* AccountPage.swift */, + 852D054E2BC43DF7008578D2 /* AddAccessMethodPage.swift */, 7ACD79382C0DAADC00DBEE14 /* AddCustomListLocationsPage.swift */, 8529693B2B4F0257007EAD4C /* Alert.swift */, + 852D054C2BC3DE3A008578D2 /* APIAccessPage.swift */, + 85021CAD2BDBC4290098B400 /* AppLogsPage.swift */, 8587A05C2B84D43100152938 /* ChangeLogAlert.swift */, A9BFB0002BD00B7F00F2BCA1 /* CustomListPage.swift */, 85A42B872BB44D31007BABF7 /* DeviceManagementPage.swift */, 852A26452BA9C9CB006EB9C8 /* DNSSettingsPage.swift */, + 8585CBE22BC684180015B6A4 /* EditAccessMethodPage.swift */, A998DA822BD2B055001D61A2 /* EditCustomListLocationsPage.swift */, 85557B1D2B5FB8C700795FE1 /* HeaderBar.swift */, A998DA802BD147AD001D61A2 /* ListCustomListsPage.swift */, 852969342B4E9270007EAD4C /* LoginPage.swift */, - F0DAC8AE2C1712C300F80144 /* MultihopPromptAlert.swift */, 85139B2C2B84B4A700734217 /* OutOfTimePage.swift */, 852969322B4E9232007EAD4C /* Page.swift */, 855D9F5A2B63E56B00D7C64D /* ProblemReportPage.swift */, 8532E6862B8CCED600ACECD1 /* ProblemReportSubmittedPage.swift */, 8556EB552B9B0AC500D26DD4 /* RevokedDevicePage.swift */, + 8542F7522BCFBD050035C042 /* SelectLocationFilterPage.swift */, 850201DC2B503D8C00EF8C96 /* SelectLocationPage.swift */, 850201E22B51A93C00EF8C96 /* SettingsPage.swift */, 852969392B4F0238007EAD4C /* TermsOfServicePage.swift */, 850201DE2B5040A500EF8C96 /* TunnelControlPage.swift */, 8542CE232B95F7B9006FCA14 /* VPNSettingsPage.swift */, 85FB5A0B2B6903990015DCED /* WelcomePage.swift */, - 8542F7522BCFBD050035C042 /* SelectLocationFilterPage.swift */, - 852D054C2BC3DE3A008578D2 /* APIAccessPage.swift */, - 852D054E2BC43DF7008578D2 /* AddAccessMethodPage.swift */, - 8585CBE22BC684180015B6A4 /* EditAccessMethodPage.swift */, - 85021CAD2BDBC4290098B400 /* AppLogsPage.swift */, ); path = Pages; sourceTree = ""; @@ -6049,7 +6046,6 @@ 7A45CFC72C071DD400D80B21 /* SnapshotHelper.swift in Sources */, 856952DC2BD2922A008C1F84 /* PartnerAPIClient.swift in Sources */, 85557B162B5ABBBE00795FE1 /* XCUIElementQuery+Extensions.swift in Sources */, - F0DAC8AF2C1712C300F80144 /* MultihopPromptAlert.swift in Sources */, 855D9F5B2B63E56B00D7C64D /* ProblemReportPage.swift in Sources */, 8529693A2B4F0238007EAD4C /* TermsOfServicePage.swift in Sources */, 85A42B882BB44D31007BABF7 /* DeviceManagementPage.swift in Sources */, diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift index ae460818a9f6..0817c8ad0610 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift @@ -218,6 +218,10 @@ final class VPNSettingsCellFactory: CellFactoryProtocol { cell.accessibilityIdentifier = item.accessibilityIdentifier cell.setOn(viewModel.multihopState.isEnabled, animated: false) + cell.infoButtonHandler = { [weak self] in + self?.delegate?.showInfo(for: .multihop) + } + cell.action = { [weak self] isEnabled in let state: MultihopState = isEnabled ? .on : .off self?.delegate?.switchMultihop(state) diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift index 1bac5f42c76e..9a44019dddef 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift @@ -617,19 +617,8 @@ extension VPNSettingsDataSource: VPNSettingsCellEventHandler { } func switchMultihop(_ state: MultihopState) { - if state == .on { - delegate?.showMultihopConfirmation({ [weak self] in - guard let self else { return } - viewModel.setMultihop(state) - self.delegate?.didChangeViewModel(viewModel) - }, onDiscard: { [weak self] in - guard let self else { return } - reload(item: .multihop) - }) - } else { - viewModel.setMultihop(state) - delegate?.didChangeViewModel(viewModel) - } + viewModel.setMultihop(state) + delegate?.didChangeViewModel(viewModel) } } diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift index 5a9a06ff059f..48e952c7a678 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift @@ -20,5 +20,4 @@ protocol VPNSettingsDataSourceDelegate: AnyObject { func showDNSSettings() func showIPOverrides() func didSelectWireGuardPort(_ port: UInt16?) - func showMultihopConfirmation(_ onSave: @escaping () -> Void, onDiscard: @escaping () -> Void) } diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift index c55a4c2eebb6..a6fb585b3376 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift @@ -13,4 +13,5 @@ enum VPNSettingsInfoButtonItem { case wireGuardObfuscation case wireGuardObfuscationPort case quantumResistance + case multihop } diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift index 90744b6ce1b2..6a950b5f69c9 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift @@ -175,6 +175,14 @@ extension VPNSettingsViewController: VPNSettingsDataSourceDelegate { """, comment: "" ) + + case .multihop: + message = NSLocalizedString( + "MULTIHOP_INFORMATION_TEXT", + tableName: "Multihop", + value: "This setting increases latency. Use only if needed.", + comment: "" + ) default: assertionFailure("No matching InfoButtonItem") } @@ -194,48 +202,4 @@ extension VPNSettingsViewController: VPNSettingsDataSourceDelegate { func didSelectWireGuardPort(_ port: UInt16?) { interactor.setPort(port) } - - func showMultihopConfirmation(_ onSave: @escaping () -> Void, onDiscard: @escaping () -> Void) { - let presentation = AlertPresentation( - id: "multihop-confirm-alert", - accessibilityIdentifier: .multihopPromptAlert, - icon: .info, - message: NSLocalizedString( - "MULTIHOP_CONFIRM_ALERT_TEXT", - tableName: "Multihop", - value: "This setting increases latency. Use only if needed.", - comment: "" - ), - buttons: [ - AlertAction( - title: NSLocalizedString( - "MULTIHOP_CONFIRM_ALERT_ENABLE_BUTTON", - tableName: "Multihop", - value: "Enable anyway", - comment: "" - ), - style: .destructive, - accessibilityId: .multihopConfirmAlertEnableButton, - handler: { - onSave() - } - ), - AlertAction( - title: NSLocalizedString( - "MULTIHOP_CONFIRM_ALERT_BACK_BUTTON", - tableName: "Multihop", - value: "Back", - comment: "" - ), - style: .default, - accessibilityId: .multihopConfirmAlertBackButton, - handler: { - onDiscard() - } - ), - ] - ) - - alertPresenter.showAlert(presentation: presentation, animated: true) - } } diff --git a/ios/MullvadVPNUITests/Pages/MultihopPromptAlert.swift b/ios/MullvadVPNUITests/Pages/MultihopPromptAlert.swift deleted file mode 100644 index 27e7806db249..000000000000 --- a/ios/MullvadVPNUITests/Pages/MultihopPromptAlert.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// MultihopPromptAlert.swift -// MullvadVPNUITests -// -// Created by Mojgan on 2024-06-10. -// Copyright © 2024 Mullvad VPN AB. All rights reserved. -// - -import Foundation -import XCTest - -class MultihopPromptAlert: Page { - @discardableResult override init(_ app: XCUIApplication) { - super.init(app) - - self.pageElement = app.otherElements[.multihopPromptAlert] - waitForPageToBeShown() - } - - @discardableResult func tapEnableAnyway() -> Self { - app.buttons[AccessibilityIdentifier.multihopConfirmAlertEnableButton].tap() - return self - } - - @discardableResult func tapBack() -> Self { - app.buttons[AccessibilityIdentifier.multihopConfirmAlertBackButton].tap() - return self - } -} diff --git a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift index 2545a9a5d761..5746ce7ce00e 100644 --- a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift +++ b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift @@ -123,16 +123,6 @@ class VPNSettingsPage: Page { app.cells[AccessibilityIdentifier.multihopSwitch] .switches[AccessibilityIdentifier.customSwitch] .tap() - - let promptIsShown = app - .otherElements[AccessibilityIdentifier.multihopPromptAlert.rawValue] - .waitForExistence(timeout: 1.0) - - if promptIsShown { - MultihopPromptAlert(app) - .tapEnableAnyway() - } - return self } From 16936b6d75faf1cca09b653c1ca8966ab1e982e1 Mon Sep 17 00:00:00 2001 From: Bug Magnet Date: Tue, 30 Jul 2024 10:48:16 +0200 Subject: [PATCH 2/2] Improve copy message for multihop settings --- .../VPNSettings/VPNSettingsViewController.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift index 6a950b5f69c9..a0833d7c4307 100644 --- a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift @@ -180,7 +180,11 @@ extension VPNSettingsViewController: VPNSettingsDataSourceDelegate { message = NSLocalizedString( "MULTIHOP_INFORMATION_TEXT", tableName: "Multihop", - value: "This setting increases latency. Use only if needed.", + value: """ + Multihop routes your traffic into one WireGuard server and out another, making it harder to trace. + This results in increased latency but increases anonymity online. + """, + comment: "" ) default: