summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadTypes/RelayLocation.swift2
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj8
-rw-r--r--ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved22
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift68
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/CustomListsDataSource.swift6
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift4
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift2
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift155
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift10
-rw-r--r--ios/MullvadVPN/View controllers/SelectLocation/SelectLocationSection.swift (renamed from ios/MullvadVPN/View controllers/SelectLocation/SelectLocationGroup.swift)6
10 files changed, 154 insertions, 129 deletions
diff --git a/ios/MullvadTypes/RelayLocation.swift b/ios/MullvadTypes/RelayLocation.swift
index 3018d157c4..b797e69d3c 100644
--- a/ios/MullvadTypes/RelayLocation.swift
+++ b/ios/MullvadTypes/RelayLocation.swift
@@ -63,7 +63,7 @@ public enum RelayLocation: Codable, Hashable, CustomDebugStringConvertible {
}
/// A list of `RelayLocation` items preceding the given one in the relay tree
- public var ascendants: [RelayLocation] {
+ public var ancestors: [RelayLocation] {
switch self {
case let .hostname(country, city, _):
return [.country(country), .city(country, city)]
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 888d2782ac..6495711e90 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -792,7 +792,7 @@
F050AE4C2B70D5A7003F4EDB /* SelectLocationNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE4B2B70D5A7003F4EDB /* SelectLocationNode.swift */; };
F050AE4E2B70D7F8003F4EDB /* LocationCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE4D2B70D7F8003F4EDB /* LocationCellViewModel.swift */; };
F050AE502B70DC4F003F4EDB /* SelectLocationNodeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE4F2B70DC4F003F4EDB /* SelectLocationNodeProtocol.swift */; };
- F050AE522B70DFC0003F4EDB /* SelectLocationGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE512B70DFC0003F4EDB /* SelectLocationGroup.swift */; };
+ F050AE522B70DFC0003F4EDB /* SelectLocationSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE512B70DFC0003F4EDB /* SelectLocationSection.swift */; };
F050AE5E2B739A73003F4EDB /* LocationDataSourceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE5D2B739A73003F4EDB /* LocationDataSourceProtocol.swift */; };
F050AE602B73A41E003F4EDB /* AllLocationDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE5F2B73A41E003F4EDB /* AllLocationDataSource.swift */; };
F050AE622B74DBAC003F4EDB /* CustomListsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE612B74DBAC003F4EDB /* CustomListsDataSource.swift */; };
@@ -1908,7 +1908,7 @@
F050AE4B2B70D5A7003F4EDB /* SelectLocationNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationNode.swift; sourceTree = "<group>"; };
F050AE4D2B70D7F8003F4EDB /* LocationCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationCellViewModel.swift; sourceTree = "<group>"; };
F050AE4F2B70DC4F003F4EDB /* SelectLocationNodeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationNodeProtocol.swift; sourceTree = "<group>"; };
- F050AE512B70DFC0003F4EDB /* SelectLocationGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationGroup.swift; sourceTree = "<group>"; };
+ F050AE512B70DFC0003F4EDB /* SelectLocationSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationSection.swift; sourceTree = "<group>"; };
F050AE5D2B739A73003F4EDB /* LocationDataSourceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationDataSourceProtocol.swift; sourceTree = "<group>"; };
F050AE5F2B73A41E003F4EDB /* AllLocationDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllLocationDataSource.swift; sourceTree = "<group>"; };
F050AE612B74DBAC003F4EDB /* CustomListsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomListsDataSource.swift; sourceTree = "<group>"; };
@@ -2345,7 +2345,7 @@
583DA21325FA4B5C00318683 /* LocationDataSource.swift */,
F050AE5D2B739A73003F4EDB /* LocationDataSourceProtocol.swift */,
5888AD82227B11080051EB06 /* SelectLocationCell.swift */,
- F050AE512B70DFC0003F4EDB /* SelectLocationGroup.swift */,
+ F050AE512B70DFC0003F4EDB /* SelectLocationSection.swift */,
F050AE4B2B70D5A7003F4EDB /* SelectLocationNode.swift */,
F050AE4F2B70DC4F003F4EDB /* SelectLocationNodeProtocol.swift */,
5888AD86227B17950051EB06 /* SelectLocationViewController.swift */,
@@ -5213,7 +5213,7 @@
586C0D912B03D8A400E7CDD7 /* AccessMethodHeaderFooterReuseIdentifier.swift in Sources */,
F050AE4C2B70D5A7003F4EDB /* SelectLocationNode.swift in Sources */,
7A2960F62A963F7500389B82 /* AlertCoordinator.swift in Sources */,
- F050AE522B70DFC0003F4EDB /* SelectLocationGroup.swift in Sources */,
+ F050AE522B70DFC0003F4EDB /* SelectLocationSection.swift in Sources */,
063687BA28EB234F00BE7161 /* PacketTunnelTransport.swift in Sources */,
A9C342C12ACC37E30045F00E /* TunnelStatusBlockObserver.swift in Sources */,
587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */,
diff --git a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
new file mode 100644
index 0000000000..02691892fe
--- /dev/null
+++ b/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -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
+}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift
index 0d4c6b9bce..33bfe57593 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/AllLocationDataSource.swift
@@ -15,52 +15,50 @@ class AllLocationDataSource: LocationDataSourceProtocol {
private var locationList = [RelayLocation]()
func search(by text: String) -> [RelayLocation] {
- if text.isEmpty {
+ guard !text.isEmpty else {
return locationList
- } else {
- var filteredLocations: [RelayLocation] = []
- locationList.forEach { location in
- guard let countryNode = nodeByLocation[location] else { return }
- countryNode.showsChildren = false
+ }
- if text.isEmpty || countryNode.displayName.fuzzyMatch(text) {
- filteredLocations.append(countryNode.location)
- }
+ var filteredLocations: [RelayLocation] = []
+ locationList.forEach { location in
+ guard let countryNode = nodeByLocation[location] else { return }
+ countryNode.showsChildren = false
- for cityNode in countryNode.children {
- cityNode.showsChildren = false
+ if countryNode.displayName.fuzzyMatch(text) {
+ filteredLocations.append(countryNode.location)
+ }
- let relaysContainSearchString = cityNode.children
- .contains(where: { $0.displayName.fuzzyMatch(text) })
+ countryNode.children.forEach { cityNode in
+ cityNode.showsChildren = false
- if cityNode.displayName.fuzzyMatch(text) || relaysContainSearchString {
- if !filteredLocations.contains(where: { $0 == countryNode.location }) {
- filteredLocations.append(countryNode.location)
- }
+ let relaysContainSearchString = cityNode.children
+ .contains(where: { $0.displayName.fuzzyMatch(text) })
- filteredLocations.append(cityNode.location)
- countryNode.showsChildren = true
+ if cityNode.displayName.fuzzyMatch(text) || relaysContainSearchString {
+ if !filteredLocations.contains(countryNode.location) {
+ filteredLocations.append(countryNode.location)
+ }
- if relaysContainSearchString {
- cityNode.children.map { $0.location }.forEach {
- filteredLocations.append($0)
- }
- cityNode.showsChildren = true
- }
+ filteredLocations.append(cityNode.location)
+ countryNode.showsChildren = true
+
+ if relaysContainSearchString {
+ filteredLocations.append(contentsOf: cityNode.children.map { $0.location })
+ cityNode.showsChildren = true
}
}
}
-
- return filteredLocations
}
+
+ return filteredLocations
}
func reload(
- _ response: MullvadREST.REST.ServerRelaysResponse,
- relays: [MullvadREST.REST.ServerRelay]
+ _ response: REST.ServerRelaysResponse,
+ relays: [REST.ServerRelay]
) -> [RelayLocation] {
nodeByLocation.removeAll()
- let rootNode = self.makeRootNode(name: SelectLocationGroup.allLocations.description)
+ let rootNode = self.makeRootNode(name: SelectLocationSection.allLocations.description)
for relay in relays {
guard case let .city(countryCode, cityCode) = RelayLocation(dashSeparatedString: relay.location),
@@ -68,22 +66,22 @@ class AllLocationDataSource: LocationDataSourceProtocol {
let relayLocation = RelayLocation.hostname(countryCode, cityCode, relay.hostname)
- for ascendantOrSelf in relayLocation.ascendants + [relayLocation] {
- guard !nodeByLocation.keys.contains(ascendantOrSelf) else {
+ for ancestorOrSelf in relayLocation.ancestors + [relayLocation] {
+ guard !nodeByLocation.keys.contains(ancestorOrSelf) else {
continue
}
// Maintain the `showsChildren` state when transitioning between relay lists
- let wasShowingChildren = nodeByLocation[ascendantOrSelf]?.showsChildren ?? false
+ let wasShowingChildren = nodeByLocation[ancestorOrSelf]?.showsChildren ?? false
let node = createNode(
root: rootNode,
- ascendantOrSelf: ascendantOrSelf,
+ ancestorOrSelf: ancestorOrSelf,
serverLocation: serverLocation,
relay: relay,
wasShowingChildren: wasShowingChildren
)
- nodeByLocation[ascendantOrSelf] = node
+ nodeByLocation[ancestorOrSelf] = node
}
}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/CustomListsDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/CustomListsDataSource.swift
index 25df241bef..897e68b9c3 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/CustomListsDataSource.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/CustomListsDataSource.swift
@@ -15,12 +15,12 @@ class CustomListsDataSource: LocationDataSourceProtocol {
private var locationList = [RelayLocation]()
func search(by text: String) -> [RelayLocation] {
- return []
+ []
}
func reload(
- _ response: MullvadREST.REST.ServerRelaysResponse,
- relays: [MullvadREST.REST.ServerRelay]
+ _ response: REST.ServerRelaysResponse,
+ relays: [REST.ServerRelay]
) -> [RelayLocation] {
locationList
}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift
index 6e98f1f729..5151752d09 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellFactory.swift
@@ -10,7 +10,7 @@ import MullvadTypes
import UIKit
protocol LocationCellEventHandler {
- func collapseCell(for item: LocationCellViewModel)
+ func toggleCell(for item: LocationCellViewModel)
func node(for item: LocationCellViewModel) -> SelectLocationNode?
}
@@ -48,7 +48,7 @@ final class LocationCellFactory: CellFactoryProtocol {
cell.showsCollapseControl = node.isCollapsible
cell.isExpanded = node.showsChildren
cell.didCollapseHandler = { [weak self] _ in
- self?.delegate?.collapseCell(for: item)
+ self?.delegate?.toggleCell(for: item)
}
}
}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift
index c90e504442..2b27f8e0ed 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationCellViewModel.swift
@@ -9,6 +9,6 @@
import MullvadTypes
struct LocationCellViewModel: Hashable {
- let group: SelectLocationGroup
+ let group: SelectLocationSection
let location: RelayLocation
}
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift
index 334c051f81..1a026e54e9 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSource.swift
@@ -11,11 +11,11 @@ import MullvadREST
import MullvadTypes
import UIKit
-final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationGroup, LocationCellViewModel> {
+final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationSection, LocationCellViewModel> {
private var currentSearchString = ""
private let tableView: UITableView
private let locationCellFactory: LocationCellFactory
- private var datasources: [LocationDataSourceProtocol] = []
+ private var dataSources: [LocationDataSourceProtocol] = []
var selectedRelayLocation: LocationCellViewModel?
var didSelectRelayLocation: ((RelayLocation) -> Void)?
@@ -26,12 +26,12 @@ final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationGrou
customLists: LocationDataSourceProtocol
) {
self.tableView = tableView
- self.datasources.append(customLists)
- self.datasources.append(allLocations)
+ self.dataSources.append(customLists)
+ self.dataSources.append(allLocations)
let locationCellFactory = LocationCellFactory(
tableView: tableView,
- reuseIdentifier: SelectLocationGroup.Cell.locationCell.reuseIdentifier
+ reuseIdentifier: SelectLocationSection.Cell.locationCell.reuseIdentifier
)
self.locationCellFactory = locationCellFactory
@@ -51,11 +51,11 @@ final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationGrou
return RelaySelector.relayMatchesFilter(relay, filter: filter)
}
var list: [[LocationCellViewModel]] = []
- for section in 0 ..< datasources.count {
+ for section in 0 ..< dataSources.count {
list.append(
- datasources[section]
+ dataSources[section]
.reload(response, relays: relays)
- .map { LocationCellViewModel(group: SelectLocationGroup.allCases[section], location: $0) }
+ .map { LocationCellViewModel(group: SelectLocationSection.allCases[section], location: $0) }
)
}
filterRelays(by: currentSearchString)
@@ -63,27 +63,27 @@ final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationGrou
func indexPathForSelectedRelay() -> IndexPath? {
selectedRelayLocation.flatMap {
- return indexPath(for: $0)
+ indexPath(for: $0)
}
}
func filterRelays(by searchString: String) {
currentSearchString = searchString
- var list: [[LocationCellViewModel]] = []
- for section in 0 ..< SelectLocationGroup.allCases.count {
- list.append(
- datasources[section]
- .search(by: searchString)
- .map { LocationCellViewModel(group: SelectLocationGroup.allCases[section], location: $0) }
- )
+
+ let list = SelectLocationSection.allCases.enumerated().map { section, group in
+ dataSources[section]
+ .search(by: searchString)
+ .map { LocationCellViewModel(group: group, location: $0) }
}
+
updateDataSnapshot(with: list, reloadExisting: !searchString.isEmpty)
+
if searchString.isEmpty {
- self.setSelectedRelayLocation(self.selectedRelayLocation, animated: false, completion: {
+ setSelectedRelayLocation(selectedRelayLocation, animated: false, completion: {
self.scrollToSelectedRelay()
})
} else {
- self.scrollToTop(animated: false)
+ scrollToTop(animated: false)
}
}
@@ -93,23 +93,23 @@ final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationGrou
animated: Bool = false,
completion: (() -> Void)? = nil
) {
- var snapshot = NSDiffableDataSourceSnapshot<SelectLocationGroup, LocationCellViewModel>()
+ var snapshot = NSDiffableDataSourceSnapshot<SelectLocationSection, LocationCellViewModel>()
- let sections = Array(SelectLocationGroup.allCases)
+ let sections = SelectLocationSection.allCases
snapshot.appendSections(sections)
for (index, section) in sections.enumerated() {
snapshot.appendItems(list[index], toSection: section)
}
if reloadExisting {
- snapshot.reloadSections(SelectLocationGroup.allCases)
+ snapshot.reloadSections(SelectLocationSection.allCases)
}
apply(snapshot, animatingDifferences: animated, completion: completion)
}
private func registerClasses() {
- SelectLocationGroup.allCases.forEach {
+ SelectLocationSection.allCases.forEach {
tableView.register(
$0.cell.reusableViewClass,
forCellReuseIdentifier: $0.cell.reuseIdentifier
@@ -117,66 +117,64 @@ final class LocationDataSource: UITableViewDiffableDataSource<SelectLocationGrou
}
}
- private func item(for indexPath: IndexPath) -> LocationCellViewModel? {
- itemIdentifier(for: indexPath)
- }
-
private func setSelectedRelayLocation(
_ relayLocation: LocationCellViewModel?,
animated: Bool,
completion: (() -> Void)? = nil
) {
selectedRelayLocation = relayLocation
- selectedRelayLocation
- .flatMap { item in
- let group = item.group
- var locationList = snapshot().itemIdentifiers(inSection: group)
- guard !locationList.contains(item) else {
- completion?()
- return
- }
- let selectedLocationTree = item.location.ascendants + [item.location]
+ guard let selectedRelayLocation else { return }
- guard let first = selectedLocationTree.first else { return }
- let topLocation = LocationCellViewModel(group: group, location: first)
+ let group = selectedRelayLocation.group
+ var locationList = snapshot().itemIdentifiers(inSection: group)
+ guard !locationList.contains(selectedRelayLocation) else {
+ completion?()
+ return
+ }
+ let selectedLocationTree = selectedRelayLocation.location.ancestors + [selectedRelayLocation.location]
- guard let indexPath = indexPath(for: topLocation),
- let topNode = node(for: topLocation) else {
- return
- }
+ guard let first = selectedLocationTree.first else { return }
+ let topLocation = LocationCellViewModel(group: group, location: first)
- selectedLocationTree.forEach { location in
- node(for: LocationCellViewModel(group: group, location: location))?.showsChildren = true
- }
+ guard let indexPath = indexPath(for: topLocation),
+ let topNode = node(for: topLocation) else {
+ return
+ }
- locationList.addLocations(
- topNode.flatRelayLocationList().map { LocationCellViewModel(group: group, location: $0) },
- at: indexPath.row + 1
- )
- var list: [[LocationCellViewModel]] = Array(repeating: [], count: datasources.count)
- for index in 0 ..< list.count {
- list[index] = (index == indexPath.section)
- ? locationList
- : snapshot().itemIdentifiers(inSection: SelectLocationGroup.allCases[index])
- }
+ selectedLocationTree.forEach { location in
+ node(for: LocationCellViewModel(group: group, location: location))?.showsChildren = true
+ }
- updateDataSnapshot(
- with: list,
- reloadExisting: true,
- animated: animated,
- completion: completion
- )
- }
+ locationList.addLocations(
+ topNode.flatRelayLocationList().map { LocationCellViewModel(group: group, location: $0) },
+ at: indexPath.row + 1
+ )
+
+ var list: [[LocationCellViewModel]] = Array(repeating: [], count: dataSources.count)
+ for index in 0 ..< list.count {
+ list[index] = (index == indexPath.section)
+ ? locationList
+ : snapshot().itemIdentifiers(inSection: SelectLocationSection.allCases[index])
+ }
+
+ updateDataSnapshot(
+ with: list,
+ reloadExisting: true,
+ animated: animated,
+ completion: completion
+ )
}
}
extension LocationDataSource: UITableViewDelegate {
func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
- item(for: indexPath).flatMap { node(for: $0) }?.isActive ?? false
+ guard let item = itemIdentifier(for: indexPath) else { return false }
+ return node(for: item)?.isActive ?? false
}
func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: IndexPath) -> Int {
- item(for: indexPath).flatMap { node(for: $0) }?.indentationLevel ?? 0
+ guard let item = itemIdentifier(for: indexPath) else { return 0 }
+ return node(for: item)?.indentationLevel ?? 0
}
func tableView(
@@ -184,18 +182,20 @@ extension LocationDataSource: UITableViewDelegate {
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath
) {
- if let item = item(for: indexPath),
+ if let item = itemIdentifier(for: indexPath),
item == selectedRelayLocation {
cell.setSelected(true, animated: false)
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- item(for: indexPath)
+ itemIdentifier(for: indexPath)
.flatMap { item in
guard item.location != selectedRelayLocation?.location else { return }
didSelectRelayLocation?(item.location)
+
setSelectedRelayLocation(item, animated: false)
+
indexPathForSelectedRelay().flatMap {
let cell = tableView.cellForRow(at: $0)
cell?.setSelected(false, animated: false)
@@ -205,43 +205,48 @@ extension LocationDataSource: UITableViewDelegate {
}
extension LocationDataSource: LocationCellEventHandler {
- func collapseCell(for item: LocationCellViewModel) {
+ func toggleCell(for item: LocationCellViewModel) {
indexPath(for: item).flatMap { indexPath in
- guard let node = self.node(for: item),
- let cell = tableView.cellForRow(at: indexPath) else { return }
+ guard let node = node(for: item), let cell = tableView.cellForRow(at: indexPath) else { return }
+
let isExpanded = node.showsChildren
- let group = SelectLocationGroup.allCases[indexPath.section]
+ let group = SelectLocationSection.allCases[indexPath.section]
+
node.showsChildren = !isExpanded
locationCellFactory.configureCell(
cell,
item: LocationCellViewModel(group: group, location: node.location),
indexPath: indexPath
)
+
var locationList = snapshot().itemIdentifiers(inSection: group)
let locationsToEdit = node.flatRelayLocationList().map { LocationCellViewModel(group: group, location: $0) }
+
if !isExpanded {
locationList.addLocations(locationsToEdit, at: indexPath.row + 1)
} else {
locationsToEdit.forEach { self.node(for: $0)?.showsChildren = false }
locationList.removeLocations(locationsToEdit)
}
- var list: [[LocationCellViewModel]] = Array(repeating: [], count: datasources.count)
+
+ var list: [[LocationCellViewModel]] = Array(repeating: [], count: dataSources.count)
for index in 0 ..< list.count {
list[index] = (index == indexPath.section)
? locationList
- : snapshot().itemIdentifiers(inSection: SelectLocationGroup.allCases[index])
+ : snapshot().itemIdentifiers(inSection: SelectLocationSection.allCases[index])
}
- self.updateDataSnapshot(with: list, completion: {
+
+ updateDataSnapshot(with: list, completion: {
self.scroll(to: item, animated: true)
})
}
}
func node(for item: LocationCellViewModel) -> SelectLocationNode? {
- guard let sectionIndex = SelectLocationGroup.allCases.firstIndex(of: item.group) else {
+ guard let sectionIndex = SelectLocationSection.allCases.firstIndex(of: item.group) else {
return nil
}
- return datasources[sectionIndex].nodeByLocation[item.location]
+ return dataSources[sectionIndex].nodeByLocation[item.location]
}
}
@@ -256,7 +261,7 @@ extension LocationDataSource {
} else {
node.children.last.flatMap { last in
if let lastInsertedIndexPath = self.indexPath(for: LocationCellViewModel(
- group: SelectLocationGroup.allCases[indexPath.section],
+ group: SelectLocationSection.allCases[indexPath.section],
location: last.location
)),
let lastVisibleIndexPath = visibleIndexPaths.last,
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift
index f00cdf3408..6511f4bd44 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/LocationDataSourceProtocol.swift
@@ -29,18 +29,18 @@ extension LocationDataSourceProtocol {
func createNode(
root: SelectLocationNode,
- ascendantOrSelf: RelayLocation,
+ ancestorOrSelf: RelayLocation,
serverLocation: REST.ServerLocation,
relay: REST.ServerRelay,
wasShowingChildren: Bool
) -> SelectLocationNode {
let node: SelectLocationNode
- switch ascendantOrSelf {
+ switch ancestorOrSelf {
case .country:
node = SelectLocationNode(
nodeType: .country,
- location: ascendantOrSelf,
+ location: ancestorOrSelf,
displayName: serverLocation.country,
showsChildren: wasShowingChildren
)
@@ -48,7 +48,7 @@ extension LocationDataSourceProtocol {
case let .city(countryCode, _):
node = SelectLocationNode(
nodeType: .city,
- location: ascendantOrSelf,
+ location: ancestorOrSelf,
displayName: serverLocation.city,
showsChildren: wasShowingChildren
)
@@ -57,7 +57,7 @@ extension LocationDataSourceProtocol {
case let .hostname(countryCode, cityCode, _):
node = SelectLocationNode(
nodeType: .relay,
- location: ascendantOrSelf,
+ location: ancestorOrSelf,
displayName: relay.hostname,
isActive: relay.active
)
diff --git a/ios/MullvadVPN/View controllers/SelectLocation/SelectLocationGroup.swift b/ios/MullvadVPN/View controllers/SelectLocation/SelectLocationSection.swift
index 1d5b66dcf2..2e0984c809 100644
--- a/ios/MullvadVPN/View controllers/SelectLocation/SelectLocationGroup.swift
+++ b/ios/MullvadVPN/View controllers/SelectLocation/SelectLocationSection.swift
@@ -7,7 +7,7 @@
//
import Foundation
-enum SelectLocationGroup: Hashable, CustomStringConvertible, CaseIterable {
+enum SelectLocationSection: Hashable, CustomStringConvertible, CaseIterable {
case customLists
case allLocations
@@ -32,7 +32,7 @@ enum SelectLocationGroup: Hashable, CustomStringConvertible, CaseIterable {
Cell.locationCell
}
- static var allCases: [SelectLocationGroup] {
+ static var allCases: [SelectLocationSection] {
#if DEBUG
return [.customLists, .allLocations]
#else
@@ -41,7 +41,7 @@ enum SelectLocationGroup: Hashable, CustomStringConvertible, CaseIterable {
}
}
-extension SelectLocationGroup {
+extension SelectLocationSection {
enum Cell: String, CaseIterable {
case locationCell