Skip to content

Commit b21fbed

Browse files
author
Jon Petersson
committed
Split select location view into two sections
1 parent b74b165 commit b21fbed

24 files changed

+990
-472
lines changed

ios/.swiftlint.yml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ disabled_rules:
77
- type_body_length
88
- opening_brace # Differs from Google swift guidelines enforced by swiftformat
99
- trailing_comma
10+
- switch_case_alignment # Enables expressions such as [return switch location {}]
1011
opt_in_rules:
1112
- empty_count
1213

ios/MullvadVPN.xcodeproj/project.pbxproj

+49-25
Large diffs are not rendered by default.

ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
6565
}()
6666

6767
private var splitTunnelCoordinator: TunnelCoordinator?
68-
private var splitLocationCoordinator: SelectLocationCoordinator?
68+
private var splitLocationCoordinator: LocationCoordinator?
6969

7070
private let tunnelManager: TunnelManager
7171
private let storePaymentManager: StorePaymentManager
@@ -703,11 +703,11 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
703703
}
704704

705705
private func makeSelectLocationCoordinator(forModalPresentation isModalPresentation: Bool)
706-
-> SelectLocationCoordinator {
706+
-> LocationCoordinator {
707707
let navigationController = CustomNavigationController()
708708
navigationController.isNavigationBarHidden = !isModalPresentation
709709

710-
let selectLocationCoordinator = SelectLocationCoordinator(
710+
let selectLocationCoordinator = LocationCoordinator(
711711
navigationController: navigationController,
712712
tunnelManager: tunnelManager,
713713
relayCacheTracker: relayCacheTracker

ios/MullvadVPN/Coordinators/SelectLocationCoordinator.swift ios/MullvadVPN/Coordinators/LocationCoordinator.swift

+13-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// SelectLocationCoordinator.swift
2+
// LocationCoordinator.swift
33
// MullvadVPN
44
//
55
// Created by pronebird on 29/01/2023.
@@ -13,7 +13,7 @@ import UIKit
1313

1414
import MullvadSettings
1515

16-
class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCacheTrackerObserver {
16+
class LocationCoordinator: Coordinator, Presentable, Presenting, RelayCacheTrackerObserver {
1717
private let tunnelManager: TunnelManager
1818
private let relayCacheTracker: RelayCacheTracker
1919
private var cachedRelays: CachedRelays?
@@ -24,10 +24,10 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
2424
navigationController
2525
}
2626

27-
var selectLocationViewController: SelectLocationViewController? {
27+
var selectLocationViewController: LocationViewController? {
2828
return navigationController.viewControllers.first {
29-
$0 is SelectLocationViewController
30-
} as? SelectLocationViewController
29+
$0 is LocationViewController
30+
} as? LocationViewController
3131
}
3232

3333
var relayFilter: RelayFilter {
@@ -39,7 +39,7 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
3939
}
4040
}
4141

42-
var didFinish: ((SelectLocationCoordinator, RelayLocation?) -> Void)?
42+
var didFinish: ((LocationCoordinator, [RelayLocation]) -> Void)?
4343

4444
init(
4545
navigationController: UINavigationController,
@@ -52,22 +52,22 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
5252
}
5353

5454
func start() {
55-
let selectLocationViewController = SelectLocationViewController()
55+
let selectLocationViewController = LocationViewController()
5656

57-
selectLocationViewController.didSelectRelay = { [weak self] relay in
57+
selectLocationViewController.didSelectRelays = { [weak self] locations, customListId in
5858
guard let self else { return }
5959

6060
var relayConstraints = tunnelManager.settings.relayConstraints
6161
relayConstraints.locations = .only(RelayLocations(
62-
locations: [relay],
63-
customListId: nil
62+
locations: locations,
63+
customListId: customListId
6464
))
6565

6666
tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) {
6767
self.tunnelManager.startTunnel()
6868
}
6969

70-
didFinish?(self, relay)
70+
didFinish?(self, locations)
7171
}
7272

7373
selectLocationViewController.navigateToFilter = { [weak self] in
@@ -91,7 +91,7 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
9191
selectLocationViewController.didFinish = { [weak self] in
9292
guard let self else { return }
9393

94-
didFinish?(self, nil)
94+
didFinish?(self, [])
9595
}
9696

9797
relayCacheTracker.addObserver(self)
@@ -101,8 +101,7 @@ class SelectLocationCoordinator: Coordinator, Presentable, Presenting, RelayCach
101101
selectLocationViewController.setCachedRelays(cachedRelays, filter: relayFilter)
102102
}
103103

104-
selectLocationViewController.relayLocation =
105-
tunnelManager.settings.relayConstraints.locations.value?.locations.first
104+
selectLocationViewController.relayLocations = tunnelManager.settings.relayConstraints.locations.value
106105

107106
navigationController.pushViewController(selectLocationViewController, animated: false)
108107
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// SettingsValidationErrorConfiguration.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-02-16.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
struct SettingsValidationErrorConfiguration: UIContentConfiguration, Equatable {
12+
var errors: [CustomListFieldValidationError] = []
13+
var directionalLayoutMargins: NSDirectionalEdgeInsets = UIMetrics.SettingsCell.settingsValidationErrorLayoutMargins
14+
15+
func makeContentView() -> UIView & UIContentView {
16+
return SettingsValidationErrorContentView(configuration: self)
17+
}
18+
19+
func updated(for state: UIConfigurationState) -> Self {
20+
return self
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//
2+
// SettingsValidationErrorContentView.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-02-16.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
class SettingsValidationErrorContentView: UIView, UIContentView {
12+
let contentView = UIStackView()
13+
14+
var icon: UIImageView {
15+
let view = UIImageView(image: UIImage(resource: .iconAlert).withTintColor(.dangerColor))
16+
view.heightAnchor.constraint(equalToConstant: 14).isActive = true
17+
view.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1).isActive = true
18+
return view
19+
}
20+
21+
var configuration: UIContentConfiguration {
22+
get {
23+
actualConfiguration
24+
}
25+
set {
26+
guard let newConfiguration = newValue as? SettingsValidationErrorConfiguration else { return }
27+
28+
let previousConfiguration = actualConfiguration
29+
actualConfiguration = newConfiguration
30+
31+
configureSubviews(previousConfiguration: previousConfiguration)
32+
}
33+
}
34+
35+
private var actualConfiguration: SettingsValidationErrorConfiguration
36+
37+
func supports(_ configuration: UIContentConfiguration) -> Bool {
38+
configuration is SettingsValidationErrorConfiguration
39+
}
40+
41+
init(configuration: SettingsValidationErrorConfiguration) {
42+
actualConfiguration = configuration
43+
44+
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
45+
46+
addSubviews()
47+
configureSubviews()
48+
}
49+
50+
required init?(coder: NSCoder) {
51+
fatalError("init(coder:) has not been implemented")
52+
}
53+
54+
private func addSubviews() {
55+
contentView.axis = .vertical
56+
contentView.spacing = 6
57+
58+
addConstrainedSubviews([contentView]) {
59+
contentView.pinEdgesToSuperviewMargins()
60+
}
61+
}
62+
63+
private func configureSubviews(previousConfiguration: SettingsValidationErrorConfiguration? = nil) {
64+
guard actualConfiguration != previousConfiguration else { return }
65+
66+
configureLayoutMargins()
67+
68+
contentView.arrangedSubviews.forEach { view in
69+
view.removeFromSuperview()
70+
}
71+
72+
actualConfiguration.errors.forEach { error in
73+
let label = UILabel()
74+
label.text = error.errorDescription
75+
label.numberOfLines = 0
76+
label.font = .systemFont(ofSize: 13)
77+
label.textColor = .white.withAlphaComponent(0.6)
78+
79+
let stackView = UIStackView(arrangedSubviews: [icon, label])
80+
stackView.alignment = .top
81+
stackView.spacing = 6
82+
83+
contentView.addArrangedSubview(stackView)
84+
}
85+
}
86+
87+
private func configureLayoutMargins() {
88+
directionalLayoutMargins = actualConfiguration.directionalLayoutMargins
89+
}
90+
}

ios/MullvadVPN/UI appearance/UIColor+Palette.swift

+4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ extension UIColor {
117117
static let backgroundColor = UIColor(red: 0.13, green: 0.20, blue: 0.30, alpha: 1.0)
118118
}
119119

120+
enum SubSubSubCell {
121+
static let backgroundColor = UIColor(red: 0.11, green: 0.17, blue: 0.27, alpha: 1.0)
122+
}
123+
120124
enum HeaderBar {
121125
static let defaultBackgroundColor = primaryColor
122126
static let unsecuredBackgroundColor = dangerColor

ios/MullvadVPN/UI appearance/UIMetrics.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ extension UIMetrics {
173173
static let contentInsets = UIEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)
174174

175175
/// Common layout margins for location cell presentation
176-
static let selectLocationCellLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 28, bottom: 16, trailing: 12)
176+
static let locationCellLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 28, bottom: 16, trailing: 12)
177177

178178
/// Layout margins used by content heading displayed below the large navigation title.
179179
static let contentHeadingLayoutMargins = NSDirectionalEdgeInsets(top: 8, leading: 24, bottom: 24, trailing: 24)

0 commit comments

Comments
 (0)