on-demand: iOS: Tunnel detail: Show SSID info
Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
bdeb89a9e5
commit
01604dd8d1
|
@ -84,9 +84,7 @@
|
||||||
"tunnelOnDemandCellular" = "Cellular";
|
"tunnelOnDemandCellular" = "Cellular";
|
||||||
"tunnelOnDemandEthernet" = "Ethernet";
|
"tunnelOnDemandEthernet" = "Ethernet";
|
||||||
"tunnelOnDemandWiFi" = "Wi-Fi";
|
"tunnelOnDemandWiFi" = "Wi-Fi";
|
||||||
"tunnelOnDemandSSIDDescription" = "Selected SSIDs";
|
"tunnelOnDemandSSIDsKey" = "SSIDs";
|
||||||
"tunnelOnDemandSSIDescriptionMac" = "SSIDs";
|
|
||||||
"tunnelOnDemandSSIDEdit" = "Select SSIDs";
|
|
||||||
|
|
||||||
"tunnelOnDemandAnySSID" = "Any SSID";
|
"tunnelOnDemandAnySSID" = "Any SSID";
|
||||||
"tunnelOnDemandOnlySelectedSSIDs" = "Only selected SSIDs";
|
"tunnelOnDemandOnlySelectedSSIDs" = "Only selected SSIDs";
|
||||||
|
@ -98,7 +96,7 @@
|
||||||
"tunnelOnDemandAddMessageAddNewSSID" = "Add manually";
|
"tunnelOnDemandAddMessageAddNewSSID" = "Add manually";
|
||||||
"tunnelOnDemandAddMessageAddConnectedSSID (%@)" = "Connected: %@";
|
"tunnelOnDemandAddMessageAddConnectedSSID (%@)" = "Connected: %@";
|
||||||
|
|
||||||
"tunnelOnDemandKey" = "Activate on demand";
|
"tunnelOnDemandKey" = "On demand";
|
||||||
"tunnelOnDemandOptionOff" = "Off";
|
"tunnelOnDemandOptionOff" = "Off";
|
||||||
"tunnelOnDemandOptionWiFiOnly" = "Wi-Fi only";
|
"tunnelOnDemandOptionWiFiOnly" = "Wi-Fi only";
|
||||||
"tunnelOnDemandOptionWiFiOrCellular" = "Wi-Fi or cellular";
|
"tunnelOnDemandOptionWiFiOrCellular" = "Wi-Fi or cellular";
|
||||||
|
|
|
@ -5,13 +5,15 @@ import Foundation
|
||||||
|
|
||||||
class ActivateOnDemandViewModel {
|
class ActivateOnDemandViewModel {
|
||||||
enum OnDemandField {
|
enum OnDemandField {
|
||||||
|
case onDemand
|
||||||
case nonWiFiInterface
|
case nonWiFiInterface
|
||||||
case wiFiInterface
|
case wiFiInterface
|
||||||
case ssidDescription
|
case ssid
|
||||||
case ssidEdit
|
|
||||||
|
|
||||||
var localizedUIString: String {
|
var localizedUIString: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .onDemand:
|
||||||
|
return tr("tunnelOnDemandKey")
|
||||||
case .nonWiFiInterface:
|
case .nonWiFiInterface:
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
return tr("tunnelOnDemandCellular")
|
return tr("tunnelOnDemandCellular")
|
||||||
|
@ -21,8 +23,7 @@ class ActivateOnDemandViewModel {
|
||||||
#error("Unimplemented")
|
#error("Unimplemented")
|
||||||
#endif
|
#endif
|
||||||
case .wiFiInterface: return tr("tunnelOnDemandWiFi")
|
case .wiFiInterface: return tr("tunnelOnDemandWiFi")
|
||||||
case .ssidDescription: return tr("tunnelOnDemandSSIDDescription")
|
case .ssid: return tr("tunnelOnDemandSSIDsKey")
|
||||||
case .ssidEdit: return tr("tunnelOnDemandSSIDEdit")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +49,15 @@ class ActivateOnDemandViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ActivateOnDemandViewModel {
|
extension ActivateOnDemandViewModel {
|
||||||
convenience init(from option: ActivateOnDemandOption) {
|
convenience init(setting: ActivateOnDemandSetting) {
|
||||||
|
if setting.isActivateOnDemandEnabled {
|
||||||
|
self.init(option: setting.activateOnDemandOption)
|
||||||
|
} else {
|
||||||
|
self.init(option: .none)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(option: ActivateOnDemandOption) {
|
||||||
self.init()
|
self.init()
|
||||||
switch option {
|
switch option {
|
||||||
case .none:
|
case .none:
|
||||||
|
@ -103,6 +112,33 @@ extension ActivateOnDemandViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ActivateOnDemandViewModel {
|
||||||
|
var localizedInterfaceDescription: String {
|
||||||
|
switch (isWiFiInterfaceEnabled, isNonWiFiInterfaceEnabled) {
|
||||||
|
case (false, false):
|
||||||
|
return tr("tunnelOnDemandOptionOff")
|
||||||
|
case (true, false):
|
||||||
|
return tr("tunnelOnDemandOptionWiFiOnly")
|
||||||
|
case (false, true):
|
||||||
|
#if os(iOS)
|
||||||
|
return tr("tunnelOnDemandOptionCellularOnly")
|
||||||
|
#elseif os(macOS)
|
||||||
|
return tr("tunnelOnDemandOptionEthernetOnly")
|
||||||
|
#else
|
||||||
|
#error("Unimplemented")
|
||||||
|
#endif
|
||||||
|
case (true, true):
|
||||||
|
#if os(iOS)
|
||||||
|
return tr("tunnelOnDemandOptionWiFiOrCellular")
|
||||||
|
#elseif os(macOS)
|
||||||
|
return tr("tunnelOnDemandOptionWiFiOrEthernet")
|
||||||
|
#else
|
||||||
|
#error("Unimplemented")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private extension ActivateOnDemandViewModel {
|
private extension ActivateOnDemandViewModel {
|
||||||
func ssidViewModel(from ssidOption: ActivateOnDemandSSIDOption) -> (OnDemandSSIDOption, [String]) {
|
func ssidViewModel(from ssidOption: ActivateOnDemandSSIDOption) -> (OnDemandSSIDOption, [String]) {
|
||||||
switch ssidOption {
|
switch ssidOption {
|
||||||
|
|
|
@ -24,21 +24,28 @@ class TunnelDetailTableViewController: UITableViewController {
|
||||||
.rxBytes, .txBytes, .lastHandshakeTime
|
.rxBytes, .txBytes, .lastHandshakeTime
|
||||||
]
|
]
|
||||||
|
|
||||||
|
static let onDemandFields: [ActivateOnDemandViewModel.OnDemandField] = [
|
||||||
|
.onDemand, .ssid
|
||||||
|
]
|
||||||
|
|
||||||
let tunnelsManager: TunnelsManager
|
let tunnelsManager: TunnelsManager
|
||||||
let tunnel: TunnelContainer
|
let tunnel: TunnelContainer
|
||||||
var tunnelViewModel: TunnelViewModel
|
var tunnelViewModel: TunnelViewModel
|
||||||
|
var onDemandViewModel: ActivateOnDemandViewModel
|
||||||
|
|
||||||
private var sections = [Section]()
|
private var sections = [Section]()
|
||||||
private var interfaceFieldIsVisible = [Bool]()
|
private var interfaceFieldIsVisible = [Bool]()
|
||||||
private var peerFieldIsVisible = [[Bool]]()
|
private var peerFieldIsVisible = [[Bool]]()
|
||||||
|
|
||||||
private var statusObservationToken: AnyObject?
|
private var statusObservationToken: AnyObject?
|
||||||
|
private var onDemandObservationToken: AnyObject?
|
||||||
private var reloadRuntimeConfigurationTimer: Timer?
|
private var reloadRuntimeConfigurationTimer: Timer?
|
||||||
|
|
||||||
init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer) {
|
init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer) {
|
||||||
self.tunnelsManager = tunnelsManager
|
self.tunnelsManager = tunnelsManager
|
||||||
self.tunnel = tunnel
|
self.tunnel = tunnel
|
||||||
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
||||||
|
onDemandViewModel = ActivateOnDemandViewModel(setting: tunnel.activateOnDemandSetting)
|
||||||
super.init(style: .grouped)
|
super.init(style: .grouped)
|
||||||
loadSections()
|
loadSections()
|
||||||
loadVisibleFields()
|
loadVisibleFields()
|
||||||
|
@ -51,6 +58,11 @@ class TunnelDetailTableViewController: UITableViewController {
|
||||||
self.stopUpdatingRuntimeConfiguration()
|
self.stopUpdatingRuntimeConfiguration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onDemandObservationToken = tunnel.observe(\.isActivateOnDemandEnabled) { [weak self] tunnel, _ in
|
||||||
|
// Handle On-Demand getting turned on/off outside of the app
|
||||||
|
self?.onDemandViewModel = ActivateOnDemandViewModel(setting: tunnel.activateOnDemandSetting)
|
||||||
|
self?.updateActivateOnDemandFields()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
@ -242,11 +254,27 @@ class TunnelDetailTableViewController: UITableViewController {
|
||||||
self.applyTunnelConfiguration(tunnelConfiguration: tunnelConfiguration)
|
self.applyTunnelConfiguration(tunnelConfiguration: tunnelConfiguration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateActivateOnDemandFields() {
|
||||||
|
guard let onDemandSection = sections.firstIndex(where: { if case .onDemand = $0 { return true } else { return false } }) else { return }
|
||||||
|
let numberOfTableViewOnDemandRows = tableView.numberOfRows(inSection: onDemandSection)
|
||||||
|
let ssidRowIndexPath = IndexPath(row: 1, section: onDemandSection)
|
||||||
|
switch (numberOfTableViewOnDemandRows, onDemandViewModel.isWiFiInterfaceEnabled) {
|
||||||
|
case (1, true):
|
||||||
|
tableView.insertRows(at: [ssidRowIndexPath], with: .automatic)
|
||||||
|
case (2, false):
|
||||||
|
tableView.deleteRows(at: [ssidRowIndexPath], with: .automatic)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
tableView.reloadSections(IndexSet(integer: onDemandSection), with: .automatic)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TunnelDetailTableViewController: TunnelEditTableViewControllerDelegate {
|
extension TunnelDetailTableViewController: TunnelEditTableViewControllerDelegate {
|
||||||
func tunnelSaved(tunnel: TunnelContainer) {
|
func tunnelSaved(tunnel: TunnelContainer) {
|
||||||
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
||||||
|
onDemandViewModel = ActivateOnDemandViewModel(setting: tunnel.activateOnDemandSetting)
|
||||||
loadSections()
|
loadSections()
|
||||||
loadVisibleFields()
|
loadVisibleFields()
|
||||||
title = tunnel.name
|
title = tunnel.name
|
||||||
|
@ -272,7 +300,7 @@ extension TunnelDetailTableViewController {
|
||||||
case .peer(let peerIndex, _):
|
case .peer(let peerIndex, _):
|
||||||
return peerFieldIsVisible[peerIndex].filter { $0 }.count
|
return peerFieldIsVisible[peerIndex].filter { $0 }.count
|
||||||
case .onDemand:
|
case .onDemand:
|
||||||
return 1
|
return onDemandViewModel.isWiFiInterfaceEnabled ? 2 : 1
|
||||||
case .delete:
|
case .delete:
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -380,10 +408,12 @@ extension TunnelDetailTableViewController {
|
||||||
|
|
||||||
private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||||
let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath)
|
let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
cell.key = tr("tunnelOnDemandKey")
|
let field = TunnelDetailTableViewController.onDemandFields[indexPath.row]
|
||||||
cell.value = TunnelViewModel.activateOnDemandDetailText(for: tunnel.activateOnDemandSetting)
|
cell.key = field.localizedUIString
|
||||||
cell.observationToken = tunnel.observe(\.isActivateOnDemandEnabled) { [weak cell] tunnel, _ in
|
if field == .onDemand {
|
||||||
cell?.value = TunnelViewModel.activateOnDemandDetailText(for: tunnel.activateOnDemandSetting)
|
cell.value = onDemandViewModel.localizedInterfaceDescription
|
||||||
|
} else if field == .ssid {
|
||||||
|
cell.value = onDemandViewModel.ssidOption.localizedUIString
|
||||||
}
|
}
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
let onDemandFields: [ActivateOnDemandViewModel.OnDemandField] = [
|
let onDemandFields: [ActivateOnDemandViewModel.OnDemandField] = [
|
||||||
.nonWiFiInterface,
|
.nonWiFiInterface,
|
||||||
.wiFiInterface,
|
.wiFiInterface,
|
||||||
.ssidEdit
|
.ssid
|
||||||
]
|
]
|
||||||
|
|
||||||
let tunnelsManager: TunnelsManager
|
let tunnelsManager: TunnelsManager
|
||||||
|
@ -60,8 +60,7 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
self.tunnelsManager = tunnelsManager
|
self.tunnelsManager = tunnelsManager
|
||||||
self.tunnel = tunnel
|
self.tunnel = tunnel
|
||||||
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
||||||
let onDemandOption = tunnel.activateOnDemandSetting.isActivateOnDemandEnabled ? tunnel.activateOnDemandSetting.activateOnDemandOption : .none
|
onDemandViewModel = ActivateOnDemandViewModel(setting: tunnel.activateOnDemandSetting)
|
||||||
onDemandViewModel = ActivateOnDemandViewModel(from: onDemandOption)
|
|
||||||
super.init(style: .grouped)
|
super.init(style: .grouped)
|
||||||
loadSections()
|
loadSections()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue