Skip to content

Commit

Permalink
Add a new container view to wrap the whole location selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson committed May 6, 2024
1 parent c2f6334 commit ab0cb28
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 97 deletions.
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -1854,6 +1855,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>"; };
Expand Down Expand Up @@ -2644,6 +2646,7 @@
F050AE512B70DFC0003F4EDB /* LocationSection.swift */,
F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */,
5888AD86227B17950051EB06 /* LocationViewController.swift */,
7AB3BEB42BD7A6CB00E34384 /* LocationViewControllerWrapper.swift */,
);
path = SelectLocation;
sourceTree = "<group>";
Expand Down Expand Up @@ -5579,6 +5582,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 */,
Expand Down
1 change: 1 addition & 0 deletions ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public enum AccessibilityIdentifier: String {
case outOfTimeView
case termsOfServiceView
case selectLocationView
case selectLocationViewWrapper
case selectLocationTableView
case settingsTableView
case vpnSettingsTableView
Expand Down
96 changes: 44 additions & 52 deletions ios/MullvadVPN/Coordinators/LocationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -54,56 +54,25 @@ 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)
}

relayCacheTracker.addObserver(self)

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)
Expand All @@ -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)
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -169,7 +138,7 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
// See showEditCustomLists() above.
extension LocationCoordinator: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
locationViewController?.refreshCustomLists()
locationViewControllerWrapper?.refreshCustomLists()
}
}

Expand All @@ -180,12 +149,37 @@ 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",
Expand Down Expand Up @@ -238,9 +232,7 @@ extension LocationCoordinator: LocationViewControllerDelegate {
value: "Cancel",
comment: ""
),
style: .cancel,
handler: nil
))
style: .cancel))

presentationContext.present(actionSheet, animated: true)
}
Expand Down
5 changes: 5 additions & 0 deletions ios/MullvadVPN/UI appearance/UIColor+Palette.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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

Expand All @@ -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)
}

Expand All @@ -58,33 +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.rightBarButtonItem = UIBarButtonItem(
systemItem: .done,
primaryAction: UIAction(handler: { [weak self] _ in
self?.didFinish?()
})
)
navigationItem.rightBarButtonItem?.accessibilityIdentifier = .closeSelectLocationButton

setUpDataSources()
setUpTableView()
setUpTopContent()
Expand All @@ -93,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)
}
}

Expand All @@ -120,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
Expand All @@ -137,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
Expand All @@ -146,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)
}
}

Expand All @@ -177,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)
Expand Down
Loading

0 comments on commit ab0cb28

Please sign in to comment.