summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJon Petersson <jon.petersson@kvadrat.se>2024-04-24 09:14:19 +0200
committerJon Petersson <jon.petersson@kvadrat.se>2024-05-13 09:26:04 +0200
commit2ad27f50a678ca06da7cb55c637890bd25692b34 (patch)
treeab4d8804705d1d219b625245b83bae34ac801f6a
parentc828a96a25b61a07fa2e72565fa3dd709b79aa76 (diff)
downloadmullvadvpn-2ad27f50a678ca06da7cb55c637890bd25692b34.tar.xz
mullvadvpn-2ad27f50a678ca06da7cb55c637890bd25692b34.zip
Add a new container view to wrap the whole location selection
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/Classes/AccessbilityIdentifier.swift1
-rw-r--r--ios/MullvadVPN/Coordinators/LocationCoordinator.swift113
-rw-r--r--ios/MullvadVPN/UI appearance/UIColor+Palette.swift5
-rw-r--r--ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift4
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift57
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift156
7 files changed, 229 insertions, 111 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 27fc3db0b0..b01bed21d7 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -587,6 +587,7 @@
7AA513862BC91C6B00D081A4 /* LogRotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */; };
7AB2B6702BA1EB8C00B03E3B /* ListCustomListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */; };
7AB2B6712BA1EB8C00B03E3B /* ListCustomListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB2B66F2BA1EB8C00B03E3B /* ListCustomListCoordinator.swift */; };
+ 7AB3BEB52BD7A6CB00E34384 /* LocationViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB3BEB42BD7A6CB00E34384 /* LocationViewControllerWrapper.swift */; };
7AB4CCB92B69097E006037F5 /* IPOverrideTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB4CCB82B69097E006037F5 /* IPOverrideTests.swift */; };
7AB4CCBB2B691BBB006037F5 /* IPOverrideInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB4CCBA2B691BBB006037F5 /* IPOverrideInteractor.swift */; };
7ABCA5B32A9349F20044A708 /* Routing.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A88DCCE2A8FABBE00D2FF0E /* Routing.framework */; };
@@ -1855,6 +1856,7 @@
7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRotationTests.swift; sourceTree = "<group>"; };
7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCustomListViewController.swift; sourceTree = "<group>"; };
7AB2B66F2BA1EB8C00B03E3B /* ListCustomListCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCustomListCoordinator.swift; sourceTree = "<group>"; };
+ 7AB3BEB42BD7A6CB00E34384 /* LocationViewControllerWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationViewControllerWrapper.swift; sourceTree = "<group>"; };
7AB4CCB82B69097E006037F5 /* IPOverrideTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideTests.swift; sourceTree = "<group>"; };
7AB4CCBA2B691BBB006037F5 /* IPOverrideInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideInteractor.swift; sourceTree = "<group>"; };
7ABE318C2A1CDD4500DF4963 /* UIFont+Weight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Weight.swift"; sourceTree = "<group>"; };
@@ -2646,6 +2648,7 @@
F050AE512B70DFC0003F4EDB /* LocationSection.swift */,
F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */,
5888AD86227B17950051EB06 /* LocationViewController.swift */,
+ 7AB3BEB42BD7A6CB00E34384 /* LocationViewControllerWrapper.swift */,
);
path = SelectLocation;
sourceTree = "<group>";
@@ -5582,6 +5585,7 @@
063687BA28EB234F00BE7161 /* PacketTunnelTransport.swift in Sources */,
A9C342C12ACC37E30045F00E /* TunnelStatusBlockObserver.swift in Sources */,
587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */,
+ 7AB3BEB52BD7A6CB00E34384 /* LocationViewControllerWrapper.swift in Sources */,
F09D04BD2AEBB7C5003D4F89 /* OutgoingConnectionService.swift in Sources */,
58FF9FF42B07C61B00E4C97D /* AccessMethodValidationError.swift in Sources */,
5896AE84246D5889005B36CB /* CustomDateComponentsFormatting.swift in Sources */,
diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
index 9f738fabcc..9fab241c13 100644
--- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
+++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
@@ -102,6 +102,7 @@ public enum AccessibilityIdentifier: String {
case outOfTimeView
case termsOfServiceView
case selectLocationView
+ case selectLocationViewWrapper
case selectLocationTableView
case settingsTableView
case vpnSettingsTableView
diff --git a/ios/MullvadVPN/Coordinators/LocationCoordinator.swift b/ios/MullvadVPN/Coordinators/LocationCoordinator.swift
index 3ccfbd1c70..58e828ef12 100644
--- a/ios/MullvadVPN/Coordinators/LocationCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/LocationCoordinator.swift
@@ -24,10 +24,10 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
navigationController
}
- var locationViewController: LocationViewController? {
+ var locationViewControllerWrapper: LocationViewControllerWrapper? {
return navigationController.viewControllers.first {
- $0 is LocationViewController
- } as? LocationViewController
+ $0 is LocationViewControllerWrapper
+ } as? LocationViewControllerWrapper
}
var relayFilter: RelayFilter {
@@ -54,43 +54,14 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
}
func start() {
- let locationViewController = LocationViewController(customListRepository: customListRepository)
- locationViewController.delegate = self
-
- locationViewController.didSelectRelays = { [weak self] locations in
- guard let self else { return }
-
- var relayConstraints = tunnelManager.settings.relayConstraints
- relayConstraints.locations = .only(locations)
-
- tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) {
- self.tunnelManager.startTunnel()
- }
-
- didFinish?(self)
- }
-
- locationViewController.navigateToFilter = { [weak self] in
- guard let self else { return }
-
- let coordinator = makeRelayFilterCoordinator(forModalPresentation: true)
- coordinator.start()
-
- presentChild(coordinator, animated: true)
- }
-
- locationViewController.didUpdateFilter = { [weak self] filter in
- guard let self else { return }
-
- var relayConstraints = tunnelManager.settings.relayConstraints
- relayConstraints.filter = .only(filter)
-
- tunnelManager.updateSettings([.relayConstraints(relayConstraints)])
- }
+ let locationViewControllerWrapper = LocationViewControllerWrapper(
+ customListRepository: customListRepository,
+ selectedRelays: tunnelManager.settings.relayConstraints.locations.value
+ )
+ locationViewControllerWrapper.delegate = self
- locationViewController.didFinish = { [weak self] in
+ locationViewControllerWrapper.didFinish = { [weak self] in
guard let self else { return }
-
didFinish?(self)
}
@@ -98,12 +69,10 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
if let cachedRelays = try? relayCacheTracker.getCachedRelays() {
self.cachedRelays = cachedRelays
- locationViewController.setCachedRelays(cachedRelays, filter: relayFilter)
+ locationViewControllerWrapper.setCachedRelays(cachedRelays, filter: relayFilter)
}
- locationViewController.relayLocations = tunnelManager.settings.relayConstraints.locations.value
-
- navigationController.pushViewController(locationViewController, animated: false)
+ navigationController.pushViewController(locationViewControllerWrapper, animated: false)
}
private func makeRelayFilterCoordinator(forModalPresentation isModalPresentation: Bool)
@@ -118,7 +87,7 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
relayFilterCoordinator.didFinish = { [weak self] coordinator, filter in
if let cachedRelays = self?.cachedRelays, let filter {
- self?.locationViewController?.setCachedRelays(cachedRelays, filter: filter)
+ self?.locationViewControllerWrapper?.setCachedRelays(cachedRelays, filter: filter)
}
coordinator.dismiss(animated: true)
@@ -138,7 +107,7 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
coordinator.didFinish = { [weak self] addCustomListCoordinator in
addCustomListCoordinator.dismiss(animated: true)
- self?.locationViewController?.refreshCustomLists()
+ self?.locationViewControllerWrapper?.refreshCustomLists()
}
coordinator.start()
@@ -155,7 +124,7 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
coordinator.didFinish = { [weak self] listCustomListCoordinator in
listCustomListCoordinator.dismiss(animated: true)
- self?.locationViewController?.refreshCustomLists()
+ self?.locationViewControllerWrapper?.refreshCustomLists()
}
coordinator.start()
@@ -169,7 +138,7 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
// See showEditCustomLists() above.
extension LocationCoordinator: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
- locationViewController?.refreshCustomLists()
+ locationViewControllerWrapper?.refreshCustomLists()
}
}
@@ -180,32 +149,50 @@ extension LocationCoordinator: RelayCacheTrackerObserver {
) {
self.cachedRelays = cachedRelays
- locationViewController?.setCachedRelays(cachedRelays, filter: relayFilter)
+ locationViewControllerWrapper?.setCachedRelays(cachedRelays, filter: relayFilter)
}
}
-extension LocationCoordinator: LocationViewControllerDelegate {
- func didRequestRouteToCustomLists(_ controller: LocationViewController, nodes: [LocationNode]) {
+extension LocationCoordinator: LocationViewControllerWrapperDelegate {
+ func didSelectRelays(relays: UserSelectedRelays) {
+ var relayConstraints = tunnelManager.settings.relayConstraints
+ relayConstraints.locations = .only(relays)
+
+ tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) {
+ self.tunnelManager.startTunnel()
+ }
+
+ didFinish?(self)
+ }
+
+ func didUpdateFilter(filter: RelayFilter) {
+ var relayConstraints = tunnelManager.settings.relayConstraints
+ relayConstraints.filter = .only(filter)
+
+ tunnelManager.updateSettings([.relayConstraints(relayConstraints)])
+ }
+
+ func navigateToFilter() {
+ let coordinator = makeRelayFilterCoordinator(forModalPresentation: true)
+ coordinator.start()
+
+ presentChild(coordinator, animated: true)
+ }
+
+ func navigateToCustomLists(nodes: [LocationNode]) {
let actionSheet = UIAlertController(
title: NSLocalizedString(
- "CUSTOM_LIST_ACTION_SHEET_TITLE",
- tableName: "CustomLists",
- value: "Custom lists",
- comment: ""
+ "ACTION_SHEET_TITLE", tableName: "CustomLists", value: "Custom lists", comment: ""
),
message: nil,
preferredStyle: UIDevice.current.userInterfaceIdiom == .pad ? .alert : .actionSheet
)
-
actionSheet.overrideUserInterfaceStyle = .dark
actionSheet.view.tintColor = UIColor(red: 0.0, green: 0.59, blue: 1.0, alpha: 1)
let addCustomListAction = UIAlertAction(
title: NSLocalizedString(
- "CUSTOM_LIST_ACTION_SHEET_ADD_LIST_BUTTON",
- tableName: "CustomLists",
- value: "Add new list",
- comment: ""
+ "ACTION_SHEET_ADD_LIST_BUTTON", tableName: "CustomLists", value: "Add new list", comment: ""
),
style: .default,
handler: { [weak self] _ in
@@ -214,12 +201,10 @@ extension LocationCoordinator: LocationViewControllerDelegate {
)
addCustomListAction.accessibilityIdentifier = AccessibilityIdentifier.addNewCustomListButton
actionSheet.addAction(addCustomListAction)
+
let editAction = UIAlertAction(
title: NSLocalizedString(
- "CUSTOM_LIST_ACTION_SHEET_EDIT_LISTS_BUTTON",
- tableName: "CustomLists",
- value: "Edit lists",
- comment: ""
+ "ACTION_SHEET_EDIT_LISTS_BUTTON", tableName: "CustomLists", value: "Edit lists", comment: ""
),
style: .default,
handler: { [weak self] _ in
@@ -228,7 +213,6 @@ extension LocationCoordinator: LocationViewControllerDelegate {
)
editAction.isEnabled = !customListRepository.fetchAll().isEmpty
editAction.accessibilityIdentifier = AccessibilityIdentifier.editCustomListButton
-
actionSheet.addAction(editAction)
actionSheet.addAction(UIAlertAction(
@@ -238,8 +222,7 @@ extension LocationCoordinator: LocationViewControllerDelegate {
value: "Cancel",
comment: ""
),
- style: .cancel,
- handler: nil
+ style: .cancel
))
presentationContext.present(actionSheet, animated: true)
diff --git a/ios/MullvadVPN/UI appearance/UIColor+Palette.swift b/ios/MullvadVPN/UI appearance/UIColor+Palette.swift
index 5cc9a562a1..bc53819d10 100644
--- a/ios/MullvadVPN/UI appearance/UIColor+Palette.swift
+++ b/ios/MullvadVPN/UI appearance/UIColor+Palette.swift
@@ -136,6 +136,11 @@ extension UIColor {
static let actionButtonColor = UIColor(white: 1.0, alpha: 0.8)
}
+ enum SegmentedControl {
+ static let backgroundColor = UIColor(red: 0.18, green: 0.33, blue: 0.49, alpha: 1.0)
+ static let selectedColor = successColor
+ }
+
// Common colors
static let primaryColor = UIColor(red: 0.16, green: 0.30, blue: 0.45, alpha: 1.0)
static let secondaryColor = UIColor(red: 0.10, green: 0.18, blue: 0.27, alpha: 1.0)
diff --git a/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift b/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift
index ab66f9b3ff..5a952b146b 100644
--- a/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift
+++ b/ios/MullvadVPN/View controllers/RelayFilter/RelayFilterView.swift
@@ -94,8 +94,8 @@ class RelayFilterView: UIView {
contentContainer.spacing = UIMetrics.FilterView.labelSpacing
addConstrainedSubviews([contentContainer]) {
- contentContainer.pinEdges(.init([.top(0), .bottom(0)]), to: self)
- contentContainer.pinEdges(.init([.leading(0), .trailing(0)]), to: layoutMarginsGuide)
+ contentContainer.pinEdges(.init([.top(4), .bottom(0)]), to: self)
+ contentContainer.pinEdges(.init([.leading(4), .trailing(4)]), to: layoutMarginsGuide)
}
}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift
index fa787f86c6..38188122ff 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift
@@ -6,14 +6,15 @@
// Copyright © 2019 Mullvad VPN AB. All rights reserved.
//
-import MullvadLogging
import MullvadREST
import MullvadSettings
import MullvadTypes
import UIKit
protocol LocationViewControllerDelegate: AnyObject {
- func didRequestRouteToCustomLists(_ controller: LocationViewController, nodes: [LocationNode])
+ func navigateToCustomLists(nodes: [LocationNode])
+ func didSelectRelays(relays: UserSelectedRelays)
+ func didUpdateFilter(filter: RelayFilter)
}
final class LocationViewController: UIViewController {
@@ -24,7 +25,7 @@ final class LocationViewController: UIViewController {
private var dataSource: LocationDataSource?
private var cachedRelays: CachedRelays?
private var filter = RelayFilter()
- var relayLocations: UserSelectedRelays?
+ private var selectedRelays: UserSelectedRelays?
weak var delegate: LocationViewControllerDelegate?
var customListRepository: CustomListRepositoryProtocol
@@ -36,13 +37,9 @@ final class LocationViewController: UIViewController {
return (filter.ownership == .any) && (filter.providers == .any)
}
- var navigateToFilter: (() -> Void)?
- var didSelectRelays: ((UserSelectedRelays) -> Void)?
- var didUpdateFilter: ((RelayFilter) -> Void)?
- var didFinish: (() -> Void)?
-
- init(customListRepository: CustomListRepositoryProtocol) {
+ init(customListRepository: CustomListRepositoryProtocol, selectedRelays: UserSelectedRelays?) {
self.customListRepository = customListRepository
+ self.selectedRelays = selectedRelays
super.init(nibName: nil, bundle: nil)
}
@@ -58,34 +55,6 @@ final class LocationViewController: UIViewController {
view.accessibilityIdentifier = .selectLocationView
view.backgroundColor = .secondaryColor
- navigationItem.title = NSLocalizedString(
- "NAVIGATION_TITLE",
- tableName: "SelectLocation",
- value: "Select location",
- comment: ""
- )
-
- navigationItem.leftBarButtonItem = UIBarButtonItem(
- title: NSLocalizedString(
- "NAVIGATION_TITLE",
- tableName: "SelectLocation",
- value: "Filter",
- comment: ""
- ),
- primaryAction: UIAction(handler: { [weak self] _ in
- self?.navigateToFilter?()
- })
- )
- navigationItem.leftBarButtonItem?.accessibilityIdentifier = .selectLocationFilterButton
-
- navigationItem.rightBarButtonItem = UIBarButtonItem(
- systemItem: .done,
- primaryAction: UIAction(handler: { [weak self] _ in
- self?.didFinish?()
- })
- )
- navigationItem.rightBarButtonItem?.accessibilityIdentifier = .closeSelectLocationButton
-
setUpDataSources()
setUpTableView()
setUpTopContent()
@@ -94,7 +63,7 @@ final class LocationViewController: UIViewController {
topContentView.pinEdgesToSuperviewMargins(.all().excluding(.bottom))
tableView.pinEdgesToSuperview(.all().excluding(.top))
- tableView.topAnchor.constraint(equalTo: topContentView.bottomAnchor)
+ tableView.topAnchor.constraint(equalTo: topContentView.bottomAnchor, constant: 8)
}
}
@@ -121,11 +90,11 @@ final class LocationViewController: UIViewController {
filterView.setFilter(filter)
}
- dataSource?.setRelays(cachedRelays.relays, selectedRelays: relayLocations, filter: filter)
+ dataSource?.setRelays(cachedRelays.relays, selectedRelays: selectedRelays, filter: filter)
}
func refreshCustomLists() {
- dataSource?.refreshCustomLists(selectedRelays: relayLocations)
+ dataSource?.refreshCustomLists(selectedRelays: selectedRelays)
}
// MARK: - Private
@@ -138,7 +107,7 @@ final class LocationViewController: UIViewController {
)
dataSource?.didSelectRelayLocations = { [weak self] locations in
- self?.didSelectRelays?(locations)
+ self?.delegate?.didSelectRelays(relays: locations)
}
dataSource?.didTapEditCustomLists = { [weak self] in
@@ -147,12 +116,12 @@ final class LocationViewController: UIViewController {
if let cachedRelays {
let allLocationDataSource = AllLocationDataSource()
allLocationDataSource.reload(cachedRelays.relays, relays: cachedRelays.relays.wireguard.relays)
- delegate?.didRequestRouteToCustomLists(self, nodes: allLocationDataSource.nodes)
+ delegate?.navigateToCustomLists(nodes: allLocationDataSource.nodes)
}
}
if let cachedRelays {
- dataSource?.setRelays(cachedRelays.relays, selectedRelays: relayLocations, filter: filter)
+ dataSource?.setRelays(cachedRelays.relays, selectedRelays: selectedRelays, filter: filter)
}
}
@@ -178,7 +147,7 @@ final class LocationViewController: UIViewController {
guard let self else { return }
filter = $0
- didUpdateFilter?($0)
+ delegate?.didUpdateFilter(filter: $0)
if let cachedRelays {
setCachedRelays(cachedRelays, filter: filter)
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift
new file mode 100644
index 0000000000..333d965f87
--- /dev/null
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewControllerWrapper.swift
@@ -0,0 +1,156 @@
+//
+// LocationViewControllerWrapper.swift
+// MullvadVPN
+//
+// Created by Jon Petersson on 2024-04-23.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import MullvadREST
+import MullvadSettings
+import MullvadTypes
+import UIKit
+
+protocol LocationViewControllerWrapperDelegate: AnyObject {
+ func navigateToCustomLists(nodes: [LocationNode])
+ func navigateToFilter()
+ func didSelectRelays(relays: UserSelectedRelays)
+ func didUpdateFilter(filter: RelayFilter)
+}
+
+final class LocationViewControllerWrapper: UIViewController {
+ private let locationViewController: LocationViewController
+ private let segmentedControl = UISegmentedControl()
+
+ weak var delegate: LocationViewControllerWrapperDelegate?
+
+ init(customListRepository: CustomListRepositoryProtocol, selectedRelays: UserSelectedRelays?) {
+ locationViewController = LocationViewController(
+ customListRepository: customListRepository,
+ selectedRelays: selectedRelays
+ )
+
+ super.init(nibName: nil, bundle: nil)
+
+ locationViewController.delegate = self
+ }
+
+ var didFinish: (() -> Void)?
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ view.accessibilityIdentifier = .selectLocationViewWrapper
+ view.backgroundColor = .secondaryColor
+
+ setUpNavigation()
+ setUpSegmentedControl()
+ addSubviews()
+ }
+
+ func setCachedRelays(_ cachedRelays: CachedRelays, filter: RelayFilter) {
+ locationViewController.setCachedRelays(cachedRelays, filter: filter)
+ }
+
+ func refreshCustomLists() {
+ locationViewController.refreshCustomLists()
+ }
+
+ private func setUpNavigation() {
+ navigationItem.largeTitleDisplayMode = .never
+
+ navigationItem.title = NSLocalizedString(
+ "NAVIGATION_TITLE",
+ tableName: "SelectLocation",
+ value: "Select location",
+ comment: ""
+ )
+
+ navigationItem.leftBarButtonItem = UIBarButtonItem(
+ title: NSLocalizedString(
+ "NAVIGATION_FILTER",
+ tableName: "SelectLocation",
+ value: "Filter",
+ comment: ""
+ ),
+ primaryAction: UIAction(handler: { [weak self] _ in
+ self?.delegate?.navigateToFilter()
+ })
+ )
+ navigationItem.leftBarButtonItem?.accessibilityIdentifier = .selectLocationFilterButton
+
+ navigationItem.rightBarButtonItem = UIBarButtonItem(
+ systemItem: .done,
+ primaryAction: UIAction(handler: { [weak self] _ in
+ self?.didFinish?()
+ })
+ )
+ navigationItem.rightBarButtonItem?.accessibilityIdentifier = .closeSelectLocationButton
+ }
+
+ private func setUpSegmentedControl() {
+ segmentedControl.backgroundColor = .SegmentedControl.backgroundColor
+ segmentedControl.selectedSegmentTintColor = .SegmentedControl.selectedColor
+ segmentedControl.setTitleTextAttributes([
+ .foregroundColor: UIColor.white,
+ .font: UIFont.systemFont(ofSize: 17, weight: .medium),
+ ], for: .normal)
+
+ segmentedControl.insertSegment(withTitle: NSLocalizedString(
+ "MULTIHOP_TAB_ENTRY",
+ tableName: "SelectLocation",
+ value: "Entry",
+ comment: ""
+ ), at: 0, animated: false)
+ segmentedControl.insertSegment(withTitle: NSLocalizedString(
+ "MULTIHOP_TAB_EXIT",
+ tableName: "SelectLocation",
+ value: "Exit",
+ comment: ""
+ ), at: 1, animated: false)
+
+ segmentedControl.selectedSegmentIndex = 0
+ segmentedControl.addTarget(self, action: #selector(segmentedControlDidChange), for: .valueChanged)
+ }
+
+ private func addSubviews() {
+ addChild(locationViewController)
+ locationViewController.didMove(toParent: self)
+
+ view.addConstrainedSubviews([segmentedControl, locationViewController.view]) {
+ segmentedControl.heightAnchor.constraint(equalToConstant: 44)
+ segmentedControl.pinEdgesToSuperviewMargins(PinnableEdges([.top(0), .leading(8), .trailing(8)]))
+
+ locationViewController.view.pinEdgesToSuperview(.all().excluding(.top))
+
+ #if DEBUG
+ locationViewController.view.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 4)
+ #else
+ locationViewController.view.pinEdgeToSuperviewMargin(.top(0))
+ #endif
+ }
+ }
+
+ @objc
+ private func segmentedControlDidChange(sender: UISegmentedControl) {
+ refreshCustomLists()
+ }
+}
+
+extension LocationViewControllerWrapper: LocationViewControllerDelegate {
+ func navigateToCustomLists(nodes: [LocationNode]) {
+ delegate?.navigateToCustomLists(nodes: nodes)
+ }
+
+ func didSelectRelays(relays: UserSelectedRelays) {
+ delegate?.didSelectRelays(relays: relays)
+ }
+
+ func didUpdateFilter(filter: RelayFilter) {
+ delegate?.didUpdateFilter(filter: filter)
+ }
+}