From 737993ccd2a2796a2ef35fdd27413bd40e526639 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 24 Apr 2023 15:01:53 -0400 Subject: [PATCH] Adding Protocol picker and making changes to region picker --- .../BraveVPNPickerViewController.swift | 115 ++++++++++++++++++ ...BraveVPNProtocolPickerViewController.swift | 85 +++++++++++++ .../BraveVPNRegionPickerViewController.swift | 108 +++------------- .../BraveVPNSettingsViewController.swift | 2 +- 4 files changed, 215 insertions(+), 95 deletions(-) create mode 100644 Sources/BraveVPN/BraveVPNPickerViewController.swift create mode 100644 Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift diff --git a/Sources/BraveVPN/BraveVPNPickerViewController.swift b/Sources/BraveVPN/BraveVPNPickerViewController.swift new file mode 100644 index 00000000000..6c22c13c6fe --- /dev/null +++ b/Sources/BraveVPN/BraveVPNPickerViewController.swift @@ -0,0 +1,115 @@ +// Copyright 2020 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import UIKit +import Shared +import BraveUI +import Lottie +import NetworkExtension +import GuardianConnect + +class BraveVPNPickerViewController: UIViewController { + + private var overlayView: UIView? + let tableView: UITableView = .init(frame: .zero, style: .insetGrouped) + + deinit { + NotificationCenter.default.removeObserver(self) + } + + var isLoading: Bool = false { + didSet { + overlayView?.removeFromSuperview() + + navigationItem.hidesBackButton = isLoading + + // Prevent dismissing the modal by swipe when the VPN is being configured + navigationController?.isModalInPresentation = isLoading + + if !isLoading { return } + + let overlay = UIView().then { + $0.backgroundColor = UIColor.black.withAlphaComponent(0.5) + let activityIndicator = UIActivityIndicatorView().then { indicator in + indicator.startAnimating() + indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight] + } + + $0.addSubview(activityIndicator) + } + + view.addSubview(overlay) + overlay.snp.makeConstraints { + $0.edges.equalToSuperview() + } + + overlayView = overlay + } + } + + init() { + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError() } + + override func viewDidLoad() { + tableView.register(VPNRegionCell.self) + + NotificationCenter.default.addObserver(self, selector: #selector(vpnConfigChanged(notification:)), + name: .NEVPNStatusDidChange, object: nil) + + view.addSubview(tableView) + tableView.snp.makeConstraints { + $0.edges.equalToSuperview() + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + tableView.reloadData() + } + + @objc func vpnConfigChanged(notification: NSNotification) { + } + + func showSuccessAlert() { + let animation = AnimationView(name: "vpncheckmark", bundle: .module).then { + $0.bounds = CGRect(x: 0, y: 0, width: 300, height: 200) + $0.contentMode = .scaleAspectFill + $0.play() + } + + let popup = AlertPopupView(imageView: animation, + title: Strings.VPN.regionSwitchSuccessPopupText, message: "", + titleWeight: .semibold, titleSize: 18, + dismissHandler: { true }) + + popup.showWithType(showType: .flyUp, autoDismissTime: 1.5) + } + + func showErrorAlert(title: String, message: String?) { + let alert = AlertController(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage, + preferredStyle: .alert) + let okAction = UIAlertAction(title: Strings.OKString, style: .default) { _ in + self.dismiss(animated: true) + } + alert.addAction(okAction) + + present(alert, animated: true) + } +} + +class VPNRegionCell: UITableViewCell, TableViewReusable { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: .value1, reuseIdentifier: reuseIdentifier) + } + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError() + } +} diff --git a/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift new file mode 100644 index 00000000000..5ccdfb4813d --- /dev/null +++ b/Sources/BraveVPN/BraveVPNProtocolPickerViewController.swift @@ -0,0 +1,85 @@ +// Copyright 2023 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import UIKit +import Shared +import BraveUI +import Lottie +import NetworkExtension +import GuardianConnect + +class BraveVPNProtocolPickerViewController: BraveVPNPickerViewController { + + private let regionList: [GRDRegion] + + /// This group monitors vpn connection status. + private var dispatchGroup: DispatchGroup? + private var vpnRegionChangeSuccess = false + + override init() { + self.regionList = BraveVPN.regions + .sorted { $0.displayName < $1.displayName } + + super.init() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError() } + + override func viewDidLoad() { + title = "Transport Protocol" + + tableView.delegate = self + tableView.dataSource = self + + super.viewDidLoad() + } + + override func vpnConfigChanged(notification: NSNotification) { + guard let connection = notification.object as? NEVPNConnection else { return } + + if connection.status == .connected { + dispatchGroup?.leave() + self.vpnRegionChangeSuccess = true + dispatchGroup = nil + } + } +} + +// MARK: - UITableView Data Source & Delegate + +extension BraveVPNProtocolPickerViewController: UITableViewDelegate, UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + regionList.count + } + + func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { + return "Please select your preferred transport protocol. Once switched your existing VPN credentials will be cleared and you will be reconnected if a VPN connection is currently established" + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(for: indexPath) as VPNRegionCell + cell.accessoryType = .none + + guard let server = regionList[safe: indexPath.row] else { return cell } + cell.textLabel?.text = server.displayName + + if server.displayName == BraveVPN.selectedRegion?.displayName { + cell.accessoryType = .checkmark + } + + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + } +} diff --git a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift index 731779cf099..0060bd5c3cb 100644 --- a/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift +++ b/Sources/BraveVPN/BraveVPNRegionPickerViewController.swift @@ -10,10 +10,7 @@ import Lottie import NetworkExtension import GuardianConnect -class BraveVPNRegionPickerViewController: UIViewController { - - private var overlayView: UIView? - private let tableView: UITableView = .init(frame: .zero, style: .insetGrouped) +class BraveVPNRegionPickerViewController: BraveVPNPickerViewController { private let regionList: [GRDRegion] private enum Section: Int, CaseIterable { @@ -21,49 +18,15 @@ class BraveVPNRegionPickerViewController: UIViewController { case regionList } - deinit { - NotificationCenter.default.removeObserver(self) - } - /// This group monitors vpn connection status. private var dispatchGroup: DispatchGroup? private var vpnRegionChangeSuccess = false - private var isLoading: Bool = false { - didSet { - overlayView?.removeFromSuperview() - - navigationItem.hidesBackButton = isLoading - - // Prevent dismissing the modal by swipe when the VPN is being configured - navigationController?.isModalInPresentation = isLoading - - if !isLoading { return } - - let overlay = UIView().then { - $0.backgroundColor = UIColor.black.withAlphaComponent(0.5) - let activityIndicator = UIActivityIndicatorView().then { indicator in - indicator.startAnimating() - indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight] - } - - $0.addSubview(activityIndicator) - } - - view.addSubview(overlay) - overlay.snp.makeConstraints { - $0.edges.equalToSuperview() - } - - overlayView = overlay - } - } - - init() { + override init() { self.regionList = BraveVPN.regions .sorted { $0.displayName < $1.displayName } - super.init(nibName: nil, bundle: nil) + super.init() } @available(*, unavailable) @@ -74,18 +37,11 @@ class BraveVPNRegionPickerViewController: UIViewController { tableView.delegate = self tableView.dataSource = self - tableView.register(VPNRegionCell.self) - NotificationCenter.default.addObserver(self, selector: #selector(vpnConfigChanged(notification:)), - name: .NEVPNStatusDidChange, object: nil) - - view.addSubview(tableView) - tableView.snp.makeConstraints { - $0.edges.equalToSuperview() - } + super.viewDidLoad() } - @objc private func vpnConfigChanged(notification: NSNotification) { + override func vpnConfigChanged(notification: NSNotification) { guard let connection = notification.object as? NEVPNConnection else { return } if connection.status == .connected { @@ -94,15 +50,12 @@ class BraveVPNRegionPickerViewController: UIViewController { dispatchGroup = nil } } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - tableView.reloadData() - } } // MARK: - UITableView Data Source & Delegate + extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { Section.allCases.count } @@ -167,24 +120,13 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa BraveVPN.changeVPNRegion(to: newRegion) { [weak self] success in guard let self = self else { return } - func _showError() { + if !success { DispatchQueue.main.async { - let alert = AlertController(title: Strings.VPN.regionPickerErrorTitle, - message: Strings.VPN.regionPickerErrorMessage, - preferredStyle: .alert) - let okAction = UIAlertAction(title: Strings.OKString, style: .default) { _ in - self.dismiss(animated: true) - } - alert.addAction(okAction) - - self.present(alert, animated: true) + self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage) } } - if !success { - _showError() - } - // Changing vpn server settings takes lot of time, // and nothing we can do about it as it relies on Apple apis. // Here we observe vpn status and we show success alert if it connected, @@ -205,34 +147,12 @@ extension BraveVPNRegionPickerViewController: UITableViewDelegate, UITableViewDa self.showSuccessAlert() } } else { - _showError() + DispatchQueue.main.async { + self.showErrorAlert(title: Strings.VPN.regionPickerErrorTitle, + message: Strings.VPN.regionPickerErrorMessage) + } } } } } - - private func showSuccessAlert() { - let animation = AnimationView(name: "vpncheckmark", bundle: .module).then { - $0.bounds = CGRect(x: 0, y: 0, width: 300, height: 200) - $0.contentMode = .scaleAspectFill - $0.play() - } - - let popup = AlertPopupView(imageView: animation, - title: Strings.VPN.regionSwitchSuccessPopupText, message: "", - titleWeight: .semibold, titleSize: 18, - dismissHandler: { true }) - - popup.showWithType(showType: .flyUp, autoDismissTime: 1.5) - } -} - -private class VPNRegionCell: UITableViewCell, TableViewReusable { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: .value1, reuseIdentifier: reuseIdentifier) - } - @available(*, unavailable) - required init(coder: NSCoder) { - fatalError() - } } diff --git a/Sources/BraveVPN/BraveVPNSettingsViewController.swift b/Sources/BraveVPN/BraveVPNSettingsViewController.swift index 20371712a11..2ba6948f0a2 100644 --- a/Sources/BraveVPN/BraveVPNSettingsViewController.swift +++ b/Sources/BraveVPN/BraveVPNSettingsViewController.swift @@ -285,7 +285,7 @@ public class BraveVPNSettingsViewController: TableViewController { } private func selectProtocolTapped() { - let vc = BraveVPNRegionPickerViewController() + let vc = BraveVPNProtocolPickerViewController() navigationController?.pushViewController(vc, animated: true) }