From 31e7c411c1be428e72a52d32da29d0118c7f7d41 Mon Sep 17 00:00:00 2001 From: Jon Petersson Date: Tue, 13 Aug 2024 13:00:08 +0200 Subject: [PATCH] List only DAITA entry locations if multihop and DAITA are enabled --- .../NoRelaysSatisfyingConstraintsError.swift | 4 ++ ios/MullvadVPN.xcodeproj/project.pbxproj | 6 +++ .../Coordinators/LocationCoordinator.swift | 41 +++++++++++++++---- .../SimulatorTunnelProviderManager.swift | 4 +- .../RelayFilter/RelayFilterChipView.swift | 16 +++++--- .../RelayFilter/RelayFilterView.swift | 22 +++++++++- .../AllLocationDataSource.swift | 6 +-- .../LocationCellViewModel.swift | 18 ++++---- .../SelectLocation/LocationDataSource.swift | 14 +------ .../SelectLocation/LocationRelays.swift | 14 +++++++ .../LocationViewController.swift | 28 ++++++------- .../LocationViewControllerWrapper.swift | 29 +++++++++++-- .../Relay/RelaySelectorTests.swift | 2 +- .../AllLocationsDataSourceTests.swift | 4 +- .../CustomListsDataSourceTests.swift | 4 +- 15 files changed, 148 insertions(+), 64 deletions(-) create mode 100644 ios/MullvadVPN/View controllers/SelectLocation/LocationRelays.swift diff --git a/ios/MullvadREST/Relay/NoRelaysSatisfyingConstraintsError.swift b/ios/MullvadREST/Relay/NoRelaysSatisfyingConstraintsError.swift index bfed08a41044..3635f9eeb926 100644 --- a/ios/MullvadREST/Relay/NoRelaysSatisfyingConstraintsError.swift +++ b/ios/MullvadREST/Relay/NoRelaysSatisfyingConstraintsError.swift @@ -43,4 +43,8 @@ public struct NoRelaysSatisfyingConstraintsError: LocalizedError { public init(_ reason: NoRelaysSatisfyingConstraintsReason) { self.reason = reason } + + public init(_ reason: NoRelaysSatisfyingConstraintsReason) { + self.reason = reason + } } diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 28b7b8d2f982..6419df3898f6 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -489,6 +489,8 @@ 7A516C3C2B712F0B00BBD33D /* IPOverrideWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */; }; 7A52F96A2C1735AE00B133B9 /* RelaySelectorStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FE25EF2AA77664003D1918 /* RelaySelectorStub.swift */; }; 7A52F96C2C17450C00B133B9 /* RelaySelectorWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A52F96B2C17450C00B133B9 /* RelaySelectorWrapperTests.swift */; }; + 7A5468AC2C6A55B100590086 /* LocationRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A5468AB2C6A55B100590086 /* LocationRelays.swift */; }; + 7A5468AD2C6B5E4B00590086 /* LocationRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A5468AB2C6A55B100590086 /* LocationRelays.swift */; }; 7A5869952B32E9C700640D27 /* LinkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A5869942B32E9C700640D27 /* LinkButton.swift */; }; 7A5869972B32EA4500640D27 /* AppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A5869962B32EA4500640D27 /* AppButton.swift */; }; 7A58699B2B482FE200640D27 /* UITableViewCell+Disable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A58699A2B482FE200640D27 /* UITableViewCell+Disable.swift */; }; @@ -1806,6 +1808,7 @@ 7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideWrapper.swift; sourceTree = ""; }; 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideWrapperTests.swift; sourceTree = ""; }; 7A52F96B2C17450C00B133B9 /* RelaySelectorWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorWrapperTests.swift; sourceTree = ""; }; + 7A5468AB2C6A55B100590086 /* LocationRelays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRelays.swift; sourceTree = ""; }; 7A5869942B32E9C700640D27 /* LinkButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkButton.swift; sourceTree = ""; }; 7A5869962B32EA4500640D27 /* AppButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppButton.swift; sourceTree = ""; }; 7A58699A2B482FE200640D27 /* UITableViewCell+Disable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewCell+Disable.swift"; sourceTree = ""; }; @@ -2756,6 +2759,7 @@ F050AE5D2B739A73003F4EDB /* LocationDataSourceProtocol.swift */, 7A6652B62BB44B120042D848 /* LocationDiffableDataSourceProtocol.swift */, 7A6389F72B864CDF008E77E1 /* LocationNode.swift */, + 7A5468AB2C6A55B100590086 /* LocationRelays.swift */, F050AE512B70DFC0003F4EDB /* LocationSection.swift */, F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */, 5888AD86227B17950051EB06 /* LocationViewController.swift */, @@ -5251,6 +5255,7 @@ A9A5FA422ACB05D90083449F /* DeviceStateAccessorProtocol.swift in Sources */, 7A5869C32B5820CE00640D27 /* IPOverrideRepositoryTests.swift in Sources */, A9A5FA392ACB05910083449F /* UIColor+Palette.swift in Sources */, + 7A5468AD2C6B5E4B00590086 /* LocationRelays.swift in Sources */, A9A5FA3A2ACB05910083449F /* UIEdgeInsets+Extensions.swift in Sources */, A9A5FA3B2ACB05910083449F /* UIMetrics.swift in Sources */, 58B07C182AEFDD6C00A09625 /* StoreTransactionLog.swift in Sources */, @@ -5542,6 +5547,7 @@ 7A9CCCC42A96302800DD6A34 /* TunnelCoordinator.swift in Sources */, 5827B0A42B0F38FD00CCBBA1 /* EditAccessMethodInteractorProtocol.swift in Sources */, 586C0D852B03D31E00E7CDD7 /* SocksSectionHandler.swift in Sources */, + 7A5468AC2C6A55B100590086 /* LocationRelays.swift in Sources */, 58BFA5CC22A7CE1F00A6173D /* ApplicationConfiguration.swift in Sources */, 5891BF5125E66B1E006D6FB0 /* UIBarButtonItem+KeyboardNavigation.swift in Sources */, 58E511E628DDDEAC00B0BCDE /* CodingErrors+CustomErrorDescription.swift in Sources */, diff --git a/ios/MullvadVPN/Coordinators/LocationCoordinator.swift b/ios/MullvadVPN/Coordinators/LocationCoordinator.swift index ad58896f517d..222a20db1b79 100644 --- a/ios/MullvadVPN/Coordinators/LocationCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/LocationCoordinator.swift @@ -16,7 +16,7 @@ class LocationCoordinator: Coordinator, Presentable, Presenting { private let tunnelManager: TunnelManager private let relayCacheTracker: RelayCacheTracker private let customListRepository: CustomListRepositoryProtocol - private var cachedRelays: CachedRelays? + private var cachedRelays: LocationRelays? let navigationController: UINavigationController @@ -54,10 +54,16 @@ class LocationCoordinator: Coordinator, Presentable, Presenting { } func start() { + let startContext: LocationViewControllerWrapper.MultihopContext = + if case .noRelaysSatisfyingDaitaConstraints = tunnelManager.tunnelStatus.observedState + .blockedState?.reason { .entry } else { .exit } + let locationViewControllerWrapper = LocationViewControllerWrapper( customListRepository: customListRepository, constraints: tunnelManager.settings.relayConstraints, - multihopEnabled: tunnelManager.settings.tunnelMultihopState.isEnabled + multihopEnabled: tunnelManager.settings.tunnelMultihopState.isEnabled, + daitaEnabled: tunnelManager.settings.daita.state.isEnabled, + startContext: startContext ) locationViewControllerWrapper.delegate = self @@ -69,8 +75,13 @@ class LocationCoordinator: Coordinator, Presentable, Presenting { relayCacheTracker.addObserver(self) if let cachedRelays = try? relayCacheTracker.getCachedRelays() { - self.cachedRelays = cachedRelays - locationViewControllerWrapper.setCachedRelays(cachedRelays, filter: relayFilter) + let locationRelays = LocationRelays( + relays: cachedRelays.relays.wireguard.relays, + locations: cachedRelays.relays.locations + ) + self.cachedRelays = locationRelays + + locationViewControllerWrapper.setCachedRelays(locationRelays, filter: relayFilter) } navigationController.pushViewController(locationViewControllerWrapper, animated: false) @@ -87,8 +98,14 @@ class LocationCoordinator: Coordinator, Presentable, Presenting { ) relayFilterCoordinator.didFinish = { [weak self] coordinator, filter in - if let cachedRelays = self?.cachedRelays, let filter { - self?.locationViewControllerWrapper?.setCachedRelays(cachedRelays, filter: filter) + guard let self else { return } + + if var cachedRelays, let filter { + cachedRelays.relays = cachedRelays.relays.filter { relay in + RelaySelector.relayMatchesFilter(relay, filter: filter) + } + + locationViewControllerWrapper?.setCachedRelays(cachedRelays, filter: filter) } coordinator.dismiss(animated: true) @@ -148,9 +165,13 @@ extension LocationCoordinator: RelayCacheTrackerObserver { _ tracker: RelayCacheTracker, didUpdateCachedRelays cachedRelays: CachedRelays ) { - self.cachedRelays = cachedRelays + let locationRelays = LocationRelays( + relays: cachedRelays.relays.wireguard.relays, + locations: cachedRelays.relays.locations + ) + self.cachedRelays = locationRelays - locationViewControllerWrapper?.setCachedRelays(cachedRelays, filter: relayFilter) + locationViewControllerWrapper?.setCachedRelays(locationRelays, filter: relayFilter) } } @@ -178,6 +199,10 @@ extension LocationCoordinator: LocationViewControllerWrapperDelegate { relayConstraints.filter = .only(filter) tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) + + if let cachedRelays { + locationViewControllerWrapper?.setCachedRelays(cachedRelays, filter: filter) + } } func navigateToFilter() { diff --git a/ios/MullvadVPN/SimulatorTunnelProvider/SimulatorTunnelProviderManager.swift b/ios/MullvadVPN/SimulatorTunnelProvider/SimulatorTunnelProviderManager.swift index c8bc1fe7fe93..4a075c0fbde4 100644 --- a/ios/MullvadVPN/SimulatorTunnelProvider/SimulatorTunnelProviderManager.swift +++ b/ios/MullvadVPN/SimulatorTunnelProvider/SimulatorTunnelProviderManager.swift @@ -171,8 +171,8 @@ final class SimulatorTunnelProviderManager: NSObject, VPNTunnelProviderManagerPr } override func isEqual(_ object: Any?) -> Bool { - guard let other = object as? Self else { return false } - return self.identifier == other.identifier + guard let multihopOther = object as? Self else { return false } + return self.identifier == multihopOther.identifier } } diff --git a/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterChipView.swift b/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterChipView.swift index 67c73b0339b9..3b6191e1aa12 100644 --- a/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterChipView.swift +++ b/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterChipView.swift @@ -18,6 +18,16 @@ class RelayFilterChipView: UIView { return label }() + let closeButton: IncreasedHitButton = { + let button = IncreasedHitButton() + button.setImage( + UIImage(resource: .iconCloseSml).withTintColor(.white.withAlphaComponent(0.6)), + for: .normal + ) + button.accessibilityIdentifier = .relayFilterChipCloseButton + return button + }() + var didTapButton: (() -> Void)? init() { @@ -25,12 +35,6 @@ class RelayFilterChipView: UIView { self.accessibilityIdentifier = .relayFilterChipView - let closeButton = IncreasedHitButton() - closeButton.setImage( - UIImage(named: "IconCloseSml")?.withTintColor(.white.withAlphaComponent(0.6)), - for: .normal - ) - closeButton.accessibilityIdentifier = .relayFilterChipCloseButton closeButton.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside) let container = UIStackView(arrangedSubviews: [titleLabel, closeButton]) diff --git a/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift b/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift index 60a752032206..e12ce5cf3708 100644 --- a/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift +++ b/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift @@ -34,6 +34,7 @@ class RelayFilterView: UIView { private let ownershipView = RelayFilterChipView() private let providersView = RelayFilterChipView() + private let daitaView = RelayFilterChipView() private var filter: RelayFilter? var didUpdateFilter: ((RelayFilter) -> Void)? @@ -71,7 +72,16 @@ class RelayFilterView: UIView { } } + func setDaita(_ enabled: Bool) { + daitaView.isHidden = !enabled + } + private func setUpViews() { + daitaView.setTitle(localizedDaitaText()) + daitaView.isHidden = true + daitaView.closeButton.isHidden = true + + ownershipView.isHidden = true ownershipView.didTapButton = { [weak self] in guard var filter = self?.filter else { return } @@ -79,6 +89,7 @@ class RelayFilterView: UIView { self?.didUpdateFilter?(filter) } + providersView.isHidden = true providersView.didTapButton = { [weak self] in guard var filter = self?.filter else { return } @@ -87,7 +98,7 @@ class RelayFilterView: UIView { } // Add a dummy view at the end to push content to the left. - let filterContainer = UIStackView(arrangedSubviews: [ownershipView, providersView, UIView()]) + let filterContainer = UIStackView(arrangedSubviews: [daitaView, ownershipView, providersView, UIView()]) filterContainer.spacing = UIMetrics.FilterView.interChipViewSpacing let contentContainer = UIStackView(arrangedSubviews: [titleLabel, filterContainer]) @@ -99,6 +110,15 @@ class RelayFilterView: UIView { } } + private func localizedDaitaText() -> String { + return NSLocalizedString( + "RELAY_FILTER_APPLIED_DAITA", + tableName: "RelayFilter", + value: "Setting: DAITA", + comment: "" + ) + } + private func localizedOwnershipText(for string: String) -> String { return NSLocalizedString( "RELAY_FILTER_APPLIED_OWNERSHIP", diff --git a/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift index 578deeddd2ca..bc15ae3976c8 100644 --- a/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift +++ b/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift @@ -20,13 +20,13 @@ class AllLocationDataSource: LocationDataSourceProtocol { /// Constructs a collection of node trees from relays fetched from the API. /// ``RelayLocation.city`` is of special import since we use it to get country /// and city names. - func reload(_ response: REST.ServerRelaysResponse, relays: [REST.ServerRelay]) { + func reload(_ relays: LocationRelays) { let rootNode = RootLocationNode() - for relay in relays { + for relay in relays.relays { guard case let .city(countryCode, cityCode) = RelayLocation(dashSeparatedString: relay.location), - let serverLocation = response.locations[relay.location] + let serverLocation = relays.locations[relay.location] else { continue } let relayLocation = RelayLocation.hostname(countryCode, cityCode, relay.hostname) diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift index ce578d13bad6..f26a0d2da492 100644 --- a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift +++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift @@ -62,17 +62,17 @@ extension [LocationCellViewModel] { } extension LocationCellViewModel { - /* Exclusion of other locations in the same node tree as the currently excluded location + /* Exclusion of other locations in the same node tree (as the currently excluded location) happens when there are no more hosts in that tree that can be selected. We check this by doing the following, in order: - 1. Count host names in the tree. More than one means that there are other locations than + 1. Count hostnames in the tree. More than one means that there are other locations than the excluded one for the relay selector to choose from. No exlusion. - 2. Count host names in the excluded node. More than one means that there are multiple - locations for the relay selector to choose from. No exlusion. + 2. Count hostnames in the excluded node. More than one means that there are multiple + locations for the relay selector to choose from. No exclusion. - 3. Check existance of a location in the tree that match the currently excluded location. + 3. Check existance of a location in the tree that matches the currently excluded location. No match means no exclusion. */ func shouldExcludeLocation(_ excludedLocation: LocationCellViewModel?) -> Bool { @@ -86,8 +86,8 @@ extension LocationCellViewModel { if case .hostname = location { true } else { false } }.count - // If the there are more than one selectable relay in the current node we don't need - // show this in the location tree and can return early. + // If the there's more than one selectable relay in the current node we don't need + // to show this in the location tree and can return early. guard hostCount == 1 else { return false } let proxyExcludedNode = RootLocationNode(children: [excludedLocation.node]) @@ -96,8 +96,8 @@ extension LocationCellViewModel { if case .hostname = location { true } else { false } }.count - // If the there are more than one selectable relay in the excluded node we don't need - // show this in the location tree and can return early. + // If the there's more than one selectable relay in the excluded node we don't need + // to show this in the location tree and can return early. guard excludedHostCount == 1 else { return false } var containsExcludedLocation = false diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift index 4d68eccbb5c6..9fe7490d5f4e 100644 --- a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift +++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift @@ -54,18 +54,14 @@ final class LocationDataSource: defaultRowAnimation = .fade } - func setRelays(_ response: REST.ServerRelaysResponse, selectedRelays: RelaySelection, filter: RelayFilter) { + func setRelays(_ cachedRelays: LocationRelays, selectedRelays: RelaySelection) { let allLocationsDataSource = dataSources.first(where: { $0 is AllLocationDataSource }) as? AllLocationDataSource let customListsDataSource = dataSources.first(where: { $0 is CustomListsDataSource }) as? CustomListsDataSource - let relays = response.wireguard.relays.filter { relay in - RelaySelector.relayMatchesFilter(relay, filter: filter) - } - - allLocationsDataSource?.reload(response, relays: relays) + allLocationsDataSource?.reload(cachedRelays) customListsDataSource?.reload(allLocationNodes: allLocationsDataSource?.nodes ?? []) setSelectedRelays(selectedRelays) @@ -237,12 +233,6 @@ final class LocationDataSource: ) } - private func nodeMatchesExcludedLocation(_ node: LocationNode) -> Bool { - // Compare nodes on name rather than whole node in order to match all items in both .customLists - // and .allLocations. - node.name == excludedLocation?.node.name - } - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = super.tableView(tableView, cellForRowAt: indexPath) guard let cell = cell as? LocationCell, let item = itemIdentifier(for: indexPath) else { diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationRelays.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationRelays.swift new file mode 100644 index 000000000000..a3bc127593e8 --- /dev/null +++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationRelays.swift @@ -0,0 +1,14 @@ +// +// LocationRelays.swift +// MullvadVPN +// +// Created by Jon Petersson on 2024-08-12. +// Copyright © 2024 Mullvad VPN AB. All rights reserved. +// + +import MullvadREST + +struct LocationRelays { + var relays: [REST.ServerRelay] + var locations: [String: REST.ServerLocation] +} diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift index 4cdfc7144696..787f4e06c987 100644 --- a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift +++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift @@ -23,9 +23,10 @@ final class LocationViewController: UIViewController { private let topContentView = UIStackView() private let filterView = RelayFilterView() private var dataSource: LocationDataSource? - private var cachedRelays: CachedRelays? + private var cachedRelays: LocationRelays? private var filter = RelayFilter() private var selectedRelays: RelaySelection + private var daitaEnabled = false weak var delegate: LocationViewControllerDelegate? var customListRepository: CustomListRepositoryProtocol @@ -34,7 +35,7 @@ final class LocationViewController: UIViewController { } var filterViewShouldBeHidden: Bool { - return (filter.ownership == .any) && (filter.providers == .any) + !daitaEnabled && (filter.ownership == .any) && (filter.providers == .any) } init(customListRepository: CustomListRepositoryProtocol, selectedRelays: RelaySelection) { @@ -80,7 +81,12 @@ final class LocationViewController: UIViewController { // MARK: - Public - func setCachedRelays(_ cachedRelays: CachedRelays, filter: RelayFilter) { + func setDaita(_ enabled: Bool) { + daitaEnabled = enabled + filterView.setDaita(enabled) + } + + func setCachedRelays(_ cachedRelays: LocationRelays, filter: RelayFilter) { self.cachedRelays = cachedRelays self.filter = filter @@ -91,7 +97,7 @@ final class LocationViewController: UIViewController { filterView.setFilter(filter) } - dataSource?.setRelays(cachedRelays.relays, selectedRelays: selectedRelays, filter: filter) + dataSource?.setRelays(cachedRelays, selectedRelays: selectedRelays) } func refreshCustomLists() { @@ -121,13 +127,13 @@ final class LocationViewController: UIViewController { if let cachedRelays { let allLocationDataSource = AllLocationDataSource() - allLocationDataSource.reload(cachedRelays.relays, relays: cachedRelays.relays.wireguard.relays) + allLocationDataSource.reload(cachedRelays) delegate?.navigateToCustomLists(nodes: allLocationDataSource.nodes) } } if let cachedRelays { - dataSource?.setRelays(cachedRelays.relays, selectedRelays: selectedRelays, filter: filter) + dataSource?.setRelays(cachedRelays, selectedRelays: selectedRelays) } } @@ -148,16 +154,10 @@ final class LocationViewController: UIViewController { topContentView.addArrangedSubview(searchBar) filterView.isHidden = filterViewShouldBeHidden + filterView.setDaita(daitaEnabled) filterView.didUpdateFilter = { [weak self] in - guard let self else { return } - - filter = $0 - delegate?.didUpdateFilter(filter: $0) - - if let cachedRelays { - setCachedRelays(cachedRelays, filter: filter) - } + self?.delegate?.didUpdateFilter(filter: $0) } setUpSearchBar() diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift index c86ea173c515..d8275320255e 100644 --- a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift +++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift @@ -52,15 +52,20 @@ final class LocationViewControllerWrapper: UIViewController { private var selectedExit: UserSelectedRelays? private let multihopEnabled: Bool private var multihopContext: MultihopContext = .exit + private let daitaEnabled: Bool weak var delegate: LocationViewControllerWrapperDelegate? init( customListRepository: CustomListRepositoryProtocol, constraints: RelayConstraints, - multihopEnabled: Bool + multihopEnabled: Bool, + daitaEnabled: Bool, + startContext: MultihopContext ) { self.multihopEnabled = multihopEnabled + self.daitaEnabled = daitaEnabled + multihopContext = startContext selectedEntry = constraints.entryLocations.value selectedExit = constraints.exitLocations.value @@ -94,15 +99,31 @@ final class LocationViewControllerWrapper: UIViewController { view.accessibilityIdentifier = .selectLocationViewWrapper view.backgroundColor = .secondaryColor + if multihopEnabled { + entryLocationViewController.setDaita(daitaEnabled) + } else { + exitLocationViewController.setDaita(daitaEnabled) + } + setUpNavigation() setUpSegmentedControl() addSubviews() swapViewController() } - func setCachedRelays(_ cachedRelays: CachedRelays, filter: RelayFilter) { - updateViewControllers { - $0.setCachedRelays(cachedRelays, filter: filter) + func setCachedRelays(_ cachedRelays: LocationRelays, filter: RelayFilter) { + var daitaFilteredRelays = cachedRelays + if daitaEnabled { + daitaFilteredRelays.relays = cachedRelays.relays.filter { relay in + relay.daita == true + } + } + + if multihopEnabled { + entryLocationViewController.setCachedRelays(daitaFilteredRelays, filter: filter) + exitLocationViewController.setCachedRelays(cachedRelays, filter: filter) + } else { + exitLocationViewController.setCachedRelays(daitaFilteredRelays, filter: filter) } } diff --git a/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorTests.swift b/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorTests.swift index 2622d883fdef..5b2a775a4f01 100644 --- a/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorTests.swift +++ b/ios/MullvadVPNTests/MullvadREST/Relay/RelaySelectorTests.swift @@ -91,7 +91,7 @@ class RelaySelectorTests: XCTestCase { ) } - func testNoMatchingRelayConstraintError() throws { + func testNoMatchingRelayConstraint() throws { let constraints = RelayConstraints( exitLocations: .only(UserSelectedRelays(locations: [.country("-")])) ) diff --git a/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/AllLocationsDataSourceTests.swift b/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/AllLocationsDataSourceTests.swift index 5149fa1261ad..d1e0ca4c9351 100644 --- a/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/AllLocationsDataSourceTests.swift +++ b/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/AllLocationsDataSourceTests.swift @@ -58,9 +58,9 @@ class AllLocationsDataSourceTests: XCTestCase { extension AllLocationsDataSourceTests { private func setUpDataSource() { let response = ServerRelaysResponseStubs.sampleRelays - let relays = response.wireguard.relays + let relays = LocationRelays(relays: response.wireguard.relays, locations: response.locations) dataSource = AllLocationDataSource() - dataSource.reload(response, relays: relays) + dataSource.reload(relays) } } diff --git a/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/CustomListsDataSourceTests.swift b/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/CustomListsDataSourceTests.swift index 15069391782b..461eff0d7241 100644 --- a/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/CustomListsDataSourceTests.swift +++ b/ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/CustomListsDataSourceTests.swift @@ -80,10 +80,10 @@ extension CustomListsDataSourceTests { private func createAllLocationNodes() { let response = ServerRelaysResponseStubs.sampleRelays - let relays = response.wireguard.relays + let relays = LocationRelays(relays: response.wireguard.relays, locations: response.locations) let dataSource = AllLocationDataSource() - dataSource.reload(response, relays: relays) + dataSource.reload(relays) allLocationNodes = dataSource.nodes }