Skip to content

Commit 2a6890c

Browse files
committed
Add locations to a custom list
1 parent 7a8028d commit 2a6890c

16 files changed

+719
-106
lines changed

ios/MullvadVPN.xcodeproj/project.pbxproj

+16
Original file line numberDiff line numberDiff line change
@@ -810,13 +810,17 @@
810810
E1187ABD289BBB850024E748 /* OutOfTimeContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1187ABB289BBB850024E748 /* OutOfTimeContentView.swift */; };
811811
E158B360285381C60002F069 /* String+AccountFormatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = E158B35F285381C60002F069 /* String+AccountFormatting.swift */; };
812812
E1FD0DF528AA7CE400299DB4 /* StatusActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FD0DF428AA7CE400299DB4 /* StatusActivityView.swift */; };
813+
F006CCFC2B99CC8400C6C2AC /* EditLocationsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F006CCFB2B99CC8400C6C2AC /* EditLocationsCoordinator.swift */; };
813814
F0164EBA2B4456D30020268D /* AccessMethodRepositoryStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0164EB92B4456D30020268D /* AccessMethodRepositoryStub.swift */; };
814815
F0164EBC2B482E430020268D /* AppStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0164EBB2B482E430020268D /* AppStorage.swift */; };
815816
F0164EBE2B4BFF940020268D /* ShadowsocksLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0164EBD2B4BFF940020268D /* ShadowsocksLoader.swift */; };
816817
F0164EC32B4C49D30020268D /* ShadowsocksLoaderStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0164EC22B4C49D30020268D /* ShadowsocksLoaderStub.swift */; };
817818
F0164ED12B4F2DCB0020268D /* AccessMethodIterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0164ED02B4F2DCB0020268D /* AccessMethodIterator.swift */; };
818819
F028A56A2A34D4E700C0CAA3 /* RedeemVoucherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028A5692A34D4E700C0CAA3 /* RedeemVoucherViewController.swift */; };
819820
F028A56C2A34D8E600C0CAA3 /* AddCreditSucceededViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028A56B2A34D8E600C0CAA3 /* AddCreditSucceededViewController.swift */; };
821+
F02F41A02B9723AF00625A4F /* AddLocationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419A2B9723AE00625A4F /* AddLocationsViewController.swift */; };
822+
F02F41A12B9723AF00625A4F /* AddLocationsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419B2B9723AE00625A4F /* AddLocationsDataSource.swift */; };
823+
F02F41A22B9723AF00625A4F /* AddLocationsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419C2B9723AF00625A4F /* AddLocationsCoordinator.swift */; };
820824
F02F41A42B9723AF00625A4F /* AddLocationCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419E2B9723AF00625A4F /* AddLocationCellViewModel.swift */; };
821825
F02F41A52B9723AF00625A4F /* AddLocationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419F2B9723AF00625A4F /* AddLocationCell.swift */; };
822826
F03580252A13842C00E5DAFD /* IncreasedHitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */; };
@@ -1960,13 +1964,17 @@
19601964
E1187ABB289BBB850024E748 /* OutOfTimeContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutOfTimeContentView.swift; sourceTree = "<group>"; };
19611965
E158B35F285381C60002F069 /* String+AccountFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+AccountFormatting.swift"; sourceTree = "<group>"; };
19621966
E1FD0DF428AA7CE400299DB4 /* StatusActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusActivityView.swift; sourceTree = "<group>"; };
1967+
F006CCFB2B99CC8400C6C2AC /* EditLocationsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditLocationsCoordinator.swift; sourceTree = "<group>"; };
19631968
F0164EB92B4456D30020268D /* AccessMethodRepositoryStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodRepositoryStub.swift; sourceTree = "<group>"; };
19641969
F0164EBB2B482E430020268D /* AppStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStorage.swift; sourceTree = "<group>"; };
19651970
F0164EBD2B4BFF940020268D /* ShadowsocksLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksLoader.swift; sourceTree = "<group>"; };
19661971
F0164EC22B4C49D30020268D /* ShadowsocksLoaderStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksLoaderStub.swift; sourceTree = "<group>"; };
19671972
F0164ED02B4F2DCB0020268D /* AccessMethodIterator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodIterator.swift; sourceTree = "<group>"; };
19681973
F028A5692A34D4E700C0CAA3 /* RedeemVoucherViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedeemVoucherViewController.swift; sourceTree = "<group>"; };
19691974
F028A56B2A34D8E600C0CAA3 /* AddCreditSucceededViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddCreditSucceededViewController.swift; sourceTree = "<group>"; };
1975+
F02F419A2B9723AE00625A4F /* AddLocationsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationsViewController.swift; sourceTree = "<group>"; };
1976+
F02F419B2B9723AE00625A4F /* AddLocationsDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationsDataSource.swift; sourceTree = "<group>"; };
1977+
F02F419C2B9723AF00625A4F /* AddLocationsCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationsCoordinator.swift; sourceTree = "<group>"; };
19701978
F02F419E2B9723AF00625A4F /* AddLocationCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationCellViewModel.swift; sourceTree = "<group>"; };
19711979
F02F419F2B9723AF00625A4F /* AddLocationCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationCell.swift; sourceTree = "<group>"; };
19721980
F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncreasedHitButton.swift; sourceTree = "<group>"; };
@@ -3498,6 +3506,9 @@
34983506
7A6389D72B7E3BD6008E77E1 /* AddCustomListCoordinator.swift */,
34993507
F02F419F2B9723AF00625A4F /* AddLocationCell.swift */,
35003508
F02F419E2B9723AF00625A4F /* AddLocationCellViewModel.swift */,
3509+
F02F419C2B9723AF00625A4F /* AddLocationsCoordinator.swift */,
3510+
F02F419B2B9723AE00625A4F /* AddLocationsDataSource.swift */,
3511+
F02F419A2B9723AE00625A4F /* AddLocationsViewController.swift */,
35013512
7A6389D22B7E3BD6008E77E1 /* CustomListCellConfiguration.swift */,
35023513
7A6389D42B7E3BD6008E77E1 /* CustomListDataSourceConfiguration.swift */,
35033514
7A6389DA2B7E3BD6008E77E1 /* CustomListInteractor.swift */,
@@ -3507,6 +3518,7 @@
35073518
7A6389E62B7E42BE008E77E1 /* CustomListViewController.swift */,
35083519
7A6389D32B7E3BD6008E77E1 /* CustomListViewModel.swift */,
35093520
7A6389E42B7E4247008E77E1 /* EditCustomListCoordinator.swift */,
3521+
F006CCFB2B99CC8400C6C2AC /* EditLocationsCoordinator.swift */,
35103522
7AB2B66F2BA1EB8C00B03E3B /* ListCustomListCoordinator.swift */,
35113523
7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */,
35123524
);
@@ -5208,6 +5220,7 @@
52085220
58EE2E3B272FF814003BFF93 /* SettingsDataSourceDelegate.swift in Sources */,
52095221
5823FA5426CE49F700283BF8 /* TunnelObserver.swift in Sources */,
52105222
5888AD87227B17950051EB06 /* LocationViewController.swift in Sources */,
5223+
F006CCFC2B99CC8400C6C2AC /* EditLocationsCoordinator.swift in Sources */,
52115224
58293FB3251241B4005D0BB5 /* CustomTextView.swift in Sources */,
52125225
586A950E290125F3007BAF2B /* ProductsRequestOperation.swift in Sources */,
52135226
7AF9BE902A39F26000DBFEDB /* Collection+Sorting.swift in Sources */,
@@ -5285,6 +5298,7 @@
52855298
5878A26F2907E7E00096FC88 /* ProblemReportInteractor.swift in Sources */,
52865299
7AB4CCBB2B691BBB006037F5 /* IPOverrideInteractor.swift in Sources */,
52875300
7A3353912AAA014400F0A71C /* SimulatorVPNConnection.swift in Sources */,
5301+
F02F41A22B9723AF00625A4F /* AddLocationsCoordinator.swift in Sources */,
52885302
F028A56A2A34D4E700C0CAA3 /* RedeemVoucherViewController.swift in Sources */,
52895303
7A5869C52B5A899C00640D27 /* MethodSettingsCellConfiguration.swift in Sources */,
52905304
58E11188292FA11F009FCA84 /* SettingsMigrationUIHandler.swift in Sources */,
@@ -5419,11 +5433,13 @@
54195433
5827B0C52B14D3E800CCBBA1 /* NSDiffableDataSourceSnapshot+Reconfigure.swift in Sources */,
54205434
58A8EE5E2976DB00009C0F8D /* StorePaymentManagerError+Display.swift in Sources */,
54215435
58A8EE5A2976BFBB009C0F8D /* SKError+Localized.swift in Sources */,
5436+
F02F41A12B9723AF00625A4F /* AddLocationsDataSource.swift in Sources */,
54225437
58EFC76E2AFB3BDA00E9F4CB /* ListAccessMethodCoordinator.swift in Sources */,
54235438
5827B0B92B14A1C700CCBBA1 /* MethodTestingStatusCellContentConfiguration.swift in Sources */,
54245439
7A42DEC92A05164100B209BE /* SettingsInputCell.swift in Sources */,
54255440
5803B4B22940A48700C23744 /* TunnelStore.swift in Sources */,
54265441
586A950F29012BEE007BAF2B /* AddressCacheTracker.swift in Sources */,
5442+
F02F41A02B9723AF00625A4F /* AddLocationsViewController.swift in Sources */,
54275443
587B753D2666468F00DEF7E9 /* NotificationController.swift in Sources */,
54285444
);
54295445
runOnlyForDeploymentPostprocessing = 0;

ios/MullvadVPN/Classes/AccessbilityIdentifier.swift

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public enum AccessibilityIdentifier: String {
5252

5353
// Views
5454
case accountView
55+
case addLocationsView
5556
case alertContainerView
5657
case alertTitle
5758
case changeLogAlert

ios/MullvadVPN/Coordinators/CustomLists/AddCustomListCoordinator.swift

+35-11
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,28 @@ import UIKit
1414
class AddCustomListCoordinator: Coordinator, Presentable, Presenting {
1515
let navigationController: UINavigationController
1616
let interactor: CustomListInteractorProtocol
17+
let nodes: [LocationNode]
18+
let subject = CurrentValueSubject<CustomListViewModel, Never>(
19+
CustomListViewModel(id: UUID(), name: "", locations: [], tableSections: [.name, .addLocations])
20+
)
1721

1822
var presentedViewController: UIViewController {
1923
navigationController
2024
}
2125

22-
var didFinish: (() -> Void)?
26+
var didFinish: ((AddCustomListCoordinator) -> Void)?
2327

2428
init(
2529
navigationController: UINavigationController,
26-
interactor: CustomListInteractorProtocol
30+
interactor: CustomListInteractorProtocol,
31+
nodes: [LocationNode]
2732
) {
2833
self.navigationController = navigationController
2934
self.interactor = interactor
35+
self.nodes = nodes
3036
}
3137

3238
func start() {
33-
let subject = CurrentValueSubject<CustomListViewModel, Never>(
34-
CustomListViewModel(id: UUID(), name: "", locations: [], tableSections: [.name, .addLocations])
35-
)
36-
3739
let controller = CustomListViewController(
3840
interactor: interactor,
3941
subject: subject,
@@ -57,8 +59,11 @@ class AddCustomListCoordinator: Coordinator, Presentable, Presenting {
5759

5860
controller.navigationItem.leftBarButtonItem = UIBarButtonItem(
5961
systemItem: .cancel,
60-
primaryAction: UIAction(handler: { _ in
61-
self.didFinish?()
62+
primaryAction: UIAction(handler: { [weak self] _ in
63+
guard let self else {
64+
return
65+
}
66+
didFinish?(self)
6267
})
6368
)
6469

@@ -68,14 +73,33 @@ class AddCustomListCoordinator: Coordinator, Presentable, Presenting {
6873

6974
extension AddCustomListCoordinator: CustomListViewControllerDelegate {
7075
func customListDidSave(_ list: CustomList) {
71-
didFinish?()
76+
didFinish?(self)
7277
}
7378

7479
func customListDidDelete(_ list: CustomList) {
7580
// No op.
7681
}
7782

78-
func showLocations() {
79-
// TODO: Show view controller for locations.
83+
func showLocations(_ list: CustomList) {
84+
let coordinator = AddLocationsCoordinator(
85+
navigationController: navigationController,
86+
nodes: nodes,
87+
customList: list
88+
)
89+
90+
coordinator.didFinish = { [weak self] locationsCoordinator, customList in
91+
guard let self else { return }
92+
subject.send(CustomListViewModel(
93+
id: customList.id,
94+
name: customList.name,
95+
locations: customList.locations,
96+
tableSections: subject.value.tableSections
97+
))
98+
locationsCoordinator.removeFromParent()
99+
}
100+
101+
coordinator.start()
102+
103+
addChild(coordinator)
80104
}
81105
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// AddLocationsCoordinator.swift
3+
// MullvadVPN
4+
//
5+
// Created by Mojgan on 2024-03-04.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import Combine
10+
import Foundation
11+
import MullvadSettings
12+
import MullvadTypes
13+
import Routing
14+
import UIKit
15+
16+
class AddLocationsCoordinator: Coordinator, Presentable, Presenting {
17+
private let navigationController: UINavigationController
18+
private let nodes: [LocationNode]
19+
private var customList: CustomList
20+
21+
var didFinish: ((AddLocationsCoordinator, CustomList) -> Void)?
22+
23+
var presentedViewController: UIViewController {
24+
navigationController
25+
}
26+
27+
init(
28+
navigationController: UINavigationController,
29+
nodes: [LocationNode],
30+
customList: CustomList
31+
) {
32+
self.navigationController = navigationController
33+
self.nodes = nodes
34+
self.customList = customList
35+
}
36+
37+
func start() {
38+
let controller = AddLocationsViewController(
39+
allLocationsNodes: nodes,
40+
customList: customList
41+
)
42+
controller.delegate = self
43+
44+
controller.navigationItem.title = NSLocalizedString(
45+
"ADD_LOCATIONS_NAVIGATION_TITLE",
46+
tableName: "AddLocations",
47+
value: "Add locations",
48+
comment: ""
49+
)
50+
51+
navigationController.pushViewController(controller, animated: true)
52+
}
53+
}
54+
55+
extension AddLocationsCoordinator: AddLocationsViewControllerDelegate {
56+
func didUpdateSelectedLocations(locations: [RelayLocation]) {
57+
customList.locations = locations
58+
}
59+
60+
func didBack() {
61+
didFinish?(self, customList)
62+
}
63+
}

0 commit comments

Comments
 (0)