Tunnel edit, Tunnel view model: UI for providing On-Demand activation options
This commit is contained in:
parent
049e9f0b05
commit
151ad9de84
|
@ -372,6 +372,7 @@ class TunnelViewModel {
|
|||
|
||||
var interfaceData: InterfaceData
|
||||
var peersData: [PeerData]
|
||||
var activationType: ActivationType
|
||||
|
||||
init(tunnelConfiguration: TunnelConfiguration?) {
|
||||
let interfaceData: InterfaceData = InterfaceData()
|
||||
|
@ -391,6 +392,20 @@ class TunnelViewModel {
|
|||
}
|
||||
self.interfaceData = interfaceData
|
||||
self.peersData = peersData
|
||||
self.activationType = tunnelConfiguration?.activationType ?? .activateManually
|
||||
}
|
||||
|
||||
func activateOnDemandOptionText(for activationType: ActivationType) -> String {
|
||||
switch (activationType) {
|
||||
case .activateManually:
|
||||
return ""
|
||||
case .useOnDemandOverWifiAndCellular:
|
||||
return "Over wifi and cellular"
|
||||
case .useOnDemandOverWifiOnly:
|
||||
return "Over wifi only"
|
||||
case .useOnDemandOverCellularOnly:
|
||||
return "Over cellular only"
|
||||
}
|
||||
}
|
||||
|
||||
func appendEmptyPeer() {
|
||||
|
@ -442,6 +457,7 @@ class TunnelViewModel {
|
|||
}
|
||||
|
||||
let tunnelConfiguration = TunnelConfiguration(interface: interfaceConfiguration, peers: peerConfigurations)
|
||||
tunnelConfiguration.activationType = self.activationType
|
||||
return .saved(tunnelConfiguration)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,12 @@ class TunnelEditTableViewController: UITableViewController {
|
|||
.deletePeer
|
||||
]
|
||||
|
||||
let activateOnDemandOptions: [ActivationType] = [
|
||||
.useOnDemandOverWifiAndCellular,
|
||||
.useOnDemandOverWifiOnly,
|
||||
.useOnDemandOverCellularOnly
|
||||
]
|
||||
|
||||
let tunnelsManager: TunnelsManager
|
||||
let tunnel: TunnelContainer?
|
||||
let tunnelViewModel: TunnelViewModel
|
||||
|
@ -58,12 +64,12 @@ class TunnelEditTableViewController: UITableViewController {
|
|||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelTapped))
|
||||
|
||||
self.tableView.rowHeight = 44
|
||||
self.tableView.allowsSelection = false
|
||||
|
||||
self.tableView.register(TunnelEditTableViewKeyValueCell.self, forCellReuseIdentifier: TunnelEditTableViewKeyValueCell.id)
|
||||
self.tableView.register(TunnelEditTableViewReadOnlyKeyValueCell.self, forCellReuseIdentifier: TunnelEditTableViewReadOnlyKeyValueCell.id)
|
||||
self.tableView.register(TunnelEditTableViewButtonCell.self, forCellReuseIdentifier: TunnelEditTableViewButtonCell.id)
|
||||
self.tableView.register(TunnelEditTableViewSwitchCell.self, forCellReuseIdentifier: TunnelEditTableViewSwitchCell.id)
|
||||
self.tableView.register(TunnelEditTableViewSelectionListCell.self, forCellReuseIdentifier: TunnelEditTableViewSelectionListCell.id)
|
||||
}
|
||||
|
||||
@objc func saveTapped() {
|
||||
|
@ -122,7 +128,7 @@ extension TunnelEditTableViewController {
|
|||
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||
let numberOfPeerSections = tunnelViewModel.peersData.count
|
||||
|
||||
return numberOfInterfaceSections + numberOfPeerSections + 1
|
||||
return numberOfInterfaceSections + numberOfPeerSections + 1 /* Add Peer */ + 1 /* On-Demand */
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
@ -138,9 +144,16 @@ extension TunnelEditTableViewController {
|
|||
let peerData = tunnelViewModel.peersData[peerIndex]
|
||||
let peerFieldsToShow = peerData.shouldAllowExcludePrivateIPsControl ? peerFields : peerFields.filter { $0 != .excludePrivateIPs }
|
||||
return peerFieldsToShow.count
|
||||
} else {
|
||||
} else if (section < (numberOfInterfaceSections + numberOfPeerSections + 1)) {
|
||||
// Add peer
|
||||
return 1
|
||||
} else {
|
||||
// On-Demand Rules
|
||||
if (tunnelViewModel.activationType == .activateManually) {
|
||||
return 1
|
||||
} else {
|
||||
return 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,9 +167,12 @@ extension TunnelEditTableViewController {
|
|||
} else if ((numberOfPeerSections > 0) && (section < (numberOfInterfaceSections + numberOfPeerSections))) {
|
||||
// Peer
|
||||
return "Peer"
|
||||
} else {
|
||||
} else if (section == (numberOfInterfaceSections + numberOfPeerSections)) {
|
||||
// Add peer
|
||||
return nil
|
||||
} else {
|
||||
assert(section == (numberOfInterfaceSections + numberOfPeerSections + 1))
|
||||
return "On-Demand Activation"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,8 +360,7 @@ extension TunnelEditTableViewController {
|
|||
}
|
||||
return cell
|
||||
}
|
||||
} else {
|
||||
assert(section == (numberOfInterfaceSections + numberOfPeerSections))
|
||||
} else if (section == (numberOfInterfaceSections + numberOfPeerSections)) {
|
||||
// Add peer
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.id, for: indexPath) as! TunnelEditTableViewButtonCell
|
||||
cell.buttonText = "Add peer"
|
||||
|
@ -365,6 +380,32 @@ extension TunnelEditTableViewController {
|
|||
}, completion: nil)
|
||||
}
|
||||
return cell
|
||||
} else {
|
||||
assert(section == (numberOfInterfaceSections + numberOfPeerSections + 1))
|
||||
if (row == 0) {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSwitchCell.id, for: indexPath) as! TunnelEditTableViewSwitchCell
|
||||
cell.message = "Activate on demand"
|
||||
cell.isOn = (tunnelViewModel.activationType != .activateManually)
|
||||
cell.onSwitchToggled = { [weak self] (isOn) in
|
||||
guard let s = self else { return }
|
||||
let indexPaths: [IndexPath] = (1 ..< 4).map { IndexPath(row: $0, section: section) }
|
||||
if (isOn) {
|
||||
s.tunnelViewModel.activationType = .useOnDemandOverWifiAndCellular
|
||||
s.tableView.insertRows(at: indexPaths, with: .automatic)
|
||||
} else {
|
||||
s.tunnelViewModel.activationType = .activateManually
|
||||
s.tableView.deleteRows(at: indexPaths, with: .automatic)
|
||||
}
|
||||
}
|
||||
return cell
|
||||
} else {
|
||||
assert(row < 4)
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSelectionListCell.id, for: indexPath) as! TunnelEditTableViewSelectionListCell
|
||||
let option = activateOnDemandOptions[row - 1]
|
||||
cell.message = tunnelViewModel.activateOnDemandOptionText(for: option)
|
||||
cell.isChecked = (tunnelViewModel.activationType == option)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,6 +447,41 @@ extension TunnelEditTableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: UITableViewDelegate
|
||||
|
||||
extension TunnelEditTableViewController {
|
||||
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||
let numberOfPeerSections = tunnelViewModel.peersData.count
|
||||
|
||||
let section = indexPath.section
|
||||
let row = indexPath.row
|
||||
|
||||
if (section == (numberOfInterfaceSections + numberOfPeerSections + 1)) {
|
||||
return (row > 0) ? indexPath : nil
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||
let numberOfPeerSections = tunnelViewModel.peersData.count
|
||||
|
||||
let section = indexPath.section
|
||||
let row = indexPath.row
|
||||
|
||||
assert(section == (numberOfInterfaceSections + numberOfPeerSections + 1))
|
||||
assert(row > 0)
|
||||
|
||||
let option = activateOnDemandOptions[row - 1]
|
||||
tunnelViewModel.activationType = option
|
||||
|
||||
let indexPaths: [IndexPath] = (1 ..< 4).map { IndexPath(row: $0, section: section) }
|
||||
tableView.reloadRows(at: indexPaths, with: .automatic)
|
||||
}
|
||||
}
|
||||
|
||||
class TunnelEditTableViewKeyValueCell: UITableViewCell {
|
||||
static let id: String = "TunnelEditTableViewKeyValueCell"
|
||||
var key: String {
|
||||
|
@ -665,3 +741,30 @@ class TunnelEditTableViewSwitchCell: UITableViewCell {
|
|||
isOn = false
|
||||
}
|
||||
}
|
||||
|
||||
class TunnelEditTableViewSelectionListCell: UITableViewCell {
|
||||
static let id: String = "TunnelEditTableViewSelectionListCell"
|
||||
var message: String {
|
||||
get { return textLabel?.text ?? "" }
|
||||
set(value) { textLabel!.text = value }
|
||||
}
|
||||
var isChecked: Bool {
|
||||
didSet {
|
||||
accessoryType = isChecked ? .checkmark : .none
|
||||
}
|
||||
}
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
isChecked = false
|
||||
super.init(style: .default, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
message = ""
|
||||
isChecked = false
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue