aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/WireGuard/UI/iOS/ViewController/MainViewController.swift
diff options
context:
space:
mode:
Diffstat (limited to 'WireGuard/WireGuard/UI/iOS/ViewController/MainViewController.swift')
-rw-r--r--WireGuard/WireGuard/UI/iOS/ViewController/MainViewController.swift129
1 files changed, 129 insertions, 0 deletions
diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/MainViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/MainViewController.swift
new file mode 100644
index 0000000..82e6f81
--- /dev/null
+++ b/WireGuard/WireGuard/UI/iOS/ViewController/MainViewController.swift
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2018 WireGuard LLC. All Rights Reserved.
+
+import UIKit
+
+class MainViewController: UISplitViewController {
+
+ var tunnelsManager: TunnelsManager?
+ var onTunnelsManagerReady: ((TunnelsManager) -> Void)?
+
+ var tunnelsListVC: TunnelsListTableViewController?
+
+ init() {
+ let detailVC = UIViewController()
+ detailVC.view.backgroundColor = .white
+ let detailNC = UINavigationController(rootViewController: detailVC)
+
+ let masterVC = TunnelsListTableViewController()
+ let masterNC = UINavigationController(rootViewController: masterVC)
+
+ tunnelsListVC = masterVC
+
+ super.init(nibName: nil, bundle: nil)
+
+ viewControllers = [ masterNC, detailNC ]
+
+ // State restoration
+ restorationIdentifier = "MainVC"
+ masterNC.restorationIdentifier = "MasterNC"
+ detailNC.restorationIdentifier = "DetailNC"
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override func viewDidLoad() {
+ delegate = self
+
+ // On iPad, always show both masterVC and detailVC, even in portrait mode, like the Settings app
+ preferredDisplayMode = .allVisible
+
+ // Create the tunnels manager, and when it's ready, inform tunnelsListVC
+ TunnelsManager.create { [weak self] result in
+ guard let self = self else { return }
+
+ if let error = result.error {
+ ErrorPresenter.showErrorAlert(error: error, from: self)
+ return
+ }
+ let tunnelsManager: TunnelsManager = result.value!
+
+ self.tunnelsManager = tunnelsManager
+ self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
+
+ tunnelsManager.activationDelegate = self
+
+ self.onTunnelsManagerReady?(tunnelsManager)
+ self.onTunnelsManagerReady = nil
+ }
+ }
+}
+
+extension MainViewController: TunnelsManagerActivationDelegate {
+ func tunnelActivationAttemptFailed(tunnel: TunnelContainer, error: TunnelsManagerActivationAttemptError) {
+ ErrorPresenter.showErrorAlert(error: error, from: self)
+ }
+
+ func tunnelActivationAttemptSucceeded(tunnel: TunnelContainer) {
+ // Nothing to do
+ }
+
+ func tunnelActivationFailed(tunnel: TunnelContainer, error: TunnelsManagerActivationError) {
+ ErrorPresenter.showErrorAlert(error: error, from: self)
+ }
+
+ func tunnelActivationSucceeded(tunnel: TunnelContainer) {
+ // Nothing to do
+ }
+}
+
+extension MainViewController {
+ func refreshTunnelConnectionStatuses() {
+ if let tunnelsManager = tunnelsManager {
+ tunnelsManager.refreshStatuses()
+ }
+ }
+
+ func showTunnelDetailForTunnel(named tunnelName: String, animated: Bool) {
+ let showTunnelDetailBlock: (TunnelsManager) -> Void = { [weak self] tunnelsManager in
+ if let tunnel = tunnelsManager.tunnel(named: tunnelName) {
+ let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager, tunnel: tunnel)
+ let tunnelDetailNC = UINavigationController(rootViewController: tunnelDetailVC)
+ tunnelDetailNC.restorationIdentifier = "DetailNC"
+ if let self = self {
+ if animated {
+ self.showDetailViewController(tunnelDetailNC, sender: self)
+ } else {
+ UIView.performWithoutAnimation {
+ self.showDetailViewController(tunnelDetailNC, sender: self)
+ }
+ }
+ }
+ }
+ }
+ if let tunnelsManager = tunnelsManager {
+ showTunnelDetailBlock(tunnelsManager)
+ } else {
+ onTunnelsManagerReady = showTunnelDetailBlock
+ }
+ }
+}
+
+extension MainViewController: UISplitViewControllerDelegate {
+ func splitViewController(_ splitViewController: UISplitViewController,
+ collapseSecondary secondaryViewController: UIViewController,
+ onto primaryViewController: UIViewController) -> Bool {
+ // On iPhone, if the secondaryVC (detailVC) is just a UIViewController, it indicates that it's empty,
+ // so just show the primaryVC (masterVC).
+ let detailVC = (secondaryViewController as? UINavigationController)?.viewControllers.first
+ let isDetailVCEmpty: Bool
+ if let detailVC = detailVC {
+ isDetailVCEmpty = (type(of: detailVC) == UIViewController.self)
+ } else {
+ isDetailVCEmpty = true
+ }
+ return isDetailVCEmpty
+ }
+}