Skip to content

Commit

Permalink
Update view model when switching between entry and exit location
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson committed Jun 7, 2024
1 parent 32c4186 commit 9e9ed56
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 105 deletions.
2 changes: 1 addition & 1 deletion ios/MullvadTypes/RelayConstraints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class RelayConstraintsUpdater: ConstraintsPropagation {
}
}

public struct RelayConstraints: Codable, Equatable, CustomDebugStringConvertible {
public struct RelayConstraints: Codable, Equatable {
@available(*, deprecated, renamed: "locations")
private var location: RelayConstraint<RelayLocation> = .only(.country("se"))

Expand Down
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@
7A3353912AAA014400F0A71C /* SimulatorVPNConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3353902AAA014400F0A71C /* SimulatorVPNConnection.swift */; };
7A3353932AAA089000F0A71C /* SimulatorTunnelInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3353922AAA089000F0A71C /* SimulatorTunnelInfo.swift */; };
7A3353972AAA0F8600F0A71C /* OperationBlockObserverSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3353962AAA0F8600F0A71C /* OperationBlockObserverSupport.swift */; };
7A3EFAAB2BDFDAE800318736 /* RelaySelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3EFAAA2BDFDAE800318736 /* RelaySelection.swift */; };
7A3FD1B52AD4465A0042BEA6 /* AppMessageHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3FD1B42AD4465A0042BEA6 /* AppMessageHandlerTests.swift */; };
7A3FD1B72AD54ABD0042BEA6 /* AnyTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BDEB982A98F4ED00F578F2 /* AnyTransport.swift */; };
7A3FD1B82AD54AE60042BEA6 /* TimeServerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BDEB9A2A98F58600F578F2 /* TimeServerProxy.swift */; };
Expand Down Expand Up @@ -1841,6 +1842,7 @@
7A3353902AAA014400F0A71C /* SimulatorVPNConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulatorVPNConnection.swift; sourceTree = "<group>"; };
7A3353922AAA089000F0A71C /* SimulatorTunnelInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulatorTunnelInfo.swift; sourceTree = "<group>"; };
7A3353962AAA0F8600F0A71C /* OperationBlockObserverSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationBlockObserverSupport.swift; sourceTree = "<group>"; };
7A3EFAAA2BDFDAE800318736 /* RelaySelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelection.swift; sourceTree = "<group>"; };
7A3FD1B42AD4465A0042BEA6 /* AppMessageHandlerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageHandlerTests.swift; sourceTree = "<group>"; };
7A42DEC82A05164100B209BE /* SettingsInputCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInputCell.swift; sourceTree = "<group>"; };
7A45CFC22C05FF2F00D80B21 /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2768,6 +2770,7 @@
F0BE65362B9F136A005CC385 /* LocationSectionHeaderView.swift */,
5888AD86227B17950051EB06 /* LocationViewController.swift */,
7AB3BEB42BD7A6CB00E34384 /* LocationViewControllerWrapper.swift */,
7A3EFAAA2BDFDAE800318736 /* RelaySelection.swift */,
);
path = SelectLocation;
sourceTree = "<group>";
Expand Down Expand Up @@ -5774,6 +5777,7 @@
5878F50029CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift in Sources */,
7A28826D2BAAC9DE00FD9F20 /* IPOverrideHeaderView.swift in Sources */,
A98502032B627B120061901E /* LocalNetworkProbe.swift in Sources */,
7A3EFAAB2BDFDAE800318736 /* RelaySelection.swift in Sources */,
583FE01029C0F532006E85F9 /* CustomSplitViewController.swift in Sources */,
7A6F2FA92AFD0842006D0856 /* CustomDNSDataSource.swift in Sources */,
58EF580B25D69D7A00AEBA94 /* ProblemReportSubmissionOverlayView.swift in Sources */,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,31 @@ class ListCustomListCoordinator: Coordinator, Presentable, Presenting {

coordinator.didFinish = { [weak self] editCustomListCoordinator, action, list in
guard let self else { return }

popToList()
editCustomListCoordinator.removeFromParent()
self.updateRelayConstraints(for: action, in: list)

var relayConstraints = tunnelManager.settings.relayConstraints
RelaySelection.MultihopContext.allCases.forEach { context in
switch context {
case .entry:
relayConstraints.entryLocations = self.updateRelayConstraint(
relayConstraints.entryLocations,
for: action,
in: list
)
case .exit:
relayConstraints.exitLocations = self.updateRelayConstraint(
relayConstraints.exitLocations,
for: action,
in: list
)
}
}

tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) { [weak self] in
self?.tunnelManager.reconnectTunnel(selectNewRelay: true)
}
}

coordinator.didCancel = { [weak self] editCustomListCoordinator in
Expand All @@ -75,38 +97,39 @@ class ListCustomListCoordinator: Coordinator, Presentable, Presenting {
addChild(coordinator)
}

private func updateRelayConstraints(for action: EditCustomListCoordinator.FinishAction, in list: CustomList) {
var relayConstraints = tunnelManager.settings.relayConstraints
private func updateRelayConstraint(
_ relayConstraint: RelayConstraint<UserSelectedRelays>,
for action: EditCustomListCoordinator.FinishAction,
in list: CustomList
) -> RelayConstraint<UserSelectedRelays> {
var relayConstraint = relayConstraint

guard let customListSelection = relayConstraints.exitLocations.value?.customListSelection,
guard let customListSelection = relayConstraint.value?.customListSelection,
customListSelection.listId == list.id
else { return }
else { return relayConstraint }

switch action {
case .save:
// TODO: - Add entry locations
if customListSelection.isList {
let selectedRelays = UserSelectedRelays(
locations: list.locations,
customListSelection: UserSelectedRelays.CustomListSelection(listId: list.id, isList: true)
)
relayConstraints.exitLocations = .only(selectedRelays)
relayConstraint = .only(selectedRelays)
} else {
let selectedConstraintIsRemovedFromList = list.locations.filter {
relayConstraints.exitLocations.value?.locations.contains($0) ?? false
relayConstraint.value?.locations.contains($0) ?? false
}.isEmpty

if selectedConstraintIsRemovedFromList {
relayConstraints.exitLocations = .only(UserSelectedRelays(locations: []))
relayConstraint = .only(UserSelectedRelays(locations: []))
}
}
case .delete:
relayConstraints.exitLocations = .only(UserSelectedRelays(locations: []))
relayConstraint = .only(UserSelectedRelays(locations: []))
}

tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) { [weak self] in
self?.tunnelManager.reconnectTunnel(selectNewRelay: true)
}
return relayConstraint
}

private func popToList() {
Expand Down
19 changes: 13 additions & 6 deletions ios/MullvadVPN/Coordinators/LocationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ class LocationCoordinator: Coordinator, Presentable, Presenting {
}

func start() {
// TODO: - the location should be defined whether it's Entry or Exit location
let locationViewControllerWrapper = LocationViewControllerWrapper(
customListRepository: customListRepository,
selectedRelays: tunnelManager.settings.relayConstraints.exitLocations.value
selectedRelays: RelaySelection(
entry: tunnelManager.settings.relayConstraints.entryLocations.value,
exit: tunnelManager.settings.relayConstraints.exitLocations.value,
currentContext: .exit
)
)
locationViewControllerWrapper.delegate = self

Expand Down Expand Up @@ -155,15 +158,19 @@ extension LocationCoordinator: RelayCacheTrackerObserver {
}

extension LocationCoordinator: LocationViewControllerWrapperDelegate {
func didSelectRelays(relays: UserSelectedRelays) {
func didSelectRelays(relays: (relays: UserSelectedRelays, context: RelaySelection.MultihopContext)) {
var relayConstraints = tunnelManager.settings.relayConstraints
relayConstraints.exitLocations = .only(relays)

switch relays.context {
case .entry:
relayConstraints.entryLocations = .only(relays.relays)
case .exit:
relayConstraints.exitLocations = .only(relays.relays)
}

tunnelManager.updateSettings([.relayConstraints(relayConstraints)]) {
self.tunnelManager.startTunnel()
}

didFinish?(self)
}

func didUpdateFilter(filter: RelayFilter) {
Expand Down
2 changes: 1 addition & 1 deletion ios/MullvadVPN/UI appearance/UIColor+Palette.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ extension UIColor {
}

enum SegmentedControl {
static let backgroundColor = UIColor(red: 0.18, green: 0.33, blue: 0.49, alpha: 1.0)
static let backgroundColor = UIColor(red: 0.14, green: 0.25, blue: 0.38, alpha: 1.0)
static let selectedColor = successColor
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class RelayFilterView: UIView {
contentContainer.spacing = UIMetrics.FilterView.labelSpacing

addConstrainedSubviews([contentContainer]) {
contentContainer.pinEdges(.init([.top(4), .bottom(0)]), to: self)
contentContainer.pinEdges(.init([.top(7), .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 @@ -69,6 +69,7 @@ class LocationCell: UITableViewCell {
private var behavior: LocationCellBehavior = .select
private let chevronDown = UIImage(resource: .iconChevronDown)
private let chevronUp = UIImage(resource: .iconChevronUp)
private var isMultipHopSelection = false

var isDisabled = false {
didSet {
Expand Down Expand Up @@ -245,7 +246,7 @@ class LocationCell: UITableViewCell {
}

private func statusIndicatorColor() -> UIColor {
if isDisabled {
if isDisabled && !isMultipHopSelection {
return UIColor.RelayStatusIndicator.inactiveColor
} else if isHighlighted {
return UIColor.RelayStatusIndicator.highlightColor
Expand Down Expand Up @@ -339,9 +340,18 @@ extension LocationCell {
}
}

setMultihopSelection(item.multihopContext)
setBehavior(behavior)
}

func setMultihopSelection(_ context: RelaySelection.MultihopContext?) {
if let context {
isMultipHopSelection = true
isDisabled = true
locationLabel.text! += " (\(context.description))"
}
}

private func setBehavior(_ newBehavior: LocationCellBehavior) {
self.behavior = newBehavior
updateLeadingImage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,20 @@ struct LocationCellViewModel: Hashable {
let node: LocationNode
var indentationLevel = 0
var isSelected = false
var multihopContext: RelaySelection.MultihopContext?

func hash(into hasher: inout Hasher) {
hasher.combine(node)
hasher.combine(node.children.count)
hasher.combine(section)
hasher.combine(isSelected)
hasher.combine(indentationLevel)
}

static func == (lhs: Self, rhs: Self) -> Bool {
lhs.node == rhs.node &&
lhs.node.children.count == rhs.node.children.count &&
lhs.section == rhs.section &&
lhs.isSelected == rhs.isSelected &&
lhs.indentationLevel == rhs.indentationLevel
lhs.isSelected == rhs.isSelected
}
}

Expand Down
Loading

0 comments on commit 9e9ed56

Please sign in to comment.