TrustedNetworksViewController.swift 13.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//
//  TrustedNetworksViewController.swift
//  PIA VPN
//
//  Created by Jose Antonio Blaya Garcia on 18/12/2018.
//  Copyright © 2018 London Trust Media. All rights reserved.
//

import UIKit
import PIALibrary

class TrustedNetworksViewController: AutolayoutViewController {

    @IBOutlet private weak var tableView: UITableView!
    private var availableNetworks: [String] = []
    private var trustedNetworks: [String] = []
    private let currentNetwork: String? = nil
    private var hotspotHelper: PIAHotspotHelper!
    private lazy var switchWiFiProtection = UISwitch()
    private lazy var switchAutoJoinAllNetworks = UISwitch()
21
    private lazy var switchCellularData = UISwitch()
Jose Blaya's avatar
Jose Blaya committed
22
    private lazy var switchRules = UISwitch()
Jose Blaya's avatar
Jose Blaya committed
23 24
    var shouldReconnectAutomatically = false
    var hasUpdatedPreferences = false
25 26

    private enum Sections: Int, EnumsBuilder {
27
        
28 29
        case rules = 0
        case cellularData
30
        case useVpnWifiProtection
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
        case autoConnectAllNetworksSettings
        case current
        case available
        case trusted
    }
    
    private struct Cells {
        static let network = "NetworkCell"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = L10n.Settings.Hotspothelper.title
        self.hotspotHelper = PIAHotspotHelper(withDelegate: self)
        self.switchAutoJoinAllNetworks.addTarget(self, action: #selector(toggleAutoconnectWithAllNetworks(_:)), for: .valueChanged)
        self.switchWiFiProtection.addTarget(self, action: #selector(toggleUseWiFiProtection(_:)), for: .valueChanged)
47
        self.switchCellularData.addTarget(self, action: #selector(toggleCellularData(_:)), for: .valueChanged)
Jose Blaya's avatar
Jose Blaya committed
48
        self.switchRules.addTarget(self, action: #selector(toggleRules(_:)), for: .valueChanged)
49

Jose Blaya's avatar
Jose Blaya committed
50
        NotificationCenter.default.addObserver(self, selector: #selector(filterAvailableNetworks), name: UIApplication.didBecomeActiveNotification, object: nil)
51

52 53 54 55 56 57 58 59
        configureTableView()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        filterAvailableNetworks()
    }
    
Jose Blaya's avatar
Jose Blaya committed
60 61 62 63 64 65 66 67 68 69
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if shouldReconnectAutomatically,
            hasUpdatedPreferences{
            NotificationCenter.default.post(name: .PIASettingsHaveChanged,
                                            object: self,
                                            userInfo: nil)
        }
    }
    
70 71 72 73 74 75 76 77 78 79 80 81
    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    // MARK: Restylable
    
    override func viewShouldRestyle() {
        super.viewShouldRestyle()
        
        styleNavigationBarWithTitle(L10n.Settings.Hotspothelper.title)

        if let viewContainer = viewContainer {
Jose Blaya's avatar
Jose Blaya committed
82
            Theme.current.applyPrincipalBackground(viewContainer)
83
        }
Jose Blaya's avatar
Jose Blaya committed
84
        Theme.current.applyPrincipalBackground(tableView)
85 86 87 88 89 90 91
        Theme.current.applyDividerToSeparator(tableView)
    }
    
    @objc private func toggleAutoconnectWithAllNetworks(_ sender: UISwitch) {
        let preferences = Client.preferences.editable()
        preferences.shouldConnectForAllNetworks = sender.isOn
        preferences.commit()
Jose Blaya's avatar
Jose Blaya committed
92
        hasUpdatedPreferences = true
93 94 95 96 97 98
    }
    
    @objc private func toggleUseWiFiProtection(_ sender: UISwitch) {
        let preferences = Client.preferences.editable()
        preferences.useWiFiProtection = sender.isOn
        preferences.commit()
Jose Blaya's avatar
Jose Blaya committed
99
        hasUpdatedPreferences = true
100
        filterAvailableNetworks()
101 102 103 104 105 106
        if sender.isOn, //If toggle is ON
            let ssid = UIDevice.current.WiFiSSID, //And we are connected to the WiFi
            Client.providers.vpnProvider.vpnStatus == .disconnected, //And we are disconnected
            !Client.preferences.trustedNetworks.contains(ssid) { // And the network is not one of the trustedNetworks
            requestPermissionToConnectVPN() // Show alert to connect the VPN
        }
107 108
    }

109 110
    @objc private func toggleCellularData(_ sender: UISwitch) {
        let preferences = Client.preferences.editable()
111
        preferences.trustCellularData = !sender.isOn
112
        preferences.commit()
Jose Blaya's avatar
Jose Blaya committed
113
        hasUpdatedPreferences = true
114
    }
Jose Blaya's avatar
Jose Blaya committed
115 116 117 118 119 120 121 122 123
    
    @objc private func toggleRules(_ sender: UISwitch) {
        let preferences = Client.preferences.editable()
        preferences.nmtRulesEnabled = sender.isOn
        preferences.commit()
        hasUpdatedPreferences = true
        tableView.reloadData()
    }

124

125 126 127
    // MARK: Private Methods
    private func configureTableView() {
        if #available(iOS 11, *) {
Jose Blaya's avatar
Jose Blaya committed
128
            tableView.sectionFooterHeight = UITableView.automaticDimension
129 130 131 132
            tableView.estimatedSectionFooterHeight = 1.0
        }
        filterAvailableNetworks()
    }
133 134
    
    @objc private func filterAvailableNetworks() {
135 136 137 138 139 140
        self.availableNetworks = Client.preferences.availableNetworks
        self.trustedNetworks = Client.preferences.trustedNetworks
        self.availableNetworks = self.availableNetworks.filter { !self.trustedNetworks.contains($0) }
        self.tableView.reloadData()
    }
    
141 142 143 144
    private func requestPermissionToConnectVPN() {
        let alert = Macros.alert(L10n.Settings.Hotspothelper.title,
                                 L10n.Settings.Trusted.Networks.Connect.message)
        alert.addCancelAction(L10n.Global.close)
145
        alert.addActionWithTitle(L10n.Global.ok) {
146 147 148
            Macros.dispatch(after: .milliseconds(200)) {
                Client.providers.vpnProvider.connect(nil)
            }
149
        }
150 151 152
        present(alert, animated: true, completion: nil)
    }
    
153 154 155
}

extension TrustedNetworksViewController: UITableViewDelegate, UITableViewDataSource {
156

157
    func numberOfSections(in tableView: UITableView) -> Int {
Jose Blaya's avatar
Jose Blaya committed
158 159 160 161 162
        if Client.preferences.nmtRulesEnabled {
            return Client.preferences.useWiFiProtection ? Sections.countCases() : 3
        } else {
            return 1
        }
163 164 165 166 167
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        switch Sections.objectIdentifyBy(index: section) {
        case .useVpnWifiProtection:
168
            return L10n.Settings.Hotspothelper.Wifi.networks.uppercased()
169 170 171 172 173 174
        case .current:
            return L10n.Settings.Trusted.Networks.Sections.current.uppercased()
        case .available:
            return L10n.Settings.Trusted.Networks.Sections.available.uppercased()
        case .trusted:
            return L10n.Settings.Trusted.Networks.Sections.trusted.uppercased()
175 176
        case .cellularData:
            return L10n.Settings.Hotspothelper.Cellular.networks.uppercased()
Jose Blaya's avatar
Jose Blaya committed
177 178
        case .rules:
            return L10n.Settings.Hotspothelper.title.uppercased()
179 180 181 182 183 184 185 186 187 188 189 190 191
        default:
            return nil
        }
    }
    
    func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        switch Sections.objectIdentifyBy(index: section) {
        case .useVpnWifiProtection:
            return L10n.Settings.Hotspothelper.Enable.description
        case .trusted:
            return L10n.Settings.Trusted.Networks.message
        case .autoConnectAllNetworksSettings:
            return L10n.Settings.Hotspothelper.All.description
192 193
        case .cellularData:
            return L10n.Settings.Hotspothelper.Cellular.description
194 195 196 197
        case .available:
            return availableNetworks.isEmpty ?
                L10n.Settings.Hotspothelper.Available.help :
                L10n.Settings.Hotspothelper.Available.Add.help
Jose Blaya's avatar
Jose Blaya committed
198 199
        case .rules:
            return L10n.Settings.Trusted.Networks.Sections.Trusted.Rule.description
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
        default:
            return nil
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch Sections.objectIdentifyBy(index: section) {
        case .current:
            return hotspotHelper.currentWiFiNetwork() != nil ? 1 : 0
        case .available:
            return availableNetworks.count
        case .trusted:
            return trustedNetworks.count
        default:
            return 1
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: Cells.network, for: indexPath)
        cell.selectionStyle = .default
221
        cell.accessoryType = .none
222 223 224 225 226 227
        cell.accessoryView = nil
        cell.isUserInteractionEnabled = true
        cell.imageView?.image = Asset.iconWifi.image.withRenderingMode(.alwaysTemplate)
        cell.imageView?.tintColor = Theme.current.palette.textColor(forRelevance: 3, appearance: .dark)

        switch Sections.objectIdentifyBy(index: indexPath.section) {
228 229
        case .rules:
            cell.imageView?.image = nil
Jose Blaya's avatar
Jose Blaya committed
230 231 232 233
            cell.textLabel?.text = L10n.Global.enabled
            cell.accessoryView = switchRules
            cell.selectionStyle = .none
            switchRules.isOn = Client.preferences.nmtRulesEnabled
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
        case .current:
            if let ssid = hotspotHelper.currentWiFiNetwork() {
                if trustedNetworks.contains(ssid) {
                    cell.isUserInteractionEnabled = false
                } else {
                    cell.accessoryView = UIImageView(image: Asset.iconAdd.image)
                }
                cell.textLabel?.text = ssid
            }
        case .available:
            cell.accessoryView = UIImageView(image: Asset.iconAdd.image)
            cell.textLabel?.text = availableNetworks[indexPath.row]
        case .trusted:
            cell.accessoryView = UIImageView(image: Asset.iconRemove.image)
            cell.textLabel?.text = trustedNetworks[indexPath.row]
        case .autoConnectAllNetworksSettings:
            cell.imageView?.image = nil
            cell.textLabel?.text = L10n.Settings.Hotspothelper.All.title
            cell.accessoryView = switchAutoJoinAllNetworks
            cell.selectionStyle = .none
            switchAutoJoinAllNetworks.isOn = Client.preferences.shouldConnectForAllNetworks
        case .useVpnWifiProtection:
            cell.imageView?.image = nil
257
            cell.textLabel?.text = L10n.Settings.Hotspothelper.Wifi.Trust.title
258 259 260
            cell.accessoryView = switchWiFiProtection
            cell.selectionStyle = .none
            switchWiFiProtection.isOn = Client.preferences.useWiFiProtection
261 262 263 264 265 266
        case .cellularData:
            cell.imageView?.image = nil
            cell.textLabel?.text = L10n.Settings.Hotspothelper.Cellular.title
            cell.detailTextLabel?.text = nil
            cell.accessoryView = switchCellularData
            cell.selectionStyle = .none
267
            switchCellularData.isOn = !Client.preferences.trustCellularData
268 269 270 271

        }

        cell.textLabel?.backgroundColor = .clear
Jose Blaya's avatar
Jose Blaya committed
272
        Theme.current.applySecondaryBackground(cell)
273
        Theme.current.applyDetailTableCell(cell)
Jose Blaya's avatar
Jose Blaya committed
274 275 276 277 278
        if let textLabel = cell.textLabel {
            Theme.current.applySettingsCellTitle(textLabel,
                                                 appearance: .dark)
            textLabel.backgroundColor = .clear
        }
279 280

        let backgroundView = UIView()
Jose Blaya's avatar
Jose Blaya committed
281
        Theme.current.applyPrincipalBackground(backgroundView)
282 283 284 285 286 287 288 289 290 291 292
        cell.selectedBackgroundView = backgroundView

        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        switch Sections.objectIdentifyBy(index: indexPath.section) {
        case .current:
            if let ssid = hotspotHelper.currentWiFiNetwork() {
                hotspotHelper.saveTrustedNetwork(ssid)
Jose Blaya's avatar
Jose Blaya committed
293
                hasUpdatedPreferences = true
294 295 296 297
            }
        case .available:
            let ssid = availableNetworks[indexPath.row]
            hotspotHelper.saveTrustedNetwork(ssid)
Jose Blaya's avatar
Jose Blaya committed
298
            hasUpdatedPreferences = true
299 300 301
        case .trusted:
            let ssid = trustedNetworks[indexPath.row]
            hotspotHelper.removeTrustedNetwork(ssid)
Jose Blaya's avatar
Jose Blaya committed
302
            hasUpdatedPreferences = true
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
        default:
            break
        }
        filterAvailableNetworks()
    }
    
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        switch Sections.objectIdentifyBy(index: indexPath.section) {
        case .trusted:
            return true
        default:
            return false
        }
    }
    
Jose Blaya's avatar
Jose Blaya committed
318
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
319 320 321
        if editingStyle == .delete {
            let ssid = trustedNetworks[indexPath.row]
            hotspotHelper.removeTrustedNetwork(ssid)
Jose Blaya's avatar
Jose Blaya committed
322
            hasUpdatedPreferences = true
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
            filterAvailableNetworks()
        }
    }
    
    func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
        return L10n.Global.clear
    }
    
    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        Theme.current.applyTableSectionHeader(view)
    }
    
    func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
        Theme.current.applyTableSectionFooter(view)
    }

}

extension TrustedNetworksViewController: PIAHotspotHelperDelegate{
    
    func refreshAvailableNetworks(_ networks: [String]?) {
        if let networks = networks {
            self.availableNetworks = networks
            self.tableView.reloadData()
        }
    }
    
}