From 1ddc41ac44b1474e1eff9a2dd724adcfea77ac77 Mon Sep 17 00:00:00 2001 From: Jon Petersson Date: Mon, 18 Mar 2024 13:41:43 +0100 Subject: [PATCH] Move IP Overrides into VPN Settings menu --- ios/MullvadSettings/SettingsManager.swift | 2 +- ios/MullvadVPN.xcodeproj/project.pbxproj | 68 ++++++++++--------- .../Classes/AccessbilityIdentifier.swift | 4 +- .../Coordinators/ApplicationCoordinator.swift | 3 +- .../IPOverride/IPOverrideCoordinator.swift | 18 +++-- .../IPOverride/IPOverrideViewController.swift | 2 - .../Settings/SettingsCoordinator.swift | 27 +++----- .../Coordinators/VPNSettingsCoordinator.swift | 56 +++++++++++++++ .../PreferencesDataSourceDelegate.swift | 16 ----- .../Settings/SettingsCellFactory.swift | 17 +---- .../Settings/SettingsDataSource.swift | 12 ++-- .../Settings/SettingsInputCell.swift | 2 +- .../Settings/SettingsInteractorFactory.swift | 15 ++-- .../Settings/SettingsViewController.swift | 6 +- .../CustomDNSCellFactory.swift | 22 +++--- .../CustomDNSDataSource.swift | 12 ++-- .../CustomDNSViewController.swift | 26 ++++--- .../VPNSettingsCellFactory.swift} | 53 +++++++++------ .../VPNSettingsDataSource.swift} | 62 ++++++++++------- .../VPNSettingsDataSourceDelegate.swift | 17 +++++ .../VPNSettingsInfoButtonItem.swift} | 4 +- .../VPNSettingsInteractor.swift} | 8 +-- .../VPNSettingsViewController.swift} | 44 +++++++----- .../VPNSettingsViewModel.swift} | 12 ++-- .../MullvadVPNScreenshots.swift | 8 +-- .../Pages/SettingsPage.swift | 2 +- 26 files changed, 296 insertions(+), 222 deletions(-) create mode 100644 ios/MullvadVPN/Coordinators/VPNSettingsCoordinator.swift delete mode 100644 ios/MullvadVPN/View controllers/Preferences/PreferencesDataSourceDelegate.swift rename ios/MullvadVPN/View controllers/{Preferences => VPNSettings}/CustomDNSCellFactory.swift (93%) rename ios/MullvadVPN/View controllers/{Preferences => VPNSettings}/CustomDNSDataSource.swift (98%) rename ios/MullvadVPN/View controllers/{Preferences => VPNSettings}/CustomDNSViewController.swift (85%) rename ios/MullvadVPN/View controllers/{Preferences/PreferencesCellFactory.swift => VPNSettings/VPNSettingsCellFactory.swift} (82%) rename ios/MullvadVPN/View controllers/{Preferences/PreferencesDataSource.swift => VPNSettings/VPNSettingsDataSource.swift} (91%) create mode 100644 ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift rename ios/MullvadVPN/View controllers/{Preferences/PreferencesInfoButtonItem.swift => VPNSettings/VPNSettingsInfoButtonItem.swift} (80%) rename ios/MullvadVPN/View controllers/{Preferences/PreferencesInteractor.swift => VPNSettings/VPNSettingsInteractor.swift} (90%) rename ios/MullvadVPN/View controllers/{Preferences/PreferencesViewController.swift => VPNSettings/VPNSettingsViewController.swift} (83%) rename ios/MullvadVPN/View controllers/{Preferences/PreferencesViewModel.swift => VPNSettings/VPNSettingsViewModel.swift} (97%) diff --git a/ios/MullvadSettings/SettingsManager.swift b/ios/MullvadSettings/SettingsManager.swift index 2f8aa546dbbd..f6c77525929e 100644 --- a/ios/MullvadSettings/SettingsManager.swift +++ b/ios/MullvadSettings/SettingsManager.swift @@ -144,7 +144,7 @@ public enum SettingsManager { public static func resetStore(completely: Bool = false) { logger.debug("Reset store.") - let keys = completely ? SettingsKey.allCases : [.settings, .deviceState, .apiAccessMethods] + let keys = completely ? SettingsKey.allCases : [.settings, .deviceState, .apiAccessMethods, .ipOverrides] keys.forEach { key in do { diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index c7427d9ef163..4047f906aca4 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -120,7 +120,7 @@ 5846227126E229F20035F7C2 /* StoreSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227026E229F20035F7C2 /* StoreSubscription.swift */; }; 5846227326E22A160035F7C2 /* StorePaymentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227226E22A160035F7C2 /* StorePaymentObserver.swift */; }; 5846227726E22A7C0035F7C2 /* StorePaymentManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227626E22A7C0035F7C2 /* StorePaymentManagerDelegate.swift */; }; - 584D26C4270C855B004EA533 /* PreferencesDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26C3270C855A004EA533 /* PreferencesDataSource.swift */; }; + 584D26C4270C855B004EA533 /* VPNSettingsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26C3270C855A004EA533 /* VPNSettingsDataSource.swift */; }; 584D26C6270C8741004EA533 /* SettingsDNSTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26C5270C8741004EA533 /* SettingsDNSTextCell.swift */; }; 5859A55529CD9DD900F66591 /* changes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5859A55429CD9DD800F66591 /* changes.txt */; }; 585A02E92A4B283000C6CAFF /* TCPUnsafeListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585A02E82A4B283000C6CAFF /* TCPUnsafeListener.swift */; }; @@ -137,7 +137,7 @@ 5864859B29A0EAF2006C5743 /* SecondaryContextPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5864859A29A0EAF2006C5743 /* SecondaryContextPresentationController.swift */; }; 5864AF0729C78843005B0CD9 /* SettingsCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5864AF0029C7879B005B0CD9 /* SettingsCellFactory.swift */; }; 5864AF0829C78849005B0CD9 /* CellFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5864AF0129C7879B005B0CD9 /* CellFactoryProtocol.swift */; }; - 5864AF0929C78850005B0CD9 /* PreferencesCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5864AF0229C7879B005B0CD9 /* PreferencesCellFactory.swift */; }; + 5864AF0929C78850005B0CD9 /* VPNSettingsCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5864AF0229C7879B005B0CD9 /* VPNSettingsCellFactory.swift */; }; 5864AF7D2A9F4DC9008BC928 /* SettingsReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5864AF7C2A9F4DC9008BC928 /* SettingsReader.swift */; }; 5867770E29096984006F721F /* OutOfTimeInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5867770D29096984006F721F /* OutOfTimeInteractor.swift */; }; 58677710290975E9006F721F /* SettingsInteractorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5867770F290975E8006F721F /* SettingsInteractorFactory.swift */; }; @@ -169,7 +169,7 @@ 586C145A2AC4735F00245C01 /* PacketTunnelActor+Public.swift in Sources */ = {isa = PBXBuildFile; fileRef = 586C14592AC4735F00245C01 /* PacketTunnelActor+Public.swift */; }; 586E54FB27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 586E54FA27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift */; }; 586E8DB82AAF4AC4007BF3DA /* Task+Duration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 586E8DB72AAF4AC4007BF3DA /* Task+Duration.swift */; }; - 5871167F2910035700D41AAC /* PreferencesInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871167E2910035700D41AAC /* PreferencesInteractor.swift */; }; + 5871167F2910035700D41AAC /* VPNSettingsInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5871167E2910035700D41AAC /* VPNSettingsInteractor.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 */; }; 58727283265D173C00F315B2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 58727282265D173C00F315B2 /* LaunchScreen.storyboard */; }; @@ -198,8 +198,8 @@ 587D9676288989DB00CD8F1C /* NSLayoutConstraint+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587D9675288989DB00CD8F1C /* NSLayoutConstraint+Helpers.swift */; }; 587DCCEF287D84A500CE821E /* countries.geo.json in Resources */ = {isa = PBXBuildFile; fileRef = 587DCCEE287D84A500CE821E /* countries.geo.json */; }; 587EB66A270EFACB00123C75 /* CharacterSet+IPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB669270EFACB00123C75 /* CharacterSet+IPAddress.swift */; }; - 587EB672271451E300123C75 /* PreferencesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB671271451E300123C75 /* PreferencesViewModel.swift */; }; - 587EB6742714520600123C75 /* PreferencesDataSourceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB6732714520600123C75 /* PreferencesDataSourceDelegate.swift */; }; + 587EB672271451E300123C75 /* VPNSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB671271451E300123C75 /* VPNSettingsViewModel.swift */; }; + 587EB6742714520600123C75 /* VPNSettingsDataSourceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587EB6732714520600123C75 /* VPNSettingsDataSourceDelegate.swift */; }; 588395602A9DEEA1008B63F6 /* WgAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5883955F2A9DEEA1008B63F6 /* WgAdapter.swift */; }; 588527B2276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588527B1276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift */; }; 588527B4276B4F2F00BAA373 /* SetAccountOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588527B3276B4F2F00BAA373 /* SetAccountOperation.swift */; }; @@ -233,7 +233,7 @@ 58A8EE5A2976BFBB009C0F8D /* SKError+Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A8EE592976BFBB009C0F8D /* SKError+Localized.swift */; }; 58A8EE5E2976DB00009C0F8D /* StorePaymentManagerError+Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A8EE5D2976DB00009C0F8D /* StorePaymentManagerError+Display.swift */; }; 58A99ED3240014A0006599E9 /* TermsOfServiceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A99ED2240014A0006599E9 /* TermsOfServiceViewController.swift */; }; - 58ACF6492655365700ACE4B7 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ACF6482655365700ACE4B7 /* PreferencesViewController.swift */; }; + 58ACF6492655365700ACE4B7 /* VPNSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ACF6482655365700ACE4B7 /* VPNSettingsViewController.swift */; }; 58ACF64B26553C3F00ACE4B7 /* SettingsSwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ACF64A26553C3F00ACE4B7 /* SettingsSwitchCell.swift */; }; 58ACF64D26567A5000ACE4B7 /* CustomSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ACF64C26567A4F00ACE4B7 /* CustomSwitch.swift */; }; 58ACF64F26567A7100ACE4B7 /* CustomSwitchContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58ACF64E26567A7100ACE4B7 /* CustomSwitchContainer.swift */; }; @@ -481,6 +481,7 @@ 7A1A26472A29CF0800B978AA /* RelayFilterDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A26462A29CF0800B978AA /* RelayFilterDataSource.swift */; }; 7A1A26492A29D48A00B978AA /* RelayFilterCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A26482A29D48A00B978AA /* RelayFilterCellFactory.swift */; }; 7A21DACF2A30AA3700A787A9 /* UITextField+Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A21DACE2A30AA3700A787A9 /* UITextField+Appearance.swift */; }; + 7A28826A2BA8336600FD9F20 /* VPNSettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2882692BA8336600FD9F20 /* VPNSettingsCoordinator.swift */; }; 7A2960F62A963F7500389B82 /* AlertCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2960F52A963F7500389B82 /* AlertCoordinator.swift */; }; 7A2960FD2A964BB700389B82 /* AlertPresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2960FC2A964BB700389B82 /* AlertPresentation.swift */; }; 7A307AD92A8CD8DA0017618B /* Duration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A307AD82A8CD8DA0017618B /* Duration.swift */; }; @@ -536,7 +537,7 @@ 7A6F2FA92AFD0842006D0856 /* CustomDNSDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6F2FA82AFD0842006D0856 /* CustomDNSDataSource.swift */; }; 7A6F2FAB2AFD3097006D0856 /* CustomDNSCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6F2FAA2AFD3097006D0856 /* CustomDNSCellFactory.swift */; }; 7A6F2FAD2AFD3DA7006D0856 /* CustomDNSViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6F2FAC2AFD3DA7006D0856 /* CustomDNSViewController.swift */; }; - 7A6F2FAF2AFE36E7006D0856 /* PreferencesInfoButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6F2FAE2AFE36E7006D0856 /* PreferencesInfoButtonItem.swift */; }; + 7A6F2FAF2AFE36E7006D0856 /* VPNSettingsInfoButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6F2FAE2AFE36E7006D0856 /* VPNSettingsInfoButtonItem.swift */; }; 7A7AD28D29DC677800480EF1 /* FirstTimeLaunch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7AD28C29DC677800480EF1 /* FirstTimeLaunch.swift */; }; 7A818F1F29F0305800C7F0F4 /* RootConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A818F1E29F0305800C7F0F4 /* RootConfiguration.swift */; }; 7A83A0C62B29A750008B5CE7 /* APIAccessMethodsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A83A0C52B29A750008B5CE7 /* APIAccessMethodsTests.swift */; }; @@ -1433,7 +1434,7 @@ 584B26F3237434D00073B10E /* RelaySelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorTests.swift; sourceTree = ""; }; 584D0111299134AB00531822 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; 584D26BE270C550B004EA533 /* AnyIPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddress.swift; sourceTree = ""; }; - 584D26C3270C855A004EA533 /* PreferencesDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesDataSource.swift; sourceTree = ""; }; + 584D26C3270C855A004EA533 /* VPNSettingsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsDataSource.swift; sourceTree = ""; }; 584D26C5270C8741004EA533 /* SettingsDNSTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDNSTextCell.swift; sourceTree = ""; }; 58561C98239A5D1500BD6B5E /* IPv4Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPv4Endpoint.swift; sourceTree = ""; }; 5859A55429CD9DD800F66591 /* changes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = changes.txt; sourceTree = ""; }; @@ -1451,7 +1452,7 @@ 5864859A29A0EAF2006C5743 /* SecondaryContextPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondaryContextPresentationController.swift; sourceTree = ""; }; 5864AF0029C7879B005B0CD9 /* SettingsCellFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsCellFactory.swift; sourceTree = ""; }; 5864AF0129C7879B005B0CD9 /* CellFactoryProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFactoryProtocol.swift; sourceTree = ""; }; - 5864AF0229C7879B005B0CD9 /* PreferencesCellFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesCellFactory.swift; sourceTree = ""; }; + 5864AF0229C7879B005B0CD9 /* VPNSettingsCellFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VPNSettingsCellFactory.swift; sourceTree = ""; }; 5864AF7C2A9F4DC9008BC928 /* SettingsReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsReader.swift; sourceTree = ""; }; 5866F39B2243B82D00168AE5 /* MullvadVPN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MullvadVPN.entitlements; sourceTree = ""; }; 5867770D29096984006F721F /* OutOfTimeInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutOfTimeInteractor.swift; sourceTree = ""; }; @@ -1483,7 +1484,7 @@ 586E54FA27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTunnelProviderMessageOperation.swift; sourceTree = ""; }; 586E7A2C2A987689006DAB1B /* SettingsReaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsReaderProtocol.swift; sourceTree = ""; }; 586E8DB72AAF4AC4007BF3DA /* Task+Duration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Task+Duration.swift"; sourceTree = ""; }; - 5871167E2910035700D41AAC /* PreferencesInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesInteractor.swift; sourceTree = ""; }; + 5871167E2910035700D41AAC /* VPNSettingsInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsInteractor.swift; sourceTree = ""; }; 5871FB95254ADE4E0051A0A4 /* ConsolidatedApplicationLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsolidatedApplicationLog.swift; sourceTree = ""; }; 5871FB9F254C26BF0051A0A4 /* NSRegularExpression+IPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+IPAddress.swift"; sourceTree = ""; }; 58727282265D173C00F315B2 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; @@ -1516,8 +1517,8 @@ 587D9675288989DB00CD8F1C /* NSLayoutConstraint+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Helpers.swift"; sourceTree = ""; }; 587DCCEE287D84A500CE821E /* countries.geo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = countries.geo.json; sourceTree = ""; }; 587EB669270EFACB00123C75 /* CharacterSet+IPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+IPAddress.swift"; sourceTree = ""; }; - 587EB671271451E300123C75 /* PreferencesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewModel.swift; sourceTree = ""; }; - 587EB6732714520600123C75 /* PreferencesDataSourceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesDataSourceDelegate.swift; sourceTree = ""; }; + 587EB671271451E300123C75 /* VPNSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsViewModel.swift; sourceTree = ""; }; + 587EB6732714520600123C75 /* VPNSettingsDataSourceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsDataSourceDelegate.swift; sourceTree = ""; }; 5883955F2A9DEEA1008B63F6 /* WgAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WgAdapter.swift; sourceTree = ""; }; 588527B1276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadTunnelConfigurationOperation.swift; sourceTree = ""; }; 588527B3276B4F2F00BAA373 /* SetAccountOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetAccountOperation.swift; sourceTree = ""; }; @@ -1563,7 +1564,7 @@ 58A8EE5D2976DB00009C0F8D /* StorePaymentManagerError+Display.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StorePaymentManagerError+Display.swift"; sourceTree = ""; }; 58A94AE326CFD945001CB97C /* TunnelStatusNotificationProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelStatusNotificationProvider.swift; sourceTree = ""; }; 58A99ED2240014A0006599E9 /* TermsOfServiceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfServiceViewController.swift; sourceTree = ""; }; - 58ACF6482655365700ACE4B7 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; }; + 58ACF6482655365700ACE4B7 /* VPNSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsViewController.swift; sourceTree = ""; }; 58ACF64A26553C3F00ACE4B7 /* SettingsSwitchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSwitchCell.swift; sourceTree = ""; }; 58ACF64C26567A4F00ACE4B7 /* CustomSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSwitch.swift; sourceTree = ""; }; 58ACF64E26567A7100ACE4B7 /* CustomSwitchContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSwitchContainer.swift; sourceTree = ""; }; @@ -1734,6 +1735,7 @@ 7A1A26482A29D48A00B978AA /* RelayFilterCellFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterCellFactory.swift; sourceTree = ""; }; 7A1A264A2A29D65E00B978AA /* SelectableSettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectableSettingsCell.swift; sourceTree = ""; }; 7A21DACE2A30AA3700A787A9 /* UITextField+Appearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITextField+Appearance.swift"; sourceTree = ""; }; + 7A2882692BA8336600FD9F20 /* VPNSettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsCoordinator.swift; sourceTree = ""; }; 7A2960F52A963F7500389B82 /* AlertCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertCoordinator.swift; sourceTree = ""; }; 7A2960FC2A964BB700389B82 /* AlertPresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertPresentation.swift; sourceTree = ""; }; 7A307AD82A8CD8DA0017618B /* Duration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Duration.swift; sourceTree = ""; }; @@ -1785,7 +1787,7 @@ 7A6F2FA82AFD0842006D0856 /* CustomDNSDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDNSDataSource.swift; sourceTree = ""; }; 7A6F2FAA2AFD3097006D0856 /* CustomDNSCellFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDNSCellFactory.swift; sourceTree = ""; }; 7A6F2FAC2AFD3DA7006D0856 /* CustomDNSViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDNSViewController.swift; sourceTree = ""; }; - 7A6F2FAE2AFE36E7006D0856 /* PreferencesInfoButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesInfoButtonItem.swift; sourceTree = ""; }; + 7A6F2FAE2AFE36E7006D0856 /* VPNSettingsInfoButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSettingsInfoButtonItem.swift; sourceTree = ""; }; 7A7AD28C29DC677800480EF1 /* FirstTimeLaunch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstTimeLaunch.swift; sourceTree = ""; }; 7A818F1E29F0305800C7F0F4 /* RootConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootConfiguration.swift; sourceTree = ""; }; 7A83A0C52B29A750008B5CE7 /* APIAccessMethodsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIAccessMethodsTests.swift; sourceTree = ""; }; @@ -2395,7 +2397,7 @@ 583FE02529C1AD0E006E85F9 /* Launch */, 583FE02129C1A0F4006E85F9 /* Login */, 583FE01B29C19786006E85F9 /* OutOfTime */, - 583FE01A29C19777006E85F9 /* Preferences */, + 583FE01A29C19777006E85F9 /* VPNSettings */, 583FE01929C19760006E85F9 /* ProblemReport */, F028A5472A336E1900C0CAA3 /* RedeemVoucher */, 7AF9BE912A39F47D00DBFEDB /* RelayFilter */, @@ -2461,21 +2463,21 @@ path = ProblemReport; sourceTree = ""; }; - 583FE01A29C19777006E85F9 /* Preferences */ = { + 583FE01A29C19777006E85F9 /* VPNSettings */ = { isa = PBXGroup; children = ( 7A6F2FAA2AFD3097006D0856 /* CustomDNSCellFactory.swift */, 7A6F2FA82AFD0842006D0856 /* CustomDNSDataSource.swift */, 7A6F2FAC2AFD3DA7006D0856 /* CustomDNSViewController.swift */, - 5864AF0229C7879B005B0CD9 /* PreferencesCellFactory.swift */, - 584D26C3270C855A004EA533 /* PreferencesDataSource.swift */, - 587EB6732714520600123C75 /* PreferencesDataSourceDelegate.swift */, - 7A6F2FAE2AFE36E7006D0856 /* PreferencesInfoButtonItem.swift */, - 5871167E2910035700D41AAC /* PreferencesInteractor.swift */, - 58ACF6482655365700ACE4B7 /* PreferencesViewController.swift */, - 587EB671271451E300123C75 /* PreferencesViewModel.swift */, - ); - path = Preferences; + 5864AF0229C7879B005B0CD9 /* VPNSettingsCellFactory.swift */, + 584D26C3270C855A004EA533 /* VPNSettingsDataSource.swift */, + 587EB6732714520600123C75 /* VPNSettingsDataSourceDelegate.swift */, + 7A6F2FAE2AFE36E7006D0856 /* VPNSettingsInfoButtonItem.swift */, + 5871167E2910035700D41AAC /* VPNSettingsInteractor.swift */, + 58ACF6482655365700ACE4B7 /* VPNSettingsViewController.swift */, + 587EB671271451E300123C75 /* VPNSettingsViewModel.swift */, + ); + path = VPNSettings; sourceTree = ""; }; 583FE01B29C19786006E85F9 /* OutOfTime */ = { @@ -3118,6 +3120,7 @@ 7A9CCCA62A96302700DD6A34 /* SetupAccountCompletedCoordinator.swift */, 7A9CCCA22A96302700DD6A34 /* TermsOfServiceCoordinator.swift */, 7A9CCCB22A96302800DD6A34 /* TunnelCoordinator.swift */, + 7A2882692BA8336600FD9F20 /* VPNSettingsCoordinator.swift */, 7A9CCCA12A96302700DD6A34 /* WelcomeCoordinator.swift */, ); path = Coordinators; @@ -5097,7 +5100,7 @@ 7A5869952B32E9C700640D27 /* LinkButton.swift in Sources */, F09A297D2A9F8A9B00EA3B6F /* RedeemVoucherContentView.swift in Sources */, 5803B4B02940A47300C23744 /* TunnelConfiguration.swift in Sources */, - 587EB672271451E300123C75 /* PreferencesViewModel.swift in Sources */, + 587EB672271451E300123C75 /* VPNSettingsViewModel.swift in Sources */, 586A950C290125EE007BAF2B /* AlertPresenter.swift in Sources */, 7A9FA1422A2E3306000B728D /* CheckboxView.swift in Sources */, 586C0D892B03D5E000E7CDD7 /* TextCellContentConfiguration+Extensions.swift in Sources */, @@ -5142,7 +5145,7 @@ 7A6000FC2B628DF6001CF0D9 /* ListCellContentConfiguration.swift in Sources */, 582BB1B1229569620055B6EF /* UINavigationBar+Appearance.swift in Sources */, 7A9FA1442A2E3FE5000B728D /* CheckableSettingsCell.swift in Sources */, - 58ACF6492655365700ACE4B7 /* PreferencesViewController.swift in Sources */, + 58ACF6492655365700ACE4B7 /* VPNSettingsViewController.swift in Sources */, 7ABE318D2A1CDD4500DF4963 /* UIFont+Weight.swift in Sources */, 58C774BE29A7A249003A1A56 /* CustomNavigationController.swift in Sources */, E1FD0DF528AA7CE400299DB4 /* StatusActivityView.swift in Sources */, @@ -5152,7 +5155,7 @@ 0697D6E728F01513007A9E99 /* TransportMonitor.swift in Sources */, 58968FAE28743E2000B799DC /* TunnelInteractor.swift in Sources */, 7A1A26472A29CF0800B978AA /* RelayFilterDataSource.swift in Sources */, - 5864AF0929C78850005B0CD9 /* PreferencesCellFactory.swift in Sources */, + 5864AF0929C78850005B0CD9 /* VPNSettingsCellFactory.swift in Sources */, F050AE4E2B70D7F8003F4EDB /* LocationCellViewModel.swift in Sources */, 58CEB30C2AFD586600E6E088 /* DynamicBackgroundConfiguration.swift in Sources */, 587B7536266528A200DEF7E9 /* NotificationManager.swift in Sources */, @@ -5233,6 +5236,7 @@ 58E25F812837BBBB002CFB2C /* SceneDelegate.swift in Sources */, 7A1A26492A29D48A00B978AA /* RelayFilterCellFactory.swift in Sources */, 5867771629097C5B006F721F /* ProductState.swift in Sources */, + 7A28826A2BA8336600FD9F20 /* VPNSettingsCoordinator.swift in Sources */, 7A6389DE2B7E3BD6008E77E1 /* CustomListItemIdentifier.swift in Sources */, 58C76A082A33850E00100D75 /* ApplicationTarget.swift in Sources */, 58CEB3042AFD36CE00E6E088 /* SwitchCellContentView.swift in Sources */, @@ -5245,7 +5249,7 @@ 58DF28A52417CB4B00E836B0 /* StorePaymentManager.swift in Sources */, 583DA21425FA4B5C00318683 /* LocationDataSource.swift in Sources */, F050AE602B73A41E003F4EDB /* AllLocationDataSource.swift in Sources */, - 587EB6742714520600123C75 /* PreferencesDataSourceDelegate.swift in Sources */, + 587EB6742714520600123C75 /* VPNSettingsDataSourceDelegate.swift in Sources */, 7AB2B6712BA1EB8C00B03E3B /* ListCustomListCoordinator.swift in Sources */, 582BB1AF229566420055B6EF /* SettingsCell.swift in Sources */, 7AF9BE8E2A331C7B00DBFEDB /* RelayFilterViewModel.swift in Sources */, @@ -5364,16 +5368,16 @@ F09D04BD2AEBB7C5003D4F89 /* OutgoingConnectionService.swift in Sources */, 58FF9FF42B07C61B00E4C97D /* AccessMethodValidationError.swift in Sources */, 5896AE84246D5889005B36CB /* CustomDateComponentsFormatting.swift in Sources */, - 5871167F2910035700D41AAC /* PreferencesInteractor.swift in Sources */, + 5871167F2910035700D41AAC /* VPNSettingsInteractor.swift in Sources */, 7A9CCCC22A96302800DD6A34 /* SafariCoordinator.swift in Sources */, 58CEB3082AFD484100E6E088 /* BasicCell.swift in Sources */, 7A5869C12B57D21A00640D27 /* IPOverrideStatusView.swift in Sources */, 58CEB2F52AFD0BB500E6E088 /* TextCellContentConfiguration.swift in Sources */, 58E20771274672CA00DE5D77 /* LaunchViewController.swift in Sources */, F0E8CC032A4C753B007ED3B4 /* WelcomeViewController.swift in Sources */, - 584D26C4270C855B004EA533 /* PreferencesDataSource.swift in Sources */, + 584D26C4270C855B004EA533 /* VPNSettingsDataSource.swift in Sources */, F0D8825B2B04F53600D3EF9A /* OutgoingConnectionData.swift in Sources */, - 7A6F2FAF2AFE36E7006D0856 /* PreferencesInfoButtonItem.swift in Sources */, + 7A6F2FAF2AFE36E7006D0856 /* VPNSettingsInfoButtonItem.swift in Sources */, 7A6389DD2B7E3BD6008E77E1 /* CustomListDataSourceConfiguration.swift in Sources */, 5827B0BF2B14B37D00CCBBA1 /* Publisher+PreviousValue.swift in Sources */, 7A9CCCB62A96302800DD6A34 /* OutOfTimeCoordinator.swift in Sources */, diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift index 8a911b97c120..48651c39f302 100644 --- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift +++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift @@ -37,12 +37,11 @@ public enum AccessibilityIdentifier: String { case problemReportSendButton // Cells - case preferencesCell + case vpnSettingsCell case versionCell case problemReportCell case faqCell case apiAccessCell - case ipOverrideCell case relayFilterOwnershipCell case relayFilterProviderCell @@ -83,6 +82,7 @@ public enum AccessibilityIdentifier: String { // DNS settings case dnsSettings + case ipOverrides case wireGuardCustomPort case wireGuardObfuscationAutomatic case wireGuardObfuscationOff diff --git a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift index b92a5492d845..ff113f5803b1 100644 --- a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift @@ -772,7 +772,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo storePaymentManager: storePaymentManager, tunnelManager: tunnelManager, apiProxy: apiProxy, - relayCacheTracker: relayCacheTracker + relayCacheTracker: relayCacheTracker, + ipOverrideRepository: ipOverrideRepository ) let navigationController = CustomNavigationController() diff --git a/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideCoordinator.swift b/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideCoordinator.swift index 7c444e781b2b..e4d6f504d25e 100644 --- a/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideCoordinator.swift @@ -15,15 +15,6 @@ class IPOverrideCoordinator: Coordinator, Presenting, SettingsChildCoordinator { private let navigationController: UINavigationController private let interactor: IPOverrideInteractor - private lazy var ipOverrideViewController: IPOverrideViewController = { - let viewController = IPOverrideViewController( - interactor: interactor, - alertPresenter: AlertPresenter(context: self) - ) - viewController.delegate = self - return viewController - }() - var presentationContext: UIViewController { navigationController } @@ -38,7 +29,14 @@ class IPOverrideCoordinator: Coordinator, Presenting, SettingsChildCoordinator { } func start(animated: Bool) { - navigationController.pushViewController(ipOverrideViewController, animated: animated) + let controller = IPOverrideViewController( + interactor: interactor, + alertPresenter: AlertPresenter(context: self) + ) + + controller.delegate = self + + navigationController.pushViewController(controller, animated: animated) } } diff --git a/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideViewController.swift b/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideViewController.swift index 5f8021d4e049..1088a86a2de5 100644 --- a/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideViewController.swift +++ b/ios/MullvadVPN/Coordinators/Settings/IPOverride/IPOverrideViewController.swift @@ -147,10 +147,8 @@ class IPOverrideViewController: UIViewController { value: """ On some networks, where various types of censorship are being used, our server IP addresses are \ sometimes blocked. - To circumvent this you can import a file or a text, provided by our support team, \ with new IP addresses that override the default addresses of the servers in the Select location view. - If you are having issues connecting to VPN servers, please contact support. """, comment: "" diff --git a/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift b/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift index 4ace0cd561ad..c9a44223ff17 100644 --- a/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift @@ -18,7 +18,7 @@ enum SettingsNavigationRoute: Equatable { case root /// VPN settings. - case preferences + case vpnSettings /// Problem report. case problemReport @@ -28,9 +28,6 @@ enum SettingsNavigationRoute: Equatable { /// API access route. case apiAccess - - /// IP override route. - case ipOverride } /// Top-level settings coordinator. @@ -246,10 +243,11 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV controller.delegate = self return .viewController(controller) - case .preferences: - return .viewController(PreferencesViewController( - interactor: interactorFactory.makePreferencesInteractor(), - alertPresenter: AlertPresenter(context: self) + case .vpnSettings: + return .childCoordinator(VPNSettingsCoordinator( + navigationController: navigationController, + interactorFactory: interactorFactory, + ipOverrideRepository: ipOverrideRepository )) case .problemReport: @@ -265,13 +263,6 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV proxyConfigurationTester: proxyConfigurationTester )) - case .ipOverride: - return .childCoordinator(IPOverrideCoordinator( - navigationController: navigationController, - repository: ipOverrideRepository, - tunnelManager: interactorFactory.tunnelManager - )) - case .faq: // Handled separately and presented as a modal. return .failed @@ -285,14 +276,12 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV switch viewController { case is SettingsViewController: return .root - case is PreferencesViewController: - return .preferences + case is VPNSettingsViewController: + return .vpnSettings case is ProblemReportViewController: return .problemReport case is ListAccessMethodViewController: return .apiAccess - case is IPOverrideViewController: - return .ipOverride default: return nil } diff --git a/ios/MullvadVPN/Coordinators/VPNSettingsCoordinator.swift b/ios/MullvadVPN/Coordinators/VPNSettingsCoordinator.swift new file mode 100644 index 000000000000..8d2db23e57c2 --- /dev/null +++ b/ios/MullvadVPN/Coordinators/VPNSettingsCoordinator.swift @@ -0,0 +1,56 @@ +// +// VPNSettingsCoordinator.swift +// MullvadVPN +// +// Created by Jon Petersson on 2024-03-18. +// Copyright © 2024 Mullvad VPN AB. All rights reserved. +// + +import MullvadSettings +import MullvadTypes +import Routing +import UIKit + +class VPNSettingsCoordinator: Coordinator, Presenting, SettingsChildCoordinator { + private let navigationController: UINavigationController + private let interactorFactory: SettingsInteractorFactory + private let ipOverrideRepository: IPOverrideRepositoryProtocol + + var presentationContext: UIViewController { + navigationController + } + + init( + navigationController: UINavigationController, + interactorFactory: SettingsInteractorFactory, + ipOverrideRepository: IPOverrideRepositoryProtocol + ) { + self.navigationController = navigationController + self.interactorFactory = interactorFactory + self.ipOverrideRepository = ipOverrideRepository + } + + func start(animated: Bool) { + let controller = VPNSettingsViewController( + interactor: interactorFactory.makeVPNSettingsInteractor(), + alertPresenter: AlertPresenter(context: self) + ) + + controller.delegate = self + + navigationController.pushViewController(controller, animated: animated) + } +} + +extension VPNSettingsCoordinator: VPNSettingsViewControllerDelegate { + func showIPOverrides() { + let coordinator = IPOverrideCoordinator( + navigationController: navigationController, + repository: ipOverrideRepository, + tunnelManager: interactorFactory.tunnelManager + ) + + addChild(coordinator) + coordinator.start(animated: true) + } +} diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSourceDelegate.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSourceDelegate.swift deleted file mode 100644 index b1ffa410fe0d..000000000000 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSourceDelegate.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// PreferencesDataSourceDelegate.swift -// MullvadVPN -// -// Created by pronebird on 11/10/2021. -// Copyright © 2021 Mullvad VPN AB. All rights reserved. -// - -import Foundation - -protocol PreferencesDataSourceDelegate: AnyObject { - func didChangeViewModel(_ viewModel: PreferencesViewModel) - func showInfo(for: PreferencesInfoButtonItem) - func showDNSSettings() - func didSelectWireGuardPort(_ port: UInt16?) -} diff --git a/ios/MullvadVPN/View controllers/Settings/SettingsCellFactory.swift b/ios/MullvadVPN/View controllers/Settings/SettingsCellFactory.swift index 7f5f2d02a692..1085f7f71c9f 100644 --- a/ios/MullvadVPN/View controllers/Settings/SettingsCellFactory.swift +++ b/ios/MullvadVPN/View controllers/Settings/SettingsCellFactory.swift @@ -28,11 +28,11 @@ struct SettingsCellFactory: CellFactoryProtocol { // swiftlint:disable:next function_body_length func configureCell(_ cell: UITableViewCell, item: SettingsDataSource.Item, indexPath: IndexPath) { switch item { - case .preferences: + case .vpnSettings: guard let cell = cell as? SettingsCell else { return } cell.titleLabel.text = NSLocalizedString( - "PREFERENCES_CELL_LABEL", + "VPN_SETTINGS_CELL_LABEL", tableName: "Settings", value: "VPN settings", comment: "" @@ -92,19 +92,6 @@ struct SettingsCellFactory: CellFactoryProtocol { cell.detailTitleLabel.text = nil cell.accessibilityIdentifier = item.accessibilityIdentifier cell.disclosureType = .chevron - - case .ipOverride: - guard let cell = cell as? SettingsCell else { return } - - cell.titleLabel.text = NSLocalizedString( - "IP_OVERRIDE_CELL_LABEL", - tableName: "Settings", - value: "Server IP override", - comment: "" - ) - cell.detailTitleLabel.text = nil - cell.accessibilityIdentifier = item.accessibilityIdentifier - cell.disclosureType = .chevron } } } diff --git a/ios/MullvadVPN/View controllers/Settings/SettingsDataSource.swift b/ios/MullvadVPN/View controllers/Settings/SettingsDataSource.swift index d4885ee100dc..87143fc84f34 100644 --- a/ios/MullvadVPN/View controllers/Settings/SettingsDataSource.swift +++ b/ios/MullvadVPN/View controllers/Settings/SettingsDataSource.swift @@ -34,17 +34,16 @@ final class SettingsDataSource: UITableViewDiffableDataSource PreferencesInteractor { - PreferencesInteractor(tunnelManager: tunnelManager, relayCacheTracker: relayCacheTracker) + func makeVPNSettingsInteractor() -> VPNSettingsInteractor { + VPNSettingsInteractor(tunnelManager: tunnelManager, relayCacheTracker: relayCacheTracker) } func makeProblemReportInteractor() -> ProblemReportInteractor { @@ -39,4 +42,8 @@ final class SettingsInteractorFactory { func makeSettingsInteractor() -> SettingsInteractor { SettingsInteractor(tunnelManager: tunnelManager) } + + func makeIPOverrideInteractor() -> IPOverrideInteractor { + IPOverrideInteractor(repository: ipOverrideRepository, tunnelManager: tunnelManager) + } } diff --git a/ios/MullvadVPN/View controllers/Settings/SettingsViewController.swift b/ios/MullvadVPN/View controllers/Settings/SettingsViewController.swift index 13f6f6d1e2a0..ed964a8dbe5b 100644 --- a/ios/MullvadVPN/View controllers/Settings/SettingsViewController.swift +++ b/ios/MullvadVPN/View controllers/Settings/SettingsViewController.swift @@ -79,8 +79,8 @@ class SettingsViewController: UITableViewController, SettingsDataSourceDelegate extension SettingsDataSource.Item { var navigationRoute: SettingsNavigationRoute? { switch self { - case .preferences: - return .preferences + case .vpnSettings: + return .vpnSettings case .version: return nil case .problemReport: @@ -89,8 +89,6 @@ extension SettingsDataSource.Item { return .faq case .apiAccess: return .apiAccess - case .ipOverride: - return .ipOverride } } } diff --git a/ios/MullvadVPN/View controllers/Preferences/CustomDNSCellFactory.swift b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSCellFactory.swift similarity index 93% rename from ios/MullvadVPN/View controllers/Preferences/CustomDNSCellFactory.swift rename to ios/MullvadVPN/View controllers/VPNSettings/CustomDNSCellFactory.swift index 18729b56a117..a45be6a538c2 100644 --- a/ios/MullvadVPN/View controllers/Preferences/CustomDNSCellFactory.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSCellFactory.swift @@ -13,16 +13,16 @@ protocol CustomDNSCellEventHandler { func addDNSEntry() func didChangeDNSEntry(with identifier: UUID, inputString: String) -> Bool func didChangeState(for preference: CustomDNSDataSource.Item, isOn: Bool) - func showInfo(for button: PreferencesInfoButtonItem) + func showInfo(for button: VPNSettingsInfoButtonItem) } final class CustomDNSCellFactory: CellFactoryProtocol { let tableView: UITableView - var viewModel: PreferencesViewModel + var viewModel: VPNSettingsViewModel var delegate: CustomDNSCellEventHandler? var isEditing = false - init(tableView: UITableView, viewModel: PreferencesViewModel) { + init(tableView: UITableView, viewModel: VPNSettingsViewModel) { self.tableView = tableView self.viewModel = viewModel } @@ -61,7 +61,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { case .blockAdvertising: let localizedString = NSLocalizedString( "BLOCK_ADS_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Ads", comment: "" ) @@ -76,7 +76,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { case .blockTracking: let localizedString = NSLocalizedString( "BLOCK_TRACKERS_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Trackers", comment: "" ) @@ -92,7 +92,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { let localizedString = NSLocalizedString( "BLOCK_MALWARE_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Malware", comment: "" ) @@ -109,7 +109,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { case .blockAdultContent: let localizedString = NSLocalizedString( "BLOCK_ADULT_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Adult content", comment: "" ) @@ -123,7 +123,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { case .blockGambling: let localizedString = NSLocalizedString( "BLOCK_GAMBLING_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Gambling", comment: "" ) @@ -137,7 +137,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { case .blockSocialMedia: let localizedString = NSLocalizedString( "BLOCK_SOCIAL_MEDIA_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Social media", comment: "" ) @@ -153,7 +153,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "CUSTOM_DNS_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Use custom DNS", comment: "" ) @@ -170,7 +170,7 @@ final class CustomDNSCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "ADD_CUSTOM_DNS_SERVER_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Add a server", comment: "" ) diff --git a/ios/MullvadVPN/View controllers/Preferences/CustomDNSDataSource.swift b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSDataSource.swift similarity index 98% rename from ios/MullvadVPN/View controllers/Preferences/CustomDNSDataSource.swift rename to ios/MullvadVPN/View controllers/VPNSettings/CustomDNSDataSource.swift index afed9c584597..32d72cb2189b 100644 --- a/ios/MullvadVPN/View controllers/Preferences/CustomDNSDataSource.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSDataSource.swift @@ -113,14 +113,14 @@ final class CustomDNSDataSource: UITableViewDiffableDataSource< private var isEditing = false - private(set) var viewModel = PreferencesViewModel() { didSet { + private(set) var viewModel = VPNSettingsViewModel() { didSet { cellFactory.viewModel = viewModel }} - private(set) var viewModelBeforeEditing = PreferencesViewModel() + private(set) var viewModelBeforeEditing = VPNSettingsViewModel() private let cellFactory: CustomDNSCellFactory private weak var tableView: UITableView? - weak var delegate: PreferencesDataSourceDelegate? + weak var delegate: VPNSettingsDataSourceDelegate? init(tableView: UITableView) { self.tableView = tableView @@ -169,7 +169,7 @@ final class CustomDNSDataSource: UITableViewDiffableDataSource< } func update(from tunnelSettings: LatestTunnelSettings) { - let newViewModel = PreferencesViewModel(from: tunnelSettings) + let newViewModel = VPNSettingsViewModel(from: tunnelSettings) let mergedViewModel = viewModel.merged(newViewModel) if viewModel != mergedViewModel { @@ -582,7 +582,7 @@ final class CustomDNSDataSource: UITableViewDiffableDataSource< private func configureContentBlockersHeader(_ header: SettingsHeaderView) { let title = NSLocalizedString( "CONTENT_BLOCKERS_HEADER_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "DNS content blockers", comment: "" ) @@ -652,7 +652,7 @@ extension CustomDNSDataSource: CustomDNSCellEventHandler { handleDNSEntryChange(with: identifier, inputString: inputString) } - func showInfo(for button: PreferencesInfoButtonItem) { + func showInfo(for button: VPNSettingsInfoButtonItem) { delegate?.showInfo(for: button) } } diff --git a/ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift similarity index 85% rename from ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift rename to ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift index f9cc03d50392..53a52275ea8f 100644 --- a/ios/MullvadVPN/View controllers/Preferences/CustomDNSViewController.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/CustomDNSViewController.swift @@ -9,8 +9,8 @@ import MullvadSettings import UIKit -class CustomDNSViewController: UITableViewController, PreferencesDataSourceDelegate { - private let interactor: PreferencesInteractor +class CustomDNSViewController: UITableViewController, VPNSettingsDataSourceDelegate { + private let interactor: VPNSettingsInteractor private var dataSource: CustomDNSDataSource? private let alertPresenter: AlertPresenter @@ -18,7 +18,7 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg .lightContent } - init(interactor: PreferencesInteractor, alertPresenter: AlertPresenter) { + init(interactor: VPNSettingsInteractor, alertPresenter: AlertPresenter) { self.interactor = interactor self.alertPresenter = alertPresenter @@ -43,7 +43,7 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg navigationItem.title = NSLocalizedString( "NAVIGATION_TITLE", - tableName: "Preferences", + tableName: "VPNSettings", value: "DNS settings", comment: "" ) @@ -73,13 +73,13 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg private func showInfo(with message: String) { let presentation = AlertPresentation( - id: "preferences-content-blockers-alert", + id: "vpn-settings-content-blockers-alert", icon: .info, message: message, buttons: [ AlertAction( title: NSLocalizedString( - "PREFERENCES_DNS_SETTINGS_OK_ACTION", + "VPN_SETTINGS_DNS_SETTINGS_OK_ACTION", tableName: "ContentBlockers", value: "Got it!", comment: "" @@ -92,19 +92,19 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg alertPresenter.showAlert(presentation: presentation, animated: true) } - // MARK: - PreferencesDataSourceDelegate + // MARK: - VPNSettingsDataSourceDelegate - func didChangeViewModel(_ viewModel: PreferencesViewModel) { + func didChangeViewModel(_ viewModel: VPNSettingsViewModel) { interactor.updateSettings([.dnsSettings(viewModel.asDNSSettings())]) } - func showInfo(for item: PreferencesInfoButtonItem) { + func showInfo(for item: VPNSettingsInfoButtonItem) { var message = "" switch item { case .contentBlockers: message = NSLocalizedString( - "PREFERENCES_CONTENT_BLOCKERS_GENERAL", + "VPN_SETTINGS_CONTENT_BLOCKERS_GENERAL", tableName: "ContentBlockers", value: """ When this feature is enabled it stops the device from contacting certain \ @@ -116,7 +116,7 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg case .blockMalware: message = NSLocalizedString( - "PREFERENCES_CONTENT_BLOCKERS_MALWARE", + "VPN_SETTINGS_CONTENT_BLOCKERS_MALWARE", tableName: "ContentBlockers", value: """ Warning: The malware blocker is not an anti-virus and should not \ @@ -136,6 +136,10 @@ class CustomDNSViewController: UITableViewController, PreferencesDataSourceDeleg // No op. } + func showIPOverrides() { + // No op. + } + func didSelectWireGuardPort(_ port: UInt16?) { // No op. } diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift similarity index 82% rename from ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift rename to ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift index 8e739c33fdf9..8e6ed59018a5 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsCellFactory.swift @@ -1,5 +1,5 @@ // -// PreferencesCellFactory.swift +// VPNSettingsCellFactory.swift // MullvadVPN // // Created by Jon Petersson on 2023-03-09. @@ -9,25 +9,25 @@ import MullvadSettings import UIKit -protocol PreferencesCellEventHandler { - func showInfo(for button: PreferencesInfoButtonItem) +protocol VPNSettingsCellEventHandler { + func showInfo(for button: VPNSettingsInfoButtonItem) func addCustomPort(_ port: UInt16) func selectCustomPortEntry(_ port: UInt16) -> Bool func selectObfuscationState(_ state: WireGuardObfuscationState) } -final class PreferencesCellFactory: CellFactoryProtocol { +final class VPNSettingsCellFactory: CellFactoryProtocol { let tableView: UITableView - var viewModel: PreferencesViewModel - var delegate: PreferencesCellEventHandler? + var viewModel: VPNSettingsViewModel + var delegate: VPNSettingsCellEventHandler? var isEditing = false - init(tableView: UITableView, viewModel: PreferencesViewModel) { + init(tableView: UITableView, viewModel: VPNSettingsViewModel) { self.tableView = tableView self.viewModel = viewModel } - func makeCell(for item: PreferencesDataSource.Item, indexPath: IndexPath) -> UITableViewCell { + func makeCell(for item: VPNSettingsDataSource.Item, indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: item.reuseIdentifier.rawValue, for: indexPath) configureCell(cell, item: item, indexPath: indexPath) @@ -36,14 +36,14 @@ final class PreferencesCellFactory: CellFactoryProtocol { } // swiftlint:disable:next cyclomatic_complexity function_body_length - func configureCell(_ cell: UITableViewCell, item: PreferencesDataSource.Item, indexPath: IndexPath) { + func configureCell(_ cell: UITableViewCell, item: VPNSettingsDataSource.Item, indexPath: IndexPath) { switch item { case .dnsSettings: guard let cell = cell as? SettingsCell else { return } cell.titleLabel.text = NSLocalizedString( "DNS_SETTINGS_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "DNS settings", comment: "" ) @@ -51,12 +51,25 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.disclosureType = .chevron cell.accessibilityIdentifier = item.accessibilityIdentifier + case .ipOverrides: + guard let cell = cell as? SettingsCell else { return } + + cell.titleLabel.text = NSLocalizedString( + "IP_OVERRIDE_CELL_LABEL", + tableName: "VPNSettings", + value: "Server IP override", + comment: "" + ) + + cell.disclosureType = .chevron + cell.accessibilityIdentifier = item.accessibilityIdentifier + case let .wireGuardPort(port): guard let cell = cell as? SelectableSettingsCell else { return } var portString = NSLocalizedString( "WIRE_GUARD_PORT_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Automatic", comment: "" ) @@ -73,13 +86,13 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "WIRE_GUARD_CUSTOM_PORT_CELL_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Custom", comment: "" ) cell.textField.placeholder = NSLocalizedString( "WIRE_GUARD_CUSTOM_PORT_CELL_INPUT_PLACEHOLDER", - tableName: "Preferences", + tableName: "VPNSettings", value: "Port", comment: "" ) @@ -113,7 +126,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "WIRE_GUARD_OBFUSCATION_AUTOMATIC_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Automatic", comment: "" ) @@ -125,7 +138,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "WIRE_GUARD_OBFUSCATION_ON_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "On (UDP-over-TCP)", comment: "" ) @@ -136,7 +149,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "WIRE_GUARD_OBFUSCATION_OFF_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Off", comment: "" ) @@ -149,7 +162,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { let portString = port == 0 ? "Automatic" : "\(port)" cell.titleLabel.text = NSLocalizedString( "WIRE_GUARD_OBFUSCATION_PORT_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: portString, comment: "" ) @@ -162,7 +175,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "QUANTUM_RESISTANCE_AUTOMATIC_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Automatic", comment: "" ) @@ -174,7 +187,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "QUANTUM_RESISTANCE_ON_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "On", comment: "" ) @@ -185,7 +198,7 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.titleLabel.text = NSLocalizedString( "QUANTUM_RESISTANCE_OFF_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Off", comment: "" ) diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift similarity index 91% rename from ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift rename to ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift index b984bc1f7176..f42d0d343bf8 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSource.swift @@ -1,5 +1,5 @@ // -// PreferencesDataSource.swift +// VPNSettingsDataSource.swift // MullvadVPN // // Created by pronebird on 05/10/2021. @@ -9,14 +9,15 @@ import MullvadSettings import UIKit -final class PreferencesDataSource: UITableViewDiffableDataSource< - PreferencesDataSource.Section, - PreferencesDataSource.Item +final class VPNSettingsDataSource: UITableViewDiffableDataSource< + VPNSettingsDataSource.Section, + VPNSettingsDataSource.Item >, UITableViewDelegate { typealias InfoButtonHandler = (Item) -> Void enum CellReuseIdentifiers: String, CaseIterable { case dnsSettings + case ipOverrides case wireGuardPort case wireGuardCustomPort case wireGuardObfuscation @@ -26,6 +27,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< switch self { case .dnsSettings: return SettingsCell.self + case .ipOverrides: + return SettingsCell.self case .wireGuardPort: return SelectableSettingsCell.self case .wireGuardCustomPort: @@ -50,6 +53,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< enum Section: String, Hashable, CaseIterable { case dnsSettings + case ipOverrides case wireGuardPorts case wireGuardObfuscation case wireGuardObfuscationPort @@ -60,6 +64,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< enum Item: Hashable { case dnsSettings + case ipOverrides case wireGuardPort(_ port: UInt16?) case wireGuardCustomPort case wireGuardObfuscationAutomatic @@ -73,7 +78,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< #endif static var wireGuardPorts: [Item] { - let defaultPorts = PreferencesViewModel.defaultWireGuardPorts.map { + let defaultPorts = VPNSettingsViewModel.defaultWireGuardPorts.map { Item.wireGuardPort($0) } return [.wireGuardPort(nil)] + defaultPorts + [.wireGuardCustomPort] @@ -97,6 +102,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< switch self { case .dnsSettings: return .dnsSettings + case .ipOverrides: + return .ipOverrides case .wireGuardPort: return .wireGuardPort case .wireGuardCustomPort: @@ -124,6 +131,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< switch self { case .dnsSettings: return .dnsSettings + case .ipOverrides: + return .ipOverrides case .wireGuardPort: return .wireGuardPort case .wireGuardCustomPort: @@ -140,13 +149,13 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< } } - private(set) var viewModel = PreferencesViewModel() { didSet { - preferencesCellFactory.viewModel = viewModel + private(set) var viewModel = VPNSettingsViewModel() { didSet { + vpnSettingsCellFactory.viewModel = viewModel }} - private let preferencesCellFactory: PreferencesCellFactory + private let vpnSettingsCellFactory: VPNSettingsCellFactory private weak var tableView: UITableView? - weak var delegate: PreferencesDataSourceDelegate? + weak var delegate: VPNSettingsDataSourceDelegate? var selectedIndexPaths: [IndexPath] { let wireGuardPortItem: Item = viewModel.customWireGuardPort == nil @@ -187,18 +196,18 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< init(tableView: UITableView) { self.tableView = tableView - let preferencesCellFactory = PreferencesCellFactory( + let vpnSettingsCellFactory = VPNSettingsCellFactory( tableView: tableView, viewModel: viewModel ) - self.preferencesCellFactory = preferencesCellFactory + self.vpnSettingsCellFactory = vpnSettingsCellFactory super.init(tableView: tableView) { _, indexPath, itemIdentifier in - preferencesCellFactory.makeCell(for: itemIdentifier, indexPath: indexPath) + vpnSettingsCellFactory.makeCell(for: itemIdentifier, indexPath: indexPath) } tableView.delegate = self - preferencesCellFactory.delegate = self + vpnSettingsCellFactory.delegate = self registerClasses() } @@ -232,7 +241,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< } func update(from tunnelSettings: LatestTunnelSettings) { - let newViewModel = PreferencesViewModel(from: tunnelSettings) + let newViewModel = VPNSettingsViewModel(from: tunnelSettings) let mergedViewModel = viewModel.merged(newViewModel) if viewModel != mergedViewModel { @@ -260,6 +269,10 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< tableView.deselectRow(at: indexPath, animated: false) delegate?.showDNSSettings() + case .ipOverrides: + tableView.deselectRow(at: indexPath, animated: false) + delegate?.showIPOverrides() + case let .wireGuardPort(port): viewModel.setWireGuardPort(port) @@ -307,7 +320,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< let item = itemIdentifier(for: indexPath) switch item { - case .dnsSettings: + case .dnsSettings, .ipOverrides: return indexPath default: return nil @@ -353,7 +366,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< let sectionIdentifier = snapshot().sectionIdentifiers[section] switch sectionIdentifier { - case .dnsSettings: + case .dnsSettings, .ipOverrides: return 0 default: @@ -365,7 +378,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< let sectionIdentifier = snapshot().sectionIdentifiers[section] switch sectionIdentifier { - case .dnsSettings: + case .ipOverrides: return 10 default: return 0.5 @@ -402,6 +415,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< snapshot.appendSections(Section.allCases) snapshot.appendItems([.dnsSettings], toSection: .dnsSettings) + snapshot.appendItems([.ipOverrides], toSection: .ipOverrides) applySnapshot(snapshot, animated: animated, completion: completion) } @@ -420,14 +434,14 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< private func reload(item: Item) { if let indexPath = indexPath(for: item), let cell = tableView?.cellForRow(at: indexPath) { - preferencesCellFactory.configureCell(cell, item: item, indexPath: indexPath) + vpnSettingsCellFactory.configureCell(cell, item: item, indexPath: indexPath) } } private func configureWireguardPortsHeader(_ header: SettingsHeaderView) { let title = NSLocalizedString( "WIRE_GUARD_PORTS_HEADER_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "WireGuard ports", comment: "" ) @@ -469,7 +483,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< private func configureObfuscationHeader(_ header: SettingsHeaderView) { let title = NSLocalizedString( "OBFUSCATION_HEADER_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "WireGuard Obfuscation", comment: "" ) @@ -497,7 +511,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< private func configureObfuscationPortHeader(_ header: SettingsHeaderView) { let title = NSLocalizedString( "OBFUSCATION_PORT_HEADER_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "UDP-over-TCP Port", comment: "" ) @@ -526,7 +540,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< private func configureQuantumResistanceHeader(_ header: SettingsHeaderView) { let title = NSLocalizedString( "QUANTUM_RESISTANCE_HEADER_LABEL", - tableName: "Preferences", + tableName: "VPNSettings", value: "Quantum-resistant tunnel", comment: "" ) @@ -571,8 +585,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< } } -extension PreferencesDataSource: PreferencesCellEventHandler { - func showInfo(for button: PreferencesInfoButtonItem) { +extension VPNSettingsDataSource: VPNSettingsCellEventHandler { + func showInfo(for button: VPNSettingsInfoButtonItem) { delegate?.showInfo(for: button) } diff --git a/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift new file mode 100644 index 000000000000..70ecf368be10 --- /dev/null +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsDataSourceDelegate.swift @@ -0,0 +1,17 @@ +// +// VPNSettingsDataSourceDelegate.swift +// MullvadVPN +// +// Created by pronebird on 11/10/2021. +// Copyright © 2021 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +protocol VPNSettingsDataSourceDelegate: AnyObject { + func didChangeViewModel(_ viewModel: VPNSettingsViewModel) + func showInfo(for: VPNSettingsInfoButtonItem) + func showDNSSettings() + func showIPOverrides() + func didSelectWireGuardPort(_ port: UInt16?) +} diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift similarity index 80% rename from ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift rename to ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift index a5b5ce5521e3..c55a4c2eebb6 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesInfoButtonItem.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInfoButtonItem.swift @@ -1,12 +1,12 @@ // -// PreferencesInfoButtonItem.swift +// VPNSettingsInfoButtonItem.swift // MullvadVPN // // Created by Jon Petersson on 2023-11-10. // Copyright © 2023 Mullvad VPN AB. All rights reserved. // -enum PreferencesInfoButtonItem { +enum VPNSettingsInfoButtonItem { case contentBlockers case blockMalware case wireGuardPorts diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInteractor.swift similarity index 90% rename from ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift rename to ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInteractor.swift index 2c6e06b07c3f..e304a8e4b6b2 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesInteractor.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsInteractor.swift @@ -1,5 +1,5 @@ // -// PreferencesInteractor.swift +// VPNSettingsInteractor.swift // MullvadVPN // // Created by pronebird on 31/10/2022. @@ -10,8 +10,8 @@ import Foundation import MullvadREST import MullvadSettings -final class PreferencesInteractor { - private let tunnelManager: TunnelManager +final class VPNSettingsInteractor { + let tunnelManager: TunnelManager private var tunnelObserver: TunnelObserver? private let relayCacheTracker: RelayCacheTracker @@ -53,7 +53,7 @@ final class PreferencesInteractor { } } -extension PreferencesInteractor: RelayCacheTrackerObserver { +extension VPNSettingsInteractor: RelayCacheTrackerObserver { func relayCacheTracker(_ tracker: RelayCacheTracker, didUpdateCachedRelays cachedRelays: CachedRelays) { cachedRelaysDidChange?(cachedRelays) } diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift similarity index 83% rename from ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift rename to ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift index d7fe22a04055..3be523ef2af4 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewController.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewController.swift @@ -1,5 +1,5 @@ // -// PreferencesViewController.swift +// VPNSettingsViewController.swift // MullvadVPN // // Created by pronebird on 19/05/2021. @@ -9,16 +9,22 @@ import MullvadSettings import UIKit -class PreferencesViewController: UITableViewController, PreferencesDataSourceDelegate { - private let interactor: PreferencesInteractor - private var dataSource: PreferencesDataSource? +protocol VPNSettingsViewControllerDelegate: AnyObject { + func showIPOverrides() +} + +class VPNSettingsViewController: UITableViewController, VPNSettingsDataSourceDelegate { + private let interactor: VPNSettingsInteractor + private var dataSource: VPNSettingsDataSource? private let alertPresenter: AlertPresenter + weak var delegate: VPNSettingsViewControllerDelegate? + override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent } - init(interactor: PreferencesInteractor, alertPresenter: AlertPresenter) { + init(interactor: VPNSettingsInteractor, alertPresenter: AlertPresenter) { self.interactor = interactor self.alertPresenter = alertPresenter @@ -39,12 +45,12 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel tableView.estimatedSectionHeaderHeight = tableView.estimatedRowHeight tableView.allowsMultipleSelection = true - dataSource = PreferencesDataSource(tableView: tableView) + dataSource = VPNSettingsDataSource(tableView: tableView) dataSource?.delegate = self navigationItem.title = NSLocalizedString( "NAVIGATION_TITLE", - tableName: "Preferences", + tableName: "VPNSettings", value: "VPN settings", comment: "" ) @@ -67,13 +73,13 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel private func showInfo(with message: String) { let presentation = AlertPresentation( - id: "preferences-content-blockers-alert", + id: "vpn-settings-content-blockers-alert", icon: .info, message: message, buttons: [ AlertAction( title: NSLocalizedString( - "PREFERENCES_VPN_SETTINGS_OK_ACTION", + "VPN_SETTINGS_VPN_SETTINGS_OK_ACTION", tableName: "ContentBlockers", value: "Got it!", comment: "" @@ -98,9 +104,9 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel .joined(separator: ", ") } - // MARK: - PreferencesDataSourceDelegate + // MARK: - VPNSettingsDataSourceDelegate - func didChangeViewModel(_ viewModel: PreferencesViewModel) { + func didChangeViewModel(_ viewModel: VPNSettingsViewModel) { interactor.updateSettings( [ .obfuscation(WireGuardObfuscationSettings( @@ -113,7 +119,7 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel } // swiftlint:disable:next function_body_length - func showInfo(for item: PreferencesInfoButtonItem) { + func showInfo(for item: VPNSettingsInfoButtonItem) { var message = "" switch item { @@ -124,13 +130,11 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel message = String( format: NSLocalizedString( - "PREFERENCES_WIRE_GUARD_PORTS_GENERAL", + "VPN_SETTINGS_WIRE_GUARD_PORTS_GENERAL", tableName: "WireGuardPorts", value: """ The automatic setting will randomly choose from the valid port ranges shown below. - The custom port can be any value inside the valid ranges: - %@ """, comment: "" @@ -140,7 +144,7 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel case .wireGuardObfuscation: message = NSLocalizedString( - "PREFERENCES_WIRE_GUARD_OBFUSCATION_GENERAL", + "VPN_SETTINGS_WIRE_GUARD_OBFUSCATION_GENERAL", tableName: "WireGuardObfuscation", value: """ Obfuscation hides the WireGuard traffic inside another protocol. \ @@ -152,7 +156,7 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel case .wireGuardObfuscationPort: message = NSLocalizedString( - "PREFERENCES_WIRE_GUARD_OBFUSCATION_PORT_GENERAL", + "VPN_SETTINGS_WIRE_GUARD_OBFUSCATION_PORT_GENERAL", tableName: "WireGuardObfuscation", value: "Which TCP port the UDP-over-TCP obfuscation protocol should connect to on the VPN server.", comment: "" @@ -160,7 +164,7 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel case .quantumResistance: message = NSLocalizedString( - "PREFERENCES_QUANTUM_RESISTANCE_GENERAL", + "VPN_SETTINGS_QUANTUM_RESISTANCE_GENERAL", tableName: "QuantumResistance", value: """ This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers. @@ -183,6 +187,10 @@ class PreferencesViewController: UITableViewController, PreferencesDataSourceDel navigationController?.pushViewController(viewController, animated: true) } + func showIPOverrides() { + delegate?.showIPOverrides() + } + func didSelectWireGuardPort(_ port: UInt16?) { interactor.setPort(port) } diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewModel.swift similarity index 97% rename from ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift rename to ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewModel.swift index ed8d2b6313a2..36c9e080d329 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesViewModel.swift +++ b/ios/MullvadVPN/View controllers/VPNSettings/VPNSettingsViewModel.swift @@ -1,5 +1,5 @@ // -// PreferencesViewModel.swift +// VPNSettingsViewModel.swift // MullvadVPN // // Created by pronebird on 11/10/2021. @@ -42,7 +42,7 @@ enum CustomDNSPrecondition { return NSAttributedString( string: NSLocalizedString( "CUSTOM_DNS_NO_DNS_ENTRIES_EDITING_ON_FOOTNOTE", - tableName: "Preferences", + tableName: "VPNSettings", value: "To enable this setting, add at least one server.", comment: "Foot note displayed if there are no DNS entries and table view is in editing mode." ), @@ -52,7 +52,7 @@ enum CustomDNSPrecondition { return NSAttributedString( markdownString: NSLocalizedString( "CUSTOM_DNS_NO_DNS_ENTRIES_EDITING_OFF_FOOTNOTE", - tableName: "Preferences", + tableName: "VPNSettings", value: "Tap **Edit** to add at least one DNS server.", comment: "Foot note displayed if there are no DNS entries, but table view is not in editing mode." @@ -65,7 +65,7 @@ enum CustomDNSPrecondition { return NSAttributedString( string: NSLocalizedString( "CUSTOM_DNS_DISABLE_CONTENT_BLOCKERS_FOOTNOTE", - tableName: "Preferences", + tableName: "VPNSettings", value: "Disable all content blockers (under VPN settings) to activate this setting.", comment: """ Foot note displayed when custom DNS cannot be enabled, because content blockers should be \ @@ -83,7 +83,7 @@ struct DNSServerEntry: Equatable, Hashable { var address: String } -struct PreferencesViewModel: Equatable { +struct VPNSettingsViewModel: Equatable { private(set) var blockAdvertising: Bool private(set) var blockTracking: Bool private(set) var blockMalware: Bool @@ -204,7 +204,7 @@ struct PreferencesViewModel: Equatable { } /// Produce merged view model keeping entry `identifier` for matching DNS entries. - func merged(_ other: PreferencesViewModel) -> PreferencesViewModel { + func merged(_ other: VPNSettingsViewModel) -> VPNSettingsViewModel { var mergedViewModel = other mergedViewModel.customDNSDomains = merge(customDNSDomains, with: other.customDNSDomains) diff --git a/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift b/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift index 4a16bc3e2d54..bae6c14b748b 100644 --- a/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift +++ b/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift @@ -103,9 +103,9 @@ class MullvadVPNScreenshots: XCTestCase { // Open Settings app.buttons[AccessibilityIdentifier.settingsButton.rawValue].tap() - // Tap on preferences cell - _ = app.tables.cells[AccessibilityIdentifier.preferencesCell.rawValue].waitForExistence(timeout: 2) - app.tables.cells[AccessibilityIdentifier.preferencesCell.rawValue].tap() + // Tap on VPN settings cell + _ = app.tables.cells[AccessibilityIdentifier.vpnSettingsCell.rawValue].waitForExistence(timeout: 2) + app.tables.cells[AccessibilityIdentifier.vpnSettingsCell.rawValue].tap() app.tables.element .cells @@ -114,7 +114,7 @@ class MullvadVPNScreenshots: XCTestCase { .matching(NSPredicate(format: "value = %@", "0")) .allElementsBoundByAccessibilityElement .forEach { $0.tap() } - snapshot("Preferences") + snapshot("VPN Settings") // Tap back button app.navigationBars.buttons.firstMatch.tap() diff --git a/ios/MullvadVPNUITests/Pages/SettingsPage.swift b/ios/MullvadVPNUITests/Pages/SettingsPage.swift index 63b3227d2965..43ad3dedd5d2 100644 --- a/ios/MullvadVPNUITests/Pages/SettingsPage.swift +++ b/ios/MullvadVPNUITests/Pages/SettingsPage.swift @@ -19,7 +19,7 @@ class SettingsPage: Page { @discardableResult func tapVPNSettingsCell() -> Self { app.tables[AccessibilityIdentifier.settingsTableView] - .cells[AccessibilityIdentifier.preferencesCell] + .cells[AccessibilityIdentifier.vpnSettingsCell] .tap() return self