Refactor out VPN-handling stuff from tunnels list VC to the main VC
Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
e1b258353c
commit
046d1413ec
|
@ -39,6 +39,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||||
mainVC?.tunnelsListVC?.refreshTunnelConnectionStatuses()
|
mainVC?.refreshTunnelConnectionStatuses()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
class MainViewController: UISplitViewController {
|
class MainViewController: UISplitViewController {
|
||||||
|
|
||||||
|
var tunnelsManager: TunnelsManager?
|
||||||
|
var onTunnelsManagerReady: ((TunnelsManager) -> Void)?
|
||||||
|
|
||||||
var tunnelsListVC: TunnelsListTableViewController?
|
var tunnelsListVC: TunnelsListTableViewController?
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
@ -30,6 +34,38 @@ class MainViewController: UISplitViewController {
|
||||||
|
|
||||||
// On iPad, always show both masterVC and detailVC, even in portrait mode, like the Settings app
|
// On iPad, always show both masterVC and detailVC, even in portrait mode, like the Settings app
|
||||||
self.preferredDisplayMode = .allVisible
|
self.preferredDisplayMode = .allVisible
|
||||||
|
|
||||||
|
// Create the tunnels manager, and when it's ready, inform tunnelsListVC
|
||||||
|
TunnelsManager.create { [weak self] tunnelsManager in
|
||||||
|
guard let tunnelsManager = tunnelsManager else { return }
|
||||||
|
guard let s = self else { return }
|
||||||
|
|
||||||
|
s.tunnelsManager = tunnelsManager
|
||||||
|
s.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
|
||||||
|
|
||||||
|
tunnelsManager.activationDelegate = s
|
||||||
|
|
||||||
|
s.onTunnelsManagerReady?(tunnelsManager)
|
||||||
|
s.onTunnelsManagerReady = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MainViewController: TunnelsManagerActivationDelegate {
|
||||||
|
func tunnelActivationFailed(tunnel: TunnelContainer, error: TunnelActivationError) {
|
||||||
|
ErrorPresenter.showErrorAlert(error: error, from: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MainViewController {
|
||||||
|
func refreshTunnelConnectionStatuses() {
|
||||||
|
if let tunnelsManager = tunnelsManager {
|
||||||
|
tunnelsManager.refreshStatuses()
|
||||||
|
} else {
|
||||||
|
onTunnelsManagerReady = { tunnelsManager in
|
||||||
|
tunnelsManager.refreshStatuses()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import UserNotifications
|
||||||
class TunnelsListTableViewController: UIViewController {
|
class TunnelsListTableViewController: UIViewController {
|
||||||
|
|
||||||
var tunnelsManager: TunnelsManager?
|
var tunnelsManager: TunnelsManager?
|
||||||
var onTunnelsManagerReady: ((TunnelsManager) -> Void)?
|
|
||||||
|
|
||||||
var busyIndicator: UIActivityIndicatorView?
|
var busyIndicator: UIActivityIndicatorView?
|
||||||
var centeredAddButton: BorderedTextButton?
|
var centeredAddButton: BorderedTextButton?
|
||||||
|
@ -38,53 +37,58 @@ class TunnelsListTableViewController: UIViewController {
|
||||||
])
|
])
|
||||||
busyIndicator.startAnimating()
|
busyIndicator.startAnimating()
|
||||||
self.busyIndicator = busyIndicator
|
self.busyIndicator = busyIndicator
|
||||||
|
}
|
||||||
|
|
||||||
// Create the tunnels manager, and when it's ready, create the tableView
|
func setTunnelsManager(tunnelsManager: TunnelsManager) {
|
||||||
TunnelsManager.create { [weak self] tunnelsManager in
|
if (self.tunnelsManager != nil) {
|
||||||
guard let tunnelsManager = tunnelsManager else { return }
|
// If a tunnels manager is already set, do nothing
|
||||||
guard let s = self else { return }
|
return
|
||||||
|
|
||||||
let tableView = UITableView(frame: CGRect.zero, style: .plain)
|
|
||||||
tableView.rowHeight = 60
|
|
||||||
tableView.separatorStyle = .none
|
|
||||||
tableView.register(TunnelsListTableViewCell.self, forCellReuseIdentifier: TunnelsListTableViewCell.id)
|
|
||||||
|
|
||||||
s.view.addSubview(tableView)
|
|
||||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
tableView.leftAnchor.constraint(equalTo: s.view.leftAnchor),
|
|
||||||
tableView.rightAnchor.constraint(equalTo: s.view.rightAnchor),
|
|
||||||
tableView.topAnchor.constraint(equalTo: s.view.topAnchor),
|
|
||||||
tableView.bottomAnchor.constraint(equalTo: s.view.bottomAnchor)
|
|
||||||
])
|
|
||||||
tableView.dataSource = s
|
|
||||||
tableView.delegate = s
|
|
||||||
s.tableView = tableView
|
|
||||||
|
|
||||||
// Add an add button, centered
|
|
||||||
let centeredAddButton = BorderedTextButton()
|
|
||||||
centeredAddButton.title = "Add a tunnel"
|
|
||||||
centeredAddButton.isHidden = true
|
|
||||||
s.view.addSubview(centeredAddButton)
|
|
||||||
centeredAddButton.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
centeredAddButton.centerXAnchor.constraint(equalTo: s.view.centerXAnchor),
|
|
||||||
centeredAddButton.centerYAnchor.constraint(equalTo: s.view.centerYAnchor)
|
|
||||||
])
|
|
||||||
centeredAddButton.onTapped = { [weak self] in
|
|
||||||
self?.addButtonTapped(sender: centeredAddButton)
|
|
||||||
}
|
|
||||||
s.centeredAddButton = centeredAddButton
|
|
||||||
|
|
||||||
centeredAddButton.isHidden = (tunnelsManager.numberOfTunnels() > 0)
|
|
||||||
busyIndicator.stopAnimating()
|
|
||||||
|
|
||||||
tunnelsManager.delegate = s
|
|
||||||
tunnelsManager.activationDelegate = s
|
|
||||||
s.tunnelsManager = tunnelsManager
|
|
||||||
s.onTunnelsManagerReady?(tunnelsManager)
|
|
||||||
s.onTunnelsManagerReady = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the table view
|
||||||
|
|
||||||
|
let tableView = UITableView(frame: CGRect.zero, style: .plain)
|
||||||
|
tableView.rowHeight = 60
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.register(TunnelsListTableViewCell.self, forCellReuseIdentifier: TunnelsListTableViewCell.id)
|
||||||
|
|
||||||
|
self.view.addSubview(tableView)
|
||||||
|
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
|
||||||
|
tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
|
||||||
|
tableView.topAnchor.constraint(equalTo: self.view.topAnchor),
|
||||||
|
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
|
||||||
|
])
|
||||||
|
tableView.dataSource = self
|
||||||
|
tableView.delegate = self
|
||||||
|
self.tableView = tableView
|
||||||
|
|
||||||
|
// Add button at the center
|
||||||
|
|
||||||
|
let centeredAddButton = BorderedTextButton()
|
||||||
|
centeredAddButton.title = "Add a tunnel"
|
||||||
|
centeredAddButton.isHidden = true
|
||||||
|
self.view.addSubview(centeredAddButton)
|
||||||
|
centeredAddButton.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
centeredAddButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
|
||||||
|
centeredAddButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
|
||||||
|
])
|
||||||
|
centeredAddButton.onTapped = { [weak self] in
|
||||||
|
self?.addButtonTapped(sender: centeredAddButton)
|
||||||
|
}
|
||||||
|
centeredAddButton.isHidden = (tunnelsManager.numberOfTunnels() > 0)
|
||||||
|
self.centeredAddButton = centeredAddButton
|
||||||
|
|
||||||
|
// Hide the busy indicator
|
||||||
|
|
||||||
|
self.busyIndicator?.stopAnimating()
|
||||||
|
|
||||||
|
// Keep track of the tunnels manager
|
||||||
|
|
||||||
|
self.tunnelsManager = tunnelsManager
|
||||||
|
tunnelsManager.tunnelsListDelegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func addButtonTapped(sender: AnyObject) {
|
@objc func addButtonTapped(sender: AnyObject) {
|
||||||
|
@ -188,16 +192,6 @@ class TunnelsListTableViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshTunnelConnectionStatuses() {
|
|
||||||
if let tunnelsManager = tunnelsManager {
|
|
||||||
tunnelsManager.refreshStatuses()
|
|
||||||
} else {
|
|
||||||
onTunnelsManagerReady = { tunnelsManager in
|
|
||||||
tunnelsManager.refreshStatuses()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: UIDocumentPickerDelegate
|
// MARK: UIDocumentPickerDelegate
|
||||||
|
@ -293,7 +287,7 @@ extension TunnelsListTableViewController: UITableViewDelegate {
|
||||||
|
|
||||||
// MARK: TunnelsManagerDelegate
|
// MARK: TunnelsManagerDelegate
|
||||||
|
|
||||||
extension TunnelsListTableViewController: TunnelsManagerDelegate {
|
extension TunnelsListTableViewController: TunnelsManagerListDelegate {
|
||||||
func tunnelAdded(at index: Int) {
|
func tunnelAdded(at index: Int) {
|
||||||
tableView?.insertRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
|
tableView?.insertRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
|
||||||
centeredAddButton?.isHidden = (tunnelsManager?.numberOfTunnels() ?? 0 > 0)
|
centeredAddButton?.isHidden = (tunnelsManager?.numberOfTunnels() ?? 0 > 0)
|
||||||
|
@ -313,14 +307,6 @@ extension TunnelsListTableViewController: TunnelsManagerDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: TunnelActivationDelegate
|
|
||||||
|
|
||||||
extension TunnelsListTableViewController: TunnelActivationDelegate {
|
|
||||||
func tunnelActivationFailed(tunnel: TunnelContainer, error: TunnelActivationError) {
|
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TunnelsListTableViewCell: UITableViewCell {
|
class TunnelsListTableViewCell: UITableViewCell {
|
||||||
static let id: String = "TunnelsListTableViewCell"
|
static let id: String = "TunnelsListTableViewCell"
|
||||||
var tunnel: TunnelContainer? {
|
var tunnel: TunnelContainer? {
|
||||||
|
|
|
@ -5,14 +5,14 @@ import Foundation
|
||||||
import NetworkExtension
|
import NetworkExtension
|
||||||
import os.log
|
import os.log
|
||||||
|
|
||||||
protocol TunnelsManagerDelegate: class {
|
protocol TunnelsManagerListDelegate: class {
|
||||||
func tunnelAdded(at: Int)
|
func tunnelAdded(at: Int)
|
||||||
func tunnelModified(at: Int)
|
func tunnelModified(at: Int)
|
||||||
func tunnelMoved(at oldIndex: Int, to newIndex: Int)
|
func tunnelMoved(at oldIndex: Int, to newIndex: Int)
|
||||||
func tunnelRemoved(at: Int)
|
func tunnelRemoved(at: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol TunnelActivationDelegate: class {
|
protocol TunnelsManagerActivationDelegate: class {
|
||||||
func tunnelActivationFailed(tunnel: TunnelContainer, error: TunnelActivationError)
|
func tunnelActivationFailed(tunnel: TunnelContainer, error: TunnelActivationError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ enum TunnelManagementError: Error {
|
||||||
class TunnelsManager {
|
class TunnelsManager {
|
||||||
|
|
||||||
private var tunnels: [TunnelContainer]
|
private var tunnels: [TunnelContainer]
|
||||||
weak var delegate: TunnelsManagerDelegate?
|
weak var tunnelsListDelegate: TunnelsManagerListDelegate?
|
||||||
weak var activationDelegate: TunnelActivationDelegate?
|
weak var activationDelegate: TunnelsManagerActivationDelegate?
|
||||||
|
|
||||||
private var isAddingTunnel: Bool = false
|
private var isAddingTunnel: Bool = false
|
||||||
private var isModifyingTunnel: Bool = false
|
private var isModifyingTunnel: Bool = false
|
||||||
|
@ -94,7 +94,7 @@ class TunnelsManager {
|
||||||
let tunnel = TunnelContainer(tunnel: tunnelProviderManager)
|
let tunnel = TunnelContainer(tunnel: tunnelProviderManager)
|
||||||
s.tunnels.append(tunnel)
|
s.tunnels.append(tunnel)
|
||||||
s.tunnels.sort { $0.name < $1.name }
|
s.tunnels.sort { $0.name < $1.name }
|
||||||
s.delegate?.tunnelAdded(at: s.tunnels.firstIndex(of: tunnel)!)
|
s.tunnelsListDelegate?.tunnelAdded(at: s.tunnels.firstIndex(of: tunnel)!)
|
||||||
completionHandler(tunnel, nil)
|
completionHandler(tunnel, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,9 +157,9 @@ class TunnelsManager {
|
||||||
let oldIndex = s.tunnels.firstIndex(of: tunnel)!
|
let oldIndex = s.tunnels.firstIndex(of: tunnel)!
|
||||||
s.tunnels.sort { $0.name < $1.name }
|
s.tunnels.sort { $0.name < $1.name }
|
||||||
let newIndex = s.tunnels.firstIndex(of: tunnel)!
|
let newIndex = s.tunnels.firstIndex(of: tunnel)!
|
||||||
s.delegate?.tunnelMoved(at: oldIndex, to: newIndex)
|
s.tunnelsListDelegate?.tunnelMoved(at: oldIndex, to: newIndex)
|
||||||
}
|
}
|
||||||
s.delegate?.tunnelModified(at: s.tunnels.firstIndex(of: tunnel)!)
|
s.tunnelsListDelegate?.tunnelModified(at: s.tunnels.firstIndex(of: tunnel)!)
|
||||||
|
|
||||||
if (tunnel.status == .active || tunnel.status == .activating || tunnel.status == .reasserting) {
|
if (tunnel.status == .active || tunnel.status == .activating || tunnel.status == .reasserting) {
|
||||||
// Turn off the tunnel, and then turn it back on, so the changes are made effective
|
// Turn off the tunnel, and then turn it back on, so the changes are made effective
|
||||||
|
@ -200,7 +200,7 @@ class TunnelsManager {
|
||||||
if let s = self {
|
if let s = self {
|
||||||
let index = s.tunnels.firstIndex(of: tunnel)!
|
let index = s.tunnels.firstIndex(of: tunnel)!
|
||||||
s.tunnels.remove(at: index)
|
s.tunnels.remove(at: index)
|
||||||
s.delegate?.tunnelRemoved(at: index)
|
s.tunnelsListDelegate?.tunnelRemoved(at: index)
|
||||||
}
|
}
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue