diff options
Diffstat (limited to '')
-rw-r--r-- | WireGuard/ViewControllers/TunnelsTableViewController.swift | 308 |
1 files changed, 0 insertions, 308 deletions
diff --git a/WireGuard/ViewControllers/TunnelsTableViewController.swift b/WireGuard/ViewControllers/TunnelsTableViewController.swift deleted file mode 100644 index 26932d9..0000000 --- a/WireGuard/ViewControllers/TunnelsTableViewController.swift +++ /dev/null @@ -1,308 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import os.log -import CoreData - -import BNRCoreDataStack -import NetworkExtension - -protocol TunnelsTableViewControllerDelegate: class { - func addProvider(tunnelsTableViewController: TunnelsTableViewController) - func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus - func showSettings() -} - -class TunnelsTableViewController: UITableViewController { - weak var delegate: TunnelsTableViewControllerDelegate? - - var viewContext: NSManagedObjectContext! - - @IBOutlet var settingsButton: UIBarButtonItem! - @IBOutlet var editButton: UIBarButtonItem! - @IBOutlet var doneButton: UIBarButtonItem! - - private lazy var fetchedResultsController: FetchedResultsController<Tunnel> = { - let fetchRequest = NSFetchRequest<Tunnel>() - fetchRequest.entity = Tunnel.entity() - fetchRequest.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)] - let frc = FetchedResultsController<Tunnel>(fetchRequest: fetchRequest, - managedObjectContext: viewContext) - frc.setDelegate(self.frcDelegate) - return frc - }() - - public func updateStatus(for tunnelIdentifier: String) { - viewContext.perform { - do { - let tunnel = try Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - if let indexPath = self.fetchedResultsController.indexPathForObject(tunnel) { - self.tableView.reloadRows(at: [indexPath], with: .none) - } - } - } catch { - os_log("Unable to load tunnel for tunnel identifier: %{public}@", log: Log.general, type: .error, error.localizedDescription) - - } - } - } - - private lazy var frcDelegate: TunnelFetchedResultsControllerDelegate = { // swiftlint:disable:this weak_delegate - return TunnelFetchedResultsControllerDelegate(tableView: self.tableView) - }() - - override func viewDidLoad() { - super.viewDidLoad() - do { - try fetchedResultsController.performFetch() - } catch { - print("Failed to fetch objects: \(error)") - } - - // Get rid of seperator lines in table. - tableView.tableFooterView = UIView(frame: CGRect.zero) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - updateBarButtons() - } - - @IBAction func editTunnels(_ sender: Any) { - tableView.setEditing(!tableView.isEditing, animated: true) - updateBarButtons() - - } - - private func updateBarButtons() { - navigationController?.setToolbarHidden(tableView.isEditing, animated: true) - if tableView.isEditing { - self.navigationItem.setRightBarButtonItems([doneButton], animated: true) - } else { - self.navigationItem.setRightBarButtonItems([settingsButton, editButton], animated: true) - } - } - - @IBAction func showSettings(_ sender: Any) { - delegate?.showSettings() - } - - @IBAction func addProvider(_ sender: UIBarButtonItem) { - delegate?.addProvider(tunnelsTableViewController: self) - } - - override func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return fetchedResultsController.sections?[0].objects.count ?? 0 - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(type: TunnelTableViewCell.self, for: indexPath) - cell.delegate = self - - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - cell.configure(tunnel: tunnel, status: delegate?.status(for: tunnel, tunnelsTableViewController: self) ?? .invalid) - - return cell - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - delegate?.info(tunnel: tunnel, tunnelsTableViewController: self) - - tableView.deselectRow(at: indexPath, animated: true) - } - - override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - delegate?.info(tunnel: tunnel, tunnelsTableViewController: self) - - } - - override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - return true - } - - override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - delegate?.delete(tunnel: tunnel, tunnelsTableViewController: self) - } - } -} - -extension TunnelsTableViewController: TunnelTableViewCellDelegate { - func connect(tunnelIdentifier: String) { - let tunnel = try? Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - self.delegate?.connect(tunnel: tunnel!, tunnelsTableViewController: self) - } - } - - func disconnect(tunnelIdentifier: String) { - let tunnel = try? Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - self.delegate?.disconnect(tunnel: tunnel!, tunnelsTableViewController: self) - } - } - -} - -extension TunnelsTableViewController: Identifyable {} - -class TunnelFetchedResultsControllerDelegate: NSObject, FetchedResultsControllerDelegate { - - private weak var tableView: UITableView? - private var arrowImage: UIImageView? - - // MARK: - Lifecycle - init(tableView: UITableView) { - self.tableView = tableView - } - - func fetchedResultsControllerDidPerformFetch(_ controller: FetchedResultsController<Tunnel>) { - tableView?.reloadData() - updateEmptyIndicator(controller) - } - - func fetchedResultsControllerWillChangeContent(_ controller: FetchedResultsController<Tunnel>) { - tableView?.beginUpdates() - } - - func fetchedResultsControllerDidChangeContent(_ controller: FetchedResultsController<Tunnel>) { - tableView?.endUpdates() - updateEmptyIndicator(controller) - } - - func fetchedResultsController(_ controller: FetchedResultsController<Tunnel>, didChangeObject change: FetchedResultsObjectChange<Tunnel>) { - guard let tableView = tableView else { return } - switch change { - case let .insert(_, indexPath): - tableView.insertRows(at: [indexPath], with: .automatic) - - case let .delete(_, indexPath): - tableView.deleteRows(at: [indexPath], with: .automatic) - - case let .move(_, fromIndexPath, toIndexPath): - tableView.moveRow(at: fromIndexPath, to: toIndexPath) - - case let .update(_, indexPath): - tableView.reloadRows(at: [indexPath], with: .automatic) - } - } - - func fetchedResultsController(_ controller: FetchedResultsController<Tunnel>, didChangeSection change: FetchedResultsSectionChange<Tunnel>) { - guard let tableView = tableView else { return } - switch change { - case let .insert(_, index): - tableView.insertSections(IndexSet(integer: index), with: .automatic) - - case let .delete(_, index): - tableView.deleteSections(IndexSet(integer: index), with: .automatic) - } - } - - private func updateEmptyIndicator(_ controller: FetchedResultsController<Tunnel>) { - guard let tableView = tableView else { return } - if controller.count > 0 { - tableView.backgroundView = nil - arrowImage = nil - } else { - if arrowImage == nil { - let imageView = UIImageView(image: UIImage(named: "Arrow")) - imageView.autoresizingMask = [.flexibleHeight, .flexibleWidth] - imageView.frame = tableView.bounds - imageView.contentMode = .bottomRight - tableView.backgroundView = imageView - arrowImage = imageView - } - } - } -} - -protocol TunnelTableViewCellDelegate: class { - func connect(tunnelIdentifier: String) - func disconnect(tunnelIdentifier: String) -} - -class TunnelTableViewCell: UITableViewCell { - - @IBOutlet weak var tunnelTitleLabel: UILabel! - @IBOutlet weak var activityIndicator: UIActivityIndicatorView! - @IBOutlet weak var tunnelSwitch: UISwitch! - - weak var delegate: TunnelTableViewCellDelegate? - private var tunnelIdentifier: String? - - @IBAction func tunnelSwitchChanged(_ sender: Any) { - tunnelSwitch.isEnabled = false - guard let tunnelIdentifier = tunnelIdentifier else { - return - } - - if tunnelSwitch.isOn { - delegate?.connect(tunnelIdentifier: tunnelIdentifier) - } else { - delegate?.disconnect(tunnelIdentifier: tunnelIdentifier) - } - } - - func configure(tunnel: Tunnel, status: NEVPNStatus) { - self.tunnelTitleLabel?.text = tunnel.title - tunnelIdentifier = tunnel.tunnelIdentifier - - if status == .connecting || status == .disconnecting || status == .reasserting { - activityIndicator.startAnimating() - tunnelSwitch.isHidden = true - } else { - activityIndicator.stopAnimating() - tunnelSwitch.isHidden = false - } - - tunnelSwitch.isOn = status == .connected - tunnelSwitch.onTintColor = status == .invalid || status == .reasserting ? .gray : .green - tunnelSwitch.isEnabled = true - } - - override func setEditing(_ editing: Bool, animated: Bool) { - super.setEditing(editing, animated: animated) - tunnelSwitch.isHidden = editing - } -} - -extension TunnelTableViewCell: Identifyable {} |