summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN
diff options
context:
space:
mode:
authormojganii <mojgan.jelodar@codic.se>2024-03-11 16:11:33 +0100
committerBug Magnet <marco.nikic@mullvad.net>2024-03-12 08:31:23 +0100
commit8506380b6f7453720faccf692b60ffd8a1bc112e (patch)
treed6b462d48943d756e9e29cbce2a2c3dfc5633331 /ios/MullvadVPN
parent1c89cd07fb90e23dd52a5e9441a2d144e913a7c3 (diff)
downloadmullvadvpn-8506380b6f7453720faccf692b60ffd8a1bc112e.tar.xz
mullvadvpn-8506380b6f7453720faccf692b60ffd8a1bc112e.zip
adding section header view in select location

- each section should have its own distinct header view. - custom list section has an action that should take user to add/edit custom list.it will be coming during upcoming changes. - refactoring location cell - removing LocationCellFactory
Diffstat (limited to 'ios/MullvadVPN')
-rw-r--r--ios/MullvadVPN/Coordinators/CustomLists/CustomListsDataSource.swift103
-rw-r--r--ios/MullvadVPN/Coordinators/LocationCoordinator.swift9
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift1
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/InMemoryCustomListRepository.swift20
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationCell.swift71
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift51
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift59
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift1
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationSectionHeaderView.swift95
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift15
10 files changed, 206 insertions, 219 deletions
diff --git a/ios/MullvadVPN/Coordinators/CustomLists/CustomListsDataSource.swift b/ios/MullvadVPN/Coordinators/CustomLists/CustomListsDataSource.swift
deleted file mode 100644
index e24a4c46dd..0000000000
--- a/ios/MullvadVPN/Coordinators/CustomLists/CustomListsDataSource.swift
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// CustomListsDataSource.swift
-// MullvadVPN
-//
-// Created by Jon Petersson on 2024-02-22.
-// Copyright © 2024 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-import MullvadREST
-import MullvadSettings
-import MullvadTypes
-import UIKit
-
-class CustomListsDataSource: LocationDataSourceProtocol {
- private(set) var nodes = [LocationNode]()
- var didTapEditCustomLists: (() -> Void)?
-
- var viewForHeader: UIView? {
- LocationSectionHeaderView(configuration: LocationSectionHeaderView.Configuration(
- name: LocationSection.customLists.description,
- primaryAction: UIAction(
- handler: { [weak self] _ in
- self?.didTapEditCustomLists?()
- }
- )
- ))
- }
-
- init(didTapEditCustomLists: (() -> Void)?) {
- self.didTapEditCustomLists = didTapEditCustomLists
- }
-
- var searchableNodes: [LocationNode] {
- nodes.flatMap { $0.children }
- }
-
- func reload(allLocationNodes: [LocationNode], customLists: [CustomList]) {
- nodes = customLists.map { list in
- let listNode = LocationListNode(
- nodeName: list.name,
- nodeCode: list.name.lowercased(),
- locations: list.locations,
- customList: list
- )
-
- listNode.children = list.locations.compactMap { location in
- copy(location, from: allLocationNodes, withParent: listNode)
- }
-
- listNode.forEachDescendant { _, node in
- node.nodeCode = "\(listNode.nodeCode)-\(node.nodeCode)"
- }
-
- return listNode
- }
- }
-
- func node(by locations: [RelayLocation], for customList: CustomList) -> LocationNode? {
- guard let customListNode = nodes.first(where: { $0.nodeName == customList.name })
- else { return nil }
-
- if locations.count > 1 {
- return customListNode
- } else {
- return switch locations.first {
- case let .country(countryCode):
- customListNode.nodeFor(nodeCode: "\(customListNode.nodeCode)-\(countryCode)")
- case let .city(_, cityCode):
- customListNode.nodeFor(nodeCode: "\(customListNode.nodeCode)-\(cityCode)")
- case let .hostname(_, _, hostCode):
- customListNode.nodeFor(nodeCode: "\(customListNode.nodeCode)-\(hostCode)")
- case .none:
- nil
- }
- }
- }
-
- private func copy(
- _ location: RelayLocation,
- from allLocationNodes: [LocationNode],
- withParent rootNode: LocationNode
- ) -> LocationNode? {
- let rootNode = RootNode(children: allLocationNodes)
-
- return switch location {
- case let .country(countryCode):
- rootNode
- .countryFor(countryCode: countryCode)?.copy(withParent: rootNode)
-
- case let .city(countryCode, cityCode):
- rootNode
- .countryFor(countryCode: countryCode)?.copy(withParent: rootNode)
- .cityFor(cityCode: cityCode)
-
- case let .hostname(countryCode, cityCode, hostCode):
- rootNode
- .countryFor(countryCode: countryCode)?.copy(withParent: rootNode)
- .cityFor(cityCode: cityCode)?
- .hostFor(hostCode: hostCode)
- }
- }
-}
diff --git a/ios/MullvadVPN/Coordinators/LocationCoordinator.swift b/ios/MullvadVPN/Coordinators/LocationCoordinator.swift
index fefc4a6f3a..4d18672f5a 100644
--- a/ios/MullvadVPN/Coordinators/LocationCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/LocationCoordinator.swift
@@ -140,13 +140,6 @@ class LocationCoordinator: Coordinator, Presentable, Presenting, RelayCacheTrack
extension LocationCoordinator: LocationViewControllerDelegate {
func didRequestRouteToCustomLists(_ controller: LocationViewController) {
- let coordinator = AddCustomListCoordinator(
- navigationController: CustomNavigationController(),
- customListInteractor: CustomListInteractor(
- repository: customListRepository
- )
- )
- coordinator.start()
- presentChild(coordinator, animated: true)
+ // TODO: Show add/Edit bottom sheet.
}
}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift
index 7427b78cc9..a6e9e1bab0 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift
@@ -9,7 +9,6 @@
import Foundation
import MullvadREST
import MullvadTypes
-import UIKit
class AllLocationDataSource: LocationDataSourceProtocol {
private(set) var nodes = [LocationNode]()
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/InMemoryCustomListRepository.swift b/ios/MullvadVPN/View controllers/SelectLocation/InMemoryCustomListRepository.swift
index fbc33ad071..999b4ad110 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/InMemoryCustomListRepository.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/InMemoryCustomListRepository.swift
@@ -17,12 +17,20 @@ class InMemoryCustomListRepository: CustomListRepositoryProtocol {
}
private var customRelayLists: [CustomList] = [
- CustomList(id: UUID(), name: "Netflix", locations: [.city("al", "tia")]),
- CustomList(id: UUID(), name: "Streaming", locations: [
- .city("us", "dal"),
- .country("se"),
- .city("de", "ber"),
- ]),
+ CustomList(
+ id: UUID(uuidString: "F17948CB-18E2-4F84-82CD-5780F94216DB")!,
+ name: "Netflix",
+ locations: [.city("al", "tia")]
+ ),
+ CustomList(
+ id: UUID(uuidString: "4104C603-B35D-4A64-8865-96C0BF33D57F")!,
+ name: "Streaming",
+ locations: [
+ .city("us", "dal"),
+ .country("se"),
+ .city("de", "ber"),
+ ]
+ ),
]
private let passthroughSubject = PassthroughSubject<[CustomList], Never>()
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationCell.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationCell.swift
index 8c1ed9334b..dfdd791de1 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationCell.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationCell.swift
@@ -8,25 +8,46 @@
import UIKit
-private let kCollapseButtonWidth: CGFloat = 24
-private let kRelayIndicatorSize: CGFloat = 16
+protocol LocationCellDelegate: AnyObject {
+ func toggle(cell: LocationCell)
+}
class LocationCell: UITableViewCell {
- typealias CollapseHandler = (LocationCell) -> Void
+ weak var delegate: LocationCellDelegate?
+
+ private let locationLabel: UILabel = {
+ let label = UILabel()
+ label.font = UIFont.systemFont(ofSize: 16)
+ label.textColor = .white
+ label.lineBreakMode = .byWordWrapping
+ label.numberOfLines = 0
+ label.lineBreakStrategy = []
+ return label
+ }()
- let locationLabel = UILabel()
- let statusIndicator: UIView = {
+ private let statusIndicator: UIView = {
let view = UIView()
- view.layer.cornerRadius = kRelayIndicatorSize * 0.5
+ view.layer.cornerRadius = 8
view.layer.cornerCurve = .circular
return view
}()
- let tickImageView = UIImageView(image: UIImage(named: "IconTick"))
- let collapseButton = UIButton(type: .custom)
+ private let tickImageView: UIImageView = {
+ let imageView = UIImageView(image: UIImage(resource: .iconTick))
+ imageView.tintColor = .white
+ return imageView
+ }()
+
+ private let collapseButton: UIButton = {
+ let button = UIButton(type: .custom)
+ button.accessibilityIdentifier = .collapseButton
+ button.isAccessibilityElement = false
+ button.tintColor = .white
+ return button
+ }()
- private let chevronDown = UIImage(named: "IconChevronDown")
- private let chevronUp = UIImage(named: "IconChevronUp")
+ private let chevronDown = UIImage(resource: .iconChevronDown)
+ private let chevronUp = UIImage(resource: .iconChevronUp)
var isDisabled = false {
didSet {
@@ -50,8 +71,6 @@ class LocationCell: UITableViewCell {
}
}
- var didCollapseHandler: CollapseHandler?
-
override var indentationLevel: Int {
didSet {
updateBackgroundColor()
@@ -103,17 +122,6 @@ class LocationCell: UITableViewCell {
selectedBackgroundView = UIView()
selectedBackgroundView?.backgroundColor = UIColor.Cell.Background.selected
- locationLabel.font = UIFont.systemFont(ofSize: 17)
- locationLabel.textColor = .white
- locationLabel.lineBreakMode = .byWordWrapping
- locationLabel.numberOfLines = 0
- locationLabel.lineBreakStrategy = []
-
- tickImageView.tintColor = .white
-
- collapseButton.accessibilityIdentifier = .collapseButton
- collapseButton.isAccessibilityElement = false
- collapseButton.tintColor = .white
collapseButton.addTarget(self, action: #selector(handleCollapseButton(_:)), for: .touchUpInside)
[locationLabel, tickImageView, statusIndicator, collapseButton].forEach { subview in
@@ -131,7 +139,7 @@ class LocationCell: UITableViewCell {
tickImageView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),
tickImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
- statusIndicator.widthAnchor.constraint(equalToConstant: kRelayIndicatorSize),
+ statusIndicator.widthAnchor.constraint(equalToConstant: 16),
statusIndicator.heightAnchor.constraint(equalTo: statusIndicator.widthAnchor),
statusIndicator.centerXAnchor.constraint(equalTo: tickImageView.centerXAnchor),
statusIndicator.centerYAnchor.constraint(equalTo: tickImageView.centerYAnchor),
@@ -148,7 +156,7 @@ class LocationCell: UITableViewCell {
collapseButton.widthAnchor
.constraint(
equalToConstant: UIMetrics.contentLayoutMargins.leading + UIMetrics
- .contentLayoutMargins.trailing + kCollapseButtonWidth
+ .contentLayoutMargins.trailing + 24
),
collapseButton.topAnchor.constraint(equalTo: contentView.topAnchor),
collapseButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
@@ -213,11 +221,11 @@ class LocationCell: UITableViewCell {
}
@objc private func handleCollapseButton(_ sender: UIControl) {
- didCollapseHandler?(self)
+ delegate?.toggle(cell: self)
}
@objc private func toggleCollapseAccessibilityAction() -> Bool {
- didCollapseHandler?(self)
+ delegate?.toggle(cell: self)
return true
}
@@ -255,3 +263,12 @@ class LocationCell: UITableViewCell {
}
}
}
+
+extension LocationCell {
+ func configureCell(item: LocationCellViewModel) {
+ accessibilityIdentifier = item.node.code
+ locationLabel.text = item.node.name
+ showsCollapseControl = !item.node.children.isEmpty
+ isExpanded = item.node.showsChildren
+ }
+}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift
deleted file mode 100644
index 1d0c1f9742..0000000000
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// LocationCellFactory.swift
-// MullvadVPN
-//
-// Created by Jon Petersson on 2023-03-17.
-// Copyright © 2023 Mullvad VPN AB. All rights reserved.
-//
-
-import MullvadTypes
-import UIKit
-
-protocol LocationCellEventHandler {
- func toggleCell(for item: LocationCellViewModel)
-}
-
-final class LocationCellFactory: CellFactoryProtocol {
- var delegate: LocationCellEventHandler?
- let tableView: UITableView
- let reuseIdentifier: String
-
- init(
- tableView: UITableView,
- reuseIdentifier: String
- ) {
- self.tableView = tableView
- self.reuseIdentifier = reuseIdentifier
- }
-
- func makeCell(for item: LocationCellViewModel, indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(
- withIdentifier: reuseIdentifier,
- for: indexPath
- )
-
- configureCell(cell, item: item, indexPath: indexPath)
-
- return cell
- }
-
- func configureCell(_ cell: UITableViewCell, item: LocationCellViewModel, indexPath: IndexPath) {
- guard let cell = cell as? LocationCell else { return }
-
- cell.accessibilityIdentifier = item.node.code
- cell.locationLabel.text = item.node.name
- cell.showsCollapseControl = !item.node.children.isEmpty
- cell.isExpanded = item.node.showsChildren
- cell.didCollapseHandler = { [weak self] _ in
- self?.delegate?.toggleCell(for: item)
- }
- }
-}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift
index 34b78737a7..77da5c69b9 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift
@@ -15,11 +15,11 @@ import UIKit
final class LocationDataSource: UITableViewDiffableDataSource<LocationSection, LocationCellViewModel> {
private var currentSearchString = ""
private let tableView: UITableView
- private let locationCellFactory: LocationCellFactory
private var dataSources: [LocationDataSourceProtocol] = []
private var selectedItem: LocationCellViewModel?
var didSelectRelayLocations: ((RelayLocations) -> Void)?
+ var didTapEditCustomLists: (() -> Void)?
init(
tableView: UITableView,
@@ -33,19 +33,18 @@ final class LocationDataSource: UITableViewDiffableDataSource<LocationSection, L
#endif
self.dataSources.append(allLocations)
- let locationCellFactory = LocationCellFactory(
- tableView: tableView,
- reuseIdentifier: LocationSection.Cell.locationCell.reuseIdentifier
- )
- self.locationCellFactory = locationCellFactory
-
super.init(tableView: tableView) { _, indexPath, itemIdentifier in
- locationCellFactory.makeCell(for: itemIdentifier, indexPath: indexPath)
+ let reuseIdentifier = LocationSection.Cell.locationCell.reuseIdentifier
+ let cell = tableView.dequeueReusableCell(
+ withIdentifier: reuseIdentifier,
+ for: indexPath
+ // swiftlint:disable:next force_cast
+ ) as! LocationCell
+ cell.configureCell(item: itemIdentifier)
+ return cell
}
tableView.delegate = self
- locationCellFactory.delegate = self
-
defaultRowAnimation = .fade
registerClasses()
}
@@ -218,21 +217,44 @@ final class LocationDataSource: UITableViewDiffableDataSource<LocationSection, L
return viewModels
}
+
+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ // swiftlint:disable:next force_cast
+ let cell = super.tableView(tableView, cellForRowAt: indexPath) as! LocationCell
+ cell.delegate = self
+ return cell
+ }
}
extension LocationDataSource: UITableViewDelegate {
+ func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
+ switch LocationSection.allCases[section] {
+ case .allLocations:
+ return LocationSectionHeaderView(
+ configuration: LocationSectionHeaderView.Configuration(name: LocationSection.allLocations.description)
+ )
+ case .customLists:
+ return LocationSectionHeaderView(configuration: LocationSectionHeaderView.Configuration(
+ name: LocationSection.customLists.description,
+ primaryAction: UIAction(
+ handler: { [weak self] _ in
+ self?.didTapEditCustomLists?()
+ }
+ )
+ ))
+ }
+ }
+
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
nil
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
- let section = snapshot().sectionIdentifiers[section]
-
- switch section {
+ switch LocationSection.allCases[section] {
+ case .allLocations:
+ return .zero
case .customLists:
return 24
- case .allLocations:
- return 0
}
}
@@ -263,9 +285,10 @@ extension LocationDataSource: UITableViewDelegate {
}
}
-extension LocationDataSource: LocationCellEventHandler {
- func toggleCell(for item: LocationCellViewModel) {
- guard let indexPath = indexPath(for: item) else { return }
+extension LocationDataSource: LocationCellDelegate {
+ func toggle(cell: LocationCell) {
+ guard let indexPath = tableView.indexPath(for: cell),
+ let item = itemIdentifier(for: indexPath) else { return }
let sections = LocationSection.allCases
let section = sections[indexPath.section]
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift
index 9fff54fff1..79f78ebc99 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift
@@ -9,7 +9,6 @@
import Foundation
import MullvadREST
import MullvadTypes
-import UIKit
protocol LocationDataSourceProtocol {
var nodes: [LocationNode] { get }
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationSectionHeaderView.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationSectionHeaderView.swift
new file mode 100644
index 0000000000..49c9cbce20
--- /dev/null
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationSectionHeaderView.swift
@@ -0,0 +1,95 @@
+//
+// LocationSectionHeaderView.swift
+// MullvadVPN
+//
+// Created by Mojgan on 2024-01-25.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+class LocationSectionHeaderView: UIView, UIContentView {
+ var configuration: UIContentConfiguration {
+ get {
+ actualConfiguration
+ } set {
+ guard let newConfiguration = newValue as? Configuration,
+ actualConfiguration != newConfiguration else { return }
+ let previousConfiguration = actualConfiguration
+ actualConfiguration = newConfiguration
+ apply(configuration: previousConfiguration)
+ }
+ }
+
+ private var actualConfiguration: Configuration
+ private let nameLabel: UILabel = {
+ let label = UILabel()
+ label.numberOfLines = 1
+ label.textColor = .primaryTextColor
+ label.font = .systemFont(ofSize: 16, weight: .semibold)
+ return label
+ }()
+
+ private let actionButton: UIButton = {
+ let button = UIButton(type: .system)
+ button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
+ button.tintColor = UIColor(white: 1, alpha: 0.6)
+ return button
+ }()
+
+ init(configuration: Configuration) {
+ self.actualConfiguration = configuration
+ super.init(frame: .zero)
+ applyAppearance()
+ addSubviews()
+ apply(configuration: configuration)
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ private func addSubviews() {
+ addConstrainedSubviews([nameLabel, actionButton]) {
+ nameLabel.pinEdgesToSuperviewMargins(.all().excluding(.trailing))
+
+ actionButton.pinEdgesToSuperviewMargins(PinnableEdges([.trailing(.zero)]))
+ actionButton.widthAnchor.constraint(equalToConstant: 24)
+ actionButton.heightAnchor.constraint(equalTo: actionButton.widthAnchor, multiplier: 1)
+ actionButton.centerYAnchor.constraint(equalTo: self.centerYAnchor)
+
+ actionButton.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 16)
+ }
+ }
+
+ private func apply(configuration: Configuration) {
+ let isActionHidden = configuration.primaryAction == nil
+ nameLabel.text = configuration.name
+ actionButton.isHidden = isActionHidden
+ actualConfiguration.primaryAction.flatMap { [weak self] action in
+ self?.actionButton.addAction(action, for: .touchUpInside)
+ }
+ }
+
+ private func applyAppearance() {
+ backgroundColor = .primaryColor
+ directionalLayoutMargins = NSDirectionalEdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 24)
+ }
+}
+
+extension LocationSectionHeaderView {
+ struct Configuration: UIContentConfiguration, Equatable {
+ let name: String
+
+ var primaryAction: UIAction?
+
+ func makeContentView() -> UIView & UIContentView {
+ LocationSectionHeaderView(configuration: self)
+ }
+
+ func updated(for state: UIConfigurationState) -> Configuration {
+ self
+ }
+ }
+}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift
index 3c37884544..baa3cce181 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationViewController.swift
@@ -83,7 +83,7 @@ final class LocationViewController: UIViewController {
})
)
- setUpDataSource()
+ setUpDataSources()
setUpTableView()
setUpTopContent()
@@ -119,17 +119,24 @@ final class LocationViewController: UIViewController {
// MARK: - Private
- private func setUpDataSource() {
+ private func setUpDataSources() {
+ let allLocationDataSource = AllLocationDataSource()
+ let customListsDataSource = CustomListsDataSource(repository: customListRepository)
dataSource = LocationDataSource(
tableView: tableView,
- allLocations: AllLocationDataSource(),
- customLists: CustomListsDataSource(repository: customListRepository)
+ allLocations: allLocationDataSource,
+ customLists: customListsDataSource
)
dataSource?.didSelectRelayLocations = { [weak self] locations in
self?.didSelectRelays?(locations)
}
+ dataSource?.didTapEditCustomLists = { [weak self] in
+ guard let self else { return }
+ delegate?.didRequestRouteToCustomLists(self)
+ }
+
if let cachedRelays {
dataSource?.setRelays(cachedRelays.relays, selectedLocations: relayLocations, filter: filter)
}