diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-12-09 16:35:26 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-12-10 11:14:56 +0100 |
| commit | de7b23a3f9d90b43dc3575c011d081e928f2e5ac (patch) | |
| tree | 9e5fff2a5afd5aa94c071df30aa070ba9a5f7222 | |
| parent | 87eeab54df529f6129da48eba32fbbc4c196649d (diff) | |
| download | mullvadvpn-de7b23a3f9d90b43dc3575c011d081e928f2e5ac.tar.xz mullvadvpn-de7b23a3f9d90b43dc3575c011d081e928f2e5ac.zip | |
Wireup Connect controller with the tunnel manager
| -rw-r--r-- | ios/MullvadVPN/ConnectViewController.swift | 138 |
1 files changed, 135 insertions, 3 deletions
diff --git a/ios/MullvadVPN/ConnectViewController.swift b/ios/MullvadVPN/ConnectViewController.swift index d7b615b3fb..8e9c4f09b7 100644 --- a/ios/MullvadVPN/ConnectViewController.swift +++ b/ios/MullvadVPN/ConnectViewController.swift @@ -6,27 +6,159 @@ // Copyright © 2019 Amagicom AB. All rights reserved. // +import Combine import UIKit +import NetworkExtension +import os -class ConnectViewController: UIViewController, RootContainment { +class ConnectViewController: UIViewController, RootContainment, TunnelControlViewControllerDelegate { + + @IBOutlet var secureLabel: UILabel! + @IBOutlet var countryLabel: UILabel! + + private var setRelaysSubscriber: AnyCancellable? + private var startStopTunnelSubscriber: AnyCancellable? + private var tunnelStateSubscriber: AnyCancellable? override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } var preferredHeaderBarStyle: HeaderBarStyle { - return .unsecured + switch tunnelState { + case .connecting, .reconnecting, .connected: + return .secured + + case .disconnecting, .disconnected: + return .unsecured + } + } + + private var tunnelState: TunnelState = .disconnected { + didSet { + setNeedsHeaderBarStyleAppearanceUpdate() + updateSecureLabel() + updateTunnelConnectionInfo() + } } override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. + + tunnelStateSubscriber = TunnelManager.shared.$tunnelState + .receive(on: DispatchQueue.main) + .assign(to: \.tunnelState, on: self) + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if case .embedTunnelControls = SegueIdentifier.Connect.from(segue: segue) { + let tunnelControlController = segue.destination as! TunnelControlViewController + tunnelControlController.view.translatesAutoresizingMaskIntoConstraints = false + tunnelControlController.delegate = self + } + } + + // MARK: - TunnelControlViewControllerDelegate + + func tunnelControlViewController(_ controller: TunnelControlViewController, handleAction action: TunnelControlAction) { + switch action { + case .connect: + connectTunnel() + + case .disconnect: + disconnectTunnel() + + case .selectLocation: + performSegue(withIdentifier: SegueIdentifier.Connect.showRelaySelector.rawValue, sender: self) + } + } + + // MARK: - Private + + private func updateSecureLabel() { + secureLabel.text = tunnelState.textForSecureLabel() + secureLabel.textColor = tunnelState.textColorForSecureLabel() + } + + private func updateTunnelConnectionInfo() { + switch tunnelState { + case .connected(let connectionInfo), + .reconnecting(let connectionInfo): + countryLabel.text = "\(connectionInfo.hostname)\nIn: \(connectionInfo.ipv4Relay)" + + case .connecting, .disconnected, .disconnecting: + countryLabel.text = "" + } + } + + private func connectTunnel() { + startStopTunnelSubscriber = TunnelManager.shared.startTunnel() + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { (completion) in + if case .failure(let error) = completion { + os_log(.error, "Failed to start the tunnel: %{public}s", error.localizedDescription) + } + }) + } + + private func disconnectTunnel() { + startStopTunnelSubscriber = TunnelManager.shared.stopTunnel() + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { (_) in + // no-op + }) } // MARK: - Actions @IBAction func unwindFromSelectLocation(segue: UIStoryboardSegue) { + guard let selectLocationController = segue.source as? SelectLocationController else { return } + guard let selectedItem = selectLocationController.selectedItem else { return } + + let relayConstraints = RelayConstraints(location: .only(selectedItem.relayLocation)) + + setRelaysSubscriber = TunnelManager.shared.setRelayConstraints(relayConstraints) + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { (completion) in + switch completion { + case .finished: + os_log(.debug, "Updated relay constraints: %{public}s", String(reflecting: relayConstraints)) + self.connectTunnel() + + case .failure(let error): + os_log(.error, "Failed to update relay constraints: %{public}s", error.localizedDescription) + } + }) + } + +} + +private extension TunnelState { + + func textColorForSecureLabel() -> UIColor { + switch self { + case .connecting, .reconnecting: + return .white + + case .connected: + return .successColor + + case .disconnecting, .disconnected: + return .dangerColor + } + } + + func textForSecureLabel() -> String { + switch self { + case .connecting, .reconnecting: + return NSLocalizedString("Creating secure connection", tableName: "Connect", comment: "") + + case .connected: + return NSLocalizedString("Secure connection", tableName: "Connect", comment: "") + case .disconnecting, .disconnected: + return NSLocalizedString("Unsecured connection", tableName: "Connect", comment: "") + } } } |
