summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormojganii <mojgan.jelodar@codic.se>2024-03-15 12:04:21 +0100
committerBug Magnet <marco.nikic@mullvad.net>2024-04-05 09:34:32 +0200
commit711ffc84de5f3f88ca9cc4344494d1c47e39d0d6 (patch)
tree3cc774dfd62e2f4d1bcc252244faa8087b2e0c04
parentad89a992ba49996eee751b7baa257bab0daa0517 (diff)
downloadmullvadvpn-711ffc84de5f3f88ca9cc4344494d1c47e39d0d6.tar.xz
mullvadvpn-711ffc84de5f3f88ca9cc4344494d1c47e39d0d6.zip
Implement addLocationCell
-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/Coordinators/CustomLists/AddLocationCell.swift204
-rw-r--r--ios/MullvadVPN/Coordinators/CustomLists/AddLocationCellViewModel.swift15
4 files changed, 227 insertions, 22 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 41411f85d4..f14b01f8ca 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -825,6 +825,8 @@
F0164ED12B4F2DCB0020268D /* AccessMethodIterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0164ED02B4F2DCB0020268D /* AccessMethodIterator.swift */; };
F028A56A2A34D4E700C0CAA3 /* RedeemVoucherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028A5692A34D4E700C0CAA3 /* RedeemVoucherViewController.swift */; };
F028A56C2A34D8E600C0CAA3 /* AddCreditSucceededViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028A56B2A34D8E600C0CAA3 /* AddCreditSucceededViewController.swift */; };
+ F02F41A42B9723AF00625A4F /* AddLocationCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419E2B9723AF00625A4F /* AddLocationCellViewModel.swift */; };
+ F02F41A52B9723AF00625A4F /* AddLocationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02F419F2B9723AF00625A4F /* AddLocationCell.swift */; };
F03580252A13842C00E5DAFD /* IncreasedHitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */; };
F04413612BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */; };
F04413622BA45CE30018A6EE /* CustomListLocationNodeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */; };
@@ -1981,6 +1983,8 @@
F0164ED02B4F2DCB0020268D /* AccessMethodIterator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodIterator.swift; sourceTree = "<group>"; };
F028A5692A34D4E700C0CAA3 /* RedeemVoucherViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedeemVoucherViewController.swift; sourceTree = "<group>"; };
F028A56B2A34D8E600C0CAA3 /* AddCreditSucceededViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddCreditSucceededViewController.swift; sourceTree = "<group>"; };
+ F02F419E2B9723AF00625A4F /* AddLocationCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationCellViewModel.swift; sourceTree = "<group>"; };
+ F02F419F2B9723AF00625A4F /* AddLocationCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddLocationCell.swift; sourceTree = "<group>"; };
F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncreasedHitButton.swift; sourceTree = "<group>"; };
F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomListLocationNodeBuilder.swift; sourceTree = "<group>"; };
F04F95A02B21D24400431E08 /* shadowsocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shadowsocks.h; sourceTree = "<group>"; };
@@ -3508,6 +3512,8 @@
isa = PBXGroup;
children = (
7A6389D72B7E3BD6008E77E1 /* AddCustomListCoordinator.swift */,
+ F02F419F2B9723AF00625A4F /* AddLocationCell.swift */,
+ F02F419E2B9723AF00625A4F /* AddLocationCellViewModel.swift */,
7A6389D22B7E3BD6008E77E1 /* CustomListCellConfiguration.swift */,
7A6389D42B7E3BD6008E77E1 /* CustomListDataSourceConfiguration.swift */,
7A6389DA2B7E3BD6008E77E1 /* CustomListInteractor.swift */,
@@ -5179,6 +5185,7 @@
582BB1B1229569620055B6EF /* UINavigationBar+Appearance.swift in Sources */,
7A9FA1442A2E3FE5000B728D /* CheckableSettingsCell.swift in Sources */,
58ACF6492655365700ACE4B7 /* VPNSettingsViewController.swift in Sources */,
+ F02F41A52B9723AF00625A4F /* AddLocationCell.swift in Sources */,
7ABE318D2A1CDD4500DF4963 /* UIFont+Weight.swift in Sources */,
58C774BE29A7A249003A1A56 /* CustomNavigationController.swift in Sources */,
E1FD0DF528AA7CE400299DB4 /* StatusActivityView.swift in Sources */,
@@ -5433,6 +5440,7 @@
7A6389DB2B7E3BD6008E77E1 /* CustomListCellConfiguration.swift in Sources */,
F09A297C2A9F8A9B00EA3B6F /* VoucherTextField.swift in Sources */,
7A5869B72B56B41500640D27 /* IPOverrideTextViewController.swift in Sources */,
+ F02F41A42B9723AF00625A4F /* AddLocationCellViewModel.swift in Sources */,
58ACF64B26553C3F00ACE4B7 /* SettingsSwitchCell.swift in Sources */,
7AF9BE952A40461100DBFEDB /* RelayFilterView.swift in Sources */,
7A09C98129D99215000C2CAC /* String+FuzzyMatch.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
deleted file mode 100644
index 02691892fe..0000000000
--- a/ios/MullvadVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "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/Coordinators/CustomLists/AddLocationCell.swift b/ios/MullvadVPN/Coordinators/CustomLists/AddLocationCell.swift
new file mode 100644
index 0000000000..e0094f0a9a
--- /dev/null
+++ b/ios/MullvadVPN/Coordinators/CustomLists/AddLocationCell.swift
@@ -0,0 +1,204 @@
+//
+// AddLocationCell.swift
+// MullvadVPN
+//
+// Created by Mojgan on 2024-02-29.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import UIKit
+
+protocol AddLocationCellDelegate: AnyObject {
+ func toggleExpanding(cell: AddLocationCell)
+ func toggleSelection(cell: AddLocationCell)
+}
+
+class AddLocationCell: UITableViewCell {
+ weak var delegate: AddLocationCellDelegate?
+
+ private let chevronDown = UIImage(resource: .iconChevronDown)
+ private let chevronUp = UIImage(resource: .iconChevronUp)
+
+ private let locationLabel: UILabel = {
+ let label = UILabel()
+ label.font = UIFont.systemFont(ofSize: 17)
+ label.textColor = .white
+ label.numberOfLines = .zero
+ label.lineBreakStrategy = []
+ return label
+ }()
+
+ private let checkboxButton: UIButton = {
+ let button = UIButton()
+ button.setImage(UIImage(systemName: "checkmark.square.fill"), for: .selected)
+ button.setImage(UIImage(systemName: "square"), for: .normal)
+ button.tintColor = .white
+ return button
+ }()
+
+ private let collapseButton: UIButton = {
+ let button = UIButton(type: .custom)
+ button.accessibilityIdentifier = .collapseButton
+ button.isAccessibilityElement = false
+ button.tintColor = .white
+ return button
+ }()
+
+ var isExpanded = false {
+ didSet {
+ updateCollapseImage()
+ updateAccessibilityCustomActions()
+ }
+ }
+
+ var showsCollapseControl = false {
+ didSet {
+ collapseButton.isHidden = !showsCollapseControl
+ updateAccessibilityCustomActions()
+ }
+ }
+
+ override var indentationLevel: Int {
+ didSet {
+ updateBackgroundColor()
+ setLayoutMargins()
+ }
+ }
+
+ override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+ super.init(style: style, reuseIdentifier: reuseIdentifier)
+ setupCell()
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ private func setLayoutMargins() {
+ let indentation = CGFloat(indentationLevel) * indentationWidth
+
+ var contentMargins = UIMetrics.locationCellLayoutMargins
+ contentMargins.leading += indentation
+
+ contentView.directionalLayoutMargins = contentMargins
+ }
+
+ private func setupCell() {
+ indentationWidth = UIMetrics.TableView.cellIndentationWidth
+
+ backgroundColor = .clear
+ contentView.backgroundColor = .clear
+
+ backgroundView = UIView()
+
+ collapseButton.addTarget(self, action: #selector(handleCollapseButton(_:)), for: .touchUpInside)
+ checkboxButton.addTarget(self, action: #selector(toggleCheckboxButton(_:)), for: .touchUpInside)
+
+ contentView.addConstrainedSubviews([checkboxButton, locationLabel, collapseButton]) {
+ checkboxButton.pinEdgeToSuperviewMargin(.leading(.zero))
+ checkboxButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
+ checkboxButton.widthAnchor
+ .constraint(
+ equalToConstant: 44.0
+ )
+ checkboxButton.heightAnchor.constraint(equalTo: checkboxButton.widthAnchor, multiplier: 1, constant: 0)
+
+ locationLabel.leadingAnchor.constraint(
+ equalTo: checkboxButton.trailingAnchor,
+ constant: 12
+ )
+
+ locationLabel.trailingAnchor.constraint(lessThanOrEqualTo: collapseButton.leadingAnchor)
+ .withPriority(.defaultHigh)
+ locationLabel.pinEdgesToSuperviewMargins(PinnableEdges([.top(.zero), .bottom(.zero)]))
+
+ collapseButton.widthAnchor
+ .constraint(
+ equalToConstant: UIMetrics.contentLayoutMargins.leading + UIMetrics
+ .contentLayoutMargins.trailing + 24.0
+ )
+ collapseButton.pinEdgesToSuperviewMargins(.all().excluding(.leading))
+ }
+
+ updateCollapseImage()
+ updateAccessibilityCustomActions()
+ updateBackgroundColor()
+ setLayoutMargins()
+ }
+
+ private func updateBackgroundColor() {
+ backgroundView?.backgroundColor = backgroundColorForIdentationLevel()
+ }
+
+ private func backgroundColorForIdentationLevel() -> UIColor {
+ switch indentationLevel {
+ case 1:
+ return UIColor.Cell.Background.indentationLevelOne
+ case 2:
+ return UIColor.Cell.Background.indentationLevelTwo
+ case 3:
+ return UIColor.Cell.Background.indentationLevelThree
+ default:
+ return UIColor.Cell.Background.normal
+ }
+ }
+
+ private func updateCollapseImage() {
+ let image = isExpanded ? chevronUp : chevronDown
+ collapseButton.setImage(image, for: .normal)
+ }
+
+ private func updateAccessibilityCustomActions() {
+ if showsCollapseControl {
+ let actionName = isExpanded
+ ? NSLocalizedString(
+ "ADD_LOCATIONS_COLLAPSE_ACCESSIBILITY_ACTION",
+ tableName: "AddLocationsLocation",
+ value: "Collapse location",
+ comment: ""
+ )
+ : NSLocalizedString(
+ "ADD_LOCATIONS_EXPAND_ACCESSIBILITY_ACTION",
+ tableName: "AddLocationsLocation",
+ value: "Expand location",
+ comment: ""
+ )
+
+ accessibilityCustomActions = [
+ UIAccessibilityCustomAction(
+ name: actionName,
+ target: self,
+ selector: #selector(toggleCollapseAccessibilityAction)
+ ),
+ ]
+ } else {
+ accessibilityCustomActions = nil
+ }
+ }
+
+ // MARK: - actions
+
+ @objc private func handleCollapseButton(_ sender: UIControl) {
+ delegate?.toggleExpanding(cell: self)
+ }
+
+ @objc private func toggleCollapseAccessibilityAction() -> Bool {
+ delegate?.toggleExpanding(cell: self)
+ return true
+ }
+
+ @objc private func toggleCheckboxButton(_ sender: UIControl) {
+ delegate?.toggleSelection(cell: self)
+ }
+}
+
+extension AddLocationCell {
+ func configure(item: AddLocationCellViewModel) {
+ accessibilityIdentifier = item.node.name
+ locationLabel.text = item.node.name
+ showsCollapseControl = !item.node.children.isEmpty
+ isExpanded = item.node.showsChildren
+ checkboxButton.isSelected = item.isSelected
+ checkboxButton.tintColor = item.isSelected ? .successColor : .white
+ }
+}
diff --git a/ios/MullvadVPN/Coordinators/CustomLists/AddLocationCellViewModel.swift b/ios/MullvadVPN/Coordinators/CustomLists/AddLocationCellViewModel.swift
new file mode 100644
index 0000000000..ffc06aea74
--- /dev/null
+++ b/ios/MullvadVPN/Coordinators/CustomLists/AddLocationCellViewModel.swift
@@ -0,0 +1,15 @@
+//
+// AddLocationCellViewModel.swift
+// MullvadVPN
+//
+// Created by Mojgan on 2024-03-04.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+struct AddLocationCellViewModel: Hashable {
+ let node: LocationNode
+ var indentationLevel = 0
+ var isSelected: Bool
+}