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:
Roopesh Chander 2018-12-03 18:51:51 +05:30
parent e1b258353c
commit 046d1413ec
4 changed files with 96 additions and 74 deletions

View File

@ -39,6 +39,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
} }
func applicationDidBecomeActive(_ application: UIApplication) { func applicationDidBecomeActive(_ application: UIApplication) {
mainVC?.tunnelsListVC?.refreshTunnelConnectionStatuses() mainVC?.refreshTunnelConnectionStatuses()
} }
} }

View File

@ -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()
}
}
} }
} }

View File

@ -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
}
// Create the table view
let tableView = UITableView(frame: CGRect.zero, style: .plain) let tableView = UITableView(frame: CGRect.zero, style: .plain)
tableView.rowHeight = 60 tableView.rowHeight = 60
tableView.separatorStyle = .none tableView.separatorStyle = .none
tableView.register(TunnelsListTableViewCell.self, forCellReuseIdentifier: TunnelsListTableViewCell.id) tableView.register(TunnelsListTableViewCell.self, forCellReuseIdentifier: TunnelsListTableViewCell.id)
s.view.addSubview(tableView) self.view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
tableView.leftAnchor.constraint(equalTo: s.view.leftAnchor), tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
tableView.rightAnchor.constraint(equalTo: s.view.rightAnchor), tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
tableView.topAnchor.constraint(equalTo: s.view.topAnchor), tableView.topAnchor.constraint(equalTo: self.view.topAnchor),
tableView.bottomAnchor.constraint(equalTo: s.view.bottomAnchor) tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
]) ])
tableView.dataSource = s tableView.dataSource = self
tableView.delegate = s tableView.delegate = self
s.tableView = tableView self.tableView = tableView
// Add button at the center
// Add an add button, centered
let centeredAddButton = BorderedTextButton() let centeredAddButton = BorderedTextButton()
centeredAddButton.title = "Add a tunnel" centeredAddButton.title = "Add a tunnel"
centeredAddButton.isHidden = true centeredAddButton.isHidden = true
s.view.addSubview(centeredAddButton) self.view.addSubview(centeredAddButton)
centeredAddButton.translatesAutoresizingMaskIntoConstraints = false centeredAddButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
centeredAddButton.centerXAnchor.constraint(equalTo: s.view.centerXAnchor), centeredAddButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
centeredAddButton.centerYAnchor.constraint(equalTo: s.view.centerYAnchor) centeredAddButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
]) ])
centeredAddButton.onTapped = { [weak self] in centeredAddButton.onTapped = { [weak self] in
self?.addButtonTapped(sender: centeredAddButton) self?.addButtonTapped(sender: centeredAddButton)
} }
s.centeredAddButton = centeredAddButton
centeredAddButton.isHidden = (tunnelsManager.numberOfTunnels() > 0) centeredAddButton.isHidden = (tunnelsManager.numberOfTunnels() > 0)
busyIndicator.stopAnimating() self.centeredAddButton = centeredAddButton
tunnelsManager.delegate = s // Hide the busy indicator
tunnelsManager.activationDelegate = s
s.tunnelsManager = tunnelsManager self.busyIndicator?.stopAnimating()
s.onTunnelsManagerReady?(tunnelsManager)
s.onTunnelsManagerReady = nil // 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? {

View File

@ -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)
} }