Skip to content

Commit

Permalink
Show providers when filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
buggmagnet authored and Jon Petersson committed Sep 21, 2023
1 parent 21d9641 commit 610e605
Show file tree
Hide file tree
Showing 18 changed files with 136 additions and 87 deletions.
63 changes: 33 additions & 30 deletions ios/MullvadVPN.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"pins" : [
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "173f567a2dfec11d74588eea82cecea555bdc0bc",
"version" : "1.4.0"
}
},
{
"identity" : "wireguard-apple",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mullvad/wireguard-apple.git",
"state" : {
"revision" : "11a00c20dc03f2751db47e94f585c0778c7bde82"
}
}
],
"version" : 2
}
1 change: 1 addition & 0 deletions ios/MullvadVPN/Coordinators/RelayFilterCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import MullvadTypes
import RelayCache
import Routing
import UIKit

class RelayFilterCoordinator: Coordinator, Presentable, RelayCacheTrackerObserver {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class FormSheetPresentationController: UIPresentationController {
let containerView,
!isInFullScreenPresentation else { return }
let frame = view.frame
let bottomMarginFromKeyboard = adjustment > 0 ? UIMetrics.sectionSpacing : 0
let bottomMarginFromKeyboard = adjustment > 0 ? UIMetrics.TableView.sectionSpacing : 0
view.frame = CGRect(
origin: CGPoint(
x: frame.origin.x,
Expand Down
29 changes: 13 additions & 16 deletions ios/MullvadVPN/UI appearance/UIMetrics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ import MullvadTypes
import UIKit

enum UIMetrics {
enum TableView {
/// Height for separators between cells and/or sections.
static let separatorHeight: CGFloat = 0.33
/// Spacing used between distinct sections of views
static let sectionSpacing: CGFloat = 24
/// Common layout margins for row views presentation
/// Similar to `SettingsCell.layoutMargins` however maintains equal horizontal spacing
static let rowViewLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24)
/// Common cell indentation width
static let cellIndentationWidth: CGFloat = 16
}

enum CustomAlert {
/// Layout margins for container (main view) in `CustomAlertViewController`
static let containerMargins = NSDirectionalEdgeInsets(
Expand Down Expand Up @@ -71,21 +83,6 @@ enum UIMetrics {
static let secondaryButtonPad = CGSize(width: 52, height: 52)
}

enum TableView {
/// Height for separators between cells and/or sections.
static let separatorHeight: CGFloat = 0.33

/// Spacing used between distinct sections of views
static let sectionSpacing: CGFloat = 24

/// Common layout margins for row views presentation
/// Similar to `SettingsCell.layoutMargins` however maintains equal horizontal spacing
static let rowViewLayoutMargins = NSDirectionalEdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24)

/// Common cell indentation width
static let cellIndentationWidth: CGFloat = 16
}

enum FilterView {
static let labelSpacing: CGFloat = 5
static let interChipViewSpacing: CGFloat = 8
Expand Down Expand Up @@ -135,7 +132,7 @@ extension UIMetrics {
/// Preferred content size for controllers presented using formsheet modal presentation style.
static let preferredFormSheetContentSize = CGSize(width: 480, height: 640)

/// Common layout margins for content presentation
/// Common layout margins for content presentation
static let contentLayoutMargins = NSDirectionalEdgeInsets(top: 24, leading: 24, bottom: 24, trailing: 24)

/// Common content margins for content presentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class AccountContentView: UIView {
contentStackView.pinEdgesToSuperviewMargins(.all().excluding(.bottom))
buttonStackView.topAnchor.constraint(
greaterThanOrEqualTo: contentStackView.bottomAnchor,
constant: UIMetrics.sectionSpacing
constant: UIMetrics.TableView.sectionSpacing
)
buttonStackView.pinEdgesToSuperviewMargins(.all().excluding(.top))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,10 +495,10 @@ final class PreferencesDataSource: UITableViewDiffableDataSource<
switch sectionIdentifier {
#if DEBUG
case .wireGuardObfuscationPort:
return UIMetrics.sectionSpacing
return UIMetrics.TableView.sectionSpacing
#else
case .wireGuardPorts:
return UIMetrics.sectionSpacing
return UIMetrics.TableView.sectionSpacing
#endif

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import UIKit
struct RelayFilterCellFactory: CellFactoryProtocol {
let tableView: UITableView

init(tableView: UITableView) {
self.tableView = tableView
}

func makeCell(for item: RelayFilterDataSource.Item, indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: item.reuseIdentifier.rawValue, for: indexPath)
configureCell(cell, item: item, indexPath: indexPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ final class RelayFilterDataSource: UITableViewDiffableDataSource<
let relayFilterCellFactory = RelayFilterCellFactory(tableView: tableView)
self.relayFilterCellFactory = relayFilterCellFactory

super.init(tableView: tableView) { tableView, indexPath, itemIdentifier in
super.init(tableView: tableView) { _, indexPath, itemIdentifier in
relayFilterCellFactory.makeCell(for: itemIdentifier, indexPath: indexPath)
}

Expand All @@ -55,9 +55,8 @@ final class RelayFilterDataSource: UITableViewDiffableDataSource<

viewModel.$relays
.combineLatest(viewModel.$relayFilter)
.sink { [weak self] relays in
print(relays)
self?.updateDataSnapshot()
.sink { [weak self] _, filter in
self?.updateDataSnapshot(filter: filter)
}
.store(in: &disposeBag)
}
Expand Down Expand Up @@ -113,7 +112,7 @@ final class RelayFilterDataSource: UITableViewDiffableDataSource<
applySnapshot(snapshot, animated: false)
}

private func updateDataSnapshot() {
private func updateDataSnapshot(filter: RelayFilter? = nil) {
let oldSnapshot = snapshot()

var newSnapshot = NSDiffableDataSourceSnapshot<Section, Item>()
Expand All @@ -127,9 +126,10 @@ final class RelayFilterDataSource: UITableViewDiffableDataSource<
}
case .providers:
if !oldSnapshot.itemIdentifiers(inSection: section).isEmpty {
let items = viewModel.uniqueProviders.map { Item.provider($0) }
let ownership = (filter ?? viewModel.relayFilter).ownership
let items = viewModel.availableProviders(for: ownership).map { Item.provider($0) }

newSnapshot.appendItems([.allProviders])
newSnapshot.appendItems([.allProviders], toSection: .providers)
newSnapshot.appendItems(items, toSection: .providers)
}
}
Expand Down Expand Up @@ -171,7 +171,10 @@ final class RelayFilterDataSource: UITableViewDiffableDataSource<
}

private func updateAllProvidersSelection() {
if viewModel.uniqueProviders.count == getSelectedIndexPaths(in: .providers).count {
let selectedCount = getSelectedIndexPaths(in: .providers).count
let providerCount = viewModel.availableProviders(for: viewModel.relayFilter.ownership).count

if selectedCount == providerCount {
selectRow(true, at: indexPath(for: .allProviders))
}
}
Expand Down Expand Up @@ -336,9 +339,8 @@ extension RelayFilterDataSource: UITableViewDelegate {
let items = snapshot.itemIdentifiers(inSection: .providers)
snapshot.deleteItems(items)
} else {
let items = viewModel.uniqueProviders.map { Item.provider($0) }

snapshot.appendItems([.allProviders])
let items = viewModel.availableProviders(for: viewModel.relayFilter.ownership).map { Item.provider($0) }
snapshot.appendItems([.allProviders], toSection: .providers)
snapshot.appendItems(items, toSection: .providers)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class RelayFilterView: UIView {
self.filter = filter

ownershipView.isHidden = filter.ownership == .any
providersView.isHidden = filter.providers == .any

switch filter.ownership {
case .any:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ class RelayFilterViewController: UIViewController {
comment: ""
)

navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .cancel, actionHandler: { [weak self] in
self?.didFinish?()
})
navigationItem.rightBarButtonItem = UIBarButtonItem(
systemItem: .cancel,
primaryAction: UIAction(handler: { [weak self] _ in
self?.didFinish?()
})
)

applyButton.addTarget(self, action: #selector(applyFilter), for: .touchUpInside)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ class RelayFilterViewModel {
@Published var relayFilter: RelayFilter

var uniqueProviders: [String] {
return Set(relays.map { $0.provider }).caseInsensitiveSorted()
Set(relays.map { $0.provider }).caseInsensitiveSorted()
}

var ownedProviders: [String] {
Set(relays.filter { $0.owned == true }.map { $0.provider }).caseInsensitiveSorted()
}

var rentedProviders: [String] {
Set(relays.filter { $0.owned == false }.map { $0.provider }).caseInsensitiveSorted()
}

init(relays: [REST.ServerRelay], relayFilter: RelayFilter) {
Expand All @@ -37,7 +45,12 @@ class RelayFilterViewModel {
if !providers.contains(name) {
providers.append(name)
providers.caseInsensitiveSort()
relayFilter.providers = .only(providers)

if providers == availableProviders(for: relayFilter.ownership) {
relayFilter.providers = .any
} else {
relayFilter.providers = .only(providers)
}
}
}
}
Expand All @@ -52,7 +65,7 @@ class RelayFilterViewModel {
case let .provider(name):
switch relayFilter.providers {
case .any:
var providers = uniqueProviders
var providers = availableProviders(for: relayFilter.ownership)
providers.removeAll { $0 == name }
relayFilter.providers = .only(providers)
case var .only(providers):
Expand Down Expand Up @@ -100,4 +113,15 @@ class RelayFilterViewModel {
func providerItem(for providerName: String?) -> RelayFilterDataSource.Item? {
return .provider(providerName ?? "")
}

func availableProviders(for ownership: RelayFilter.Ownership) -> [String] {
switch ownership {
case .any:
return uniqueProviders
case .owned:
return ownedProviders
case .rented:
return rentedProviders
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ final class LocationDataSource: UITableViewDiffableDataSource<Int, RelayLocation
let rootNode = Self.makeRootNode()
nodeByLocation.removeAll()

for relay in response.wireguard.relays {
for relay in relays {
guard case let .city(countryCode, cityCode) = RelayLocation(dashSeparatedString: relay.location),
let serverLocation = response.locations[relay.location] else { continue }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ final class SelectLocationViewController: UIViewController {
value: "Filter",
comment: ""
),
actionHandler: { [weak self] in
primaryAction: UIAction(handler: { [weak self] _ in
self?.navigateToFilter?()
}
})
)

navigationItem.rightBarButtonItem = UIBarButtonItem(
Expand All @@ -66,7 +66,7 @@ final class SelectLocationViewController: UIViewController {
self?.didFinish?()
})
)

setUpDataSource()
setUpTableView()
setUpTopContent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SettingsDNSInfoCell: UITableViewCell {
super.init(style: style, reuseIdentifier: reuseIdentifier)

backgroundColor = .secondaryColor
contentView.directionalLayoutMargins = UIMetrics.settingsCellLayoutMargins
contentView.directionalLayoutMargins = UIMetrics.SettingsCell.layoutMargins

titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.textColor = UIColor.Cell.titleTextColor
Expand Down
9 changes: 5 additions & 4 deletions ios/MullvadVPN/Views/CheckboxView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ class CheckboxView: UIView {
return imageView
}()

var isChecked: Bool { didSet {
checkmarkView.alpha = isChecked ? 1 : 0
}}
var isChecked = false {
didSet {
checkmarkView.alpha = isChecked ? 1 : 0
}
}

init() {
isChecked = false
super.init(frame: .zero)

directionalLayoutMargins = .init(top: 4, leading: 4, bottom: 4, trailing: 4)
Expand Down
1 change: 0 additions & 1 deletion ios/MullvadVPNTests/RelaySelectorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ class RelaySelectorTests: XCTestCase {
)

XCTAssertNil(result)
>>>>>>> a61a0cd20 (Add filtering to location selection)
}
}

Expand Down
12 changes: 6 additions & 6 deletions ios/RelaySelector/RelaySelector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,9 @@ public enum RelaySelector {
}

/// Determines whether a `REST.ServerRelay` satisfies the given relay filter.
public static func relayMatchesFilter(_ relay: REST.ServerRelay, filter: RelayFilter) -> Bool {
if case let .only(providers) = filter.providers {
if !providers.contains(relay.provider) {
return false
}
public static func relayMatchesFilter(_ relay: AnyRelay, filter: RelayFilter) -> Bool {
if case let .only(providers) = filter.providers, providers.contains(relay.provider) == false {
return false
}

switch filter.ownership {
Expand Down Expand Up @@ -318,9 +316,11 @@ public struct RelaySelectorResult: Codable {
}
}

protocol AnyRelay {
public protocol AnyRelay {
var hostname: String { get }
var owned: Bool { get }
var location: String { get }
var provider: String { get }
var weight: UInt64 { get }
var active: Bool { get }
var includeInCountry: Bool { get }
Expand Down

0 comments on commit 610e605

Please sign in to comment.