passepartout-apple/Passepartout-iOS/Scenes/AccountViewController.swift

311 lines
9.7 KiB
Swift
Raw Normal View History

2018-10-11 07:13:19 +00:00
//
// AccountViewController.swift
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/12/18.
2019-03-09 10:44:44 +00:00
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
2018-10-11 07:13:19 +00:00
//
2018-11-03 21:33:30 +00:00
// https://github.com/passepartoutvpn
2018-10-11 07:13:19 +00:00
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
import PassepartoutCore
import Convenience
2018-10-11 07:13:19 +00:00
protocol AccountViewControllerDelegate: class {
func accountController(_: AccountViewController, didEnterCredentials credentials: Credentials)
func accountControllerDidComplete(_: AccountViewController)
}
class AccountViewController: UIViewController, StrongTableHost {
2018-10-11 07:13:19 +00:00
@IBOutlet private weak var tableView: UITableView?
private weak var cellUsername: FieldTableViewCell?
private weak var cellPassword: FieldTableViewCell?
var currentCredentials: Credentials?
var usernamePlaceholder: String?
var infrastructureName: Infrastructure.Name? {
didSet {
reloadModel()
tableView?.reloadData()
2018-10-11 07:13:19 +00:00
}
}
var credentials: Credentials {
let username = cellUsername?.field.text ?? ""
let password = cellPassword?.field.text ?? ""
return Credentials(username, password).trimmed()
}
2019-03-03 13:11:12 +00:00
2019-04-05 14:17:34 +00:00
private var guidanceString: String? {
guard let name = infrastructureName, let metadata = InfrastructureFactory.shared.metadata(forName: name) else {
2019-04-05 14:17:34 +00:00
return nil
}
// XXX: should make this dynamic
let V = L10n.Core.Account.Sections.Guidance.Footer.Infrastructure.self
switch metadata.name {
2019-04-05 14:17:34 +00:00
case .mullvad:
return V.mullvad(metadata.description)
2019-04-05 14:17:34 +00:00
case .nordvpn:
return V.nordvpn(metadata.description)
2019-04-09 20:35:00 +00:00
2019-04-05 14:17:34 +00:00
case .pia:
return V.pia(metadata.description)
2019-04-05 14:17:34 +00:00
case .protonvpn:
return V.protonvpn(metadata.description)
2019-03-24 22:08:38 +00:00
case .tunnelbear:
return V.tunnelbear(metadata.description)
2019-04-05 14:17:34 +00:00
case .vyprvpn:
return V.vyprvpn(metadata.description)
2019-04-26 11:51:08 +00:00
2019-04-05 14:17:34 +00:00
case .windscribe:
return V.windscribe(metadata.description)
default:
return nil
2019-04-05 14:17:34 +00:00
}
}
private var guidanceURL: String? {
guard let name = infrastructureName else {
return nil
}
return AppConstants.URLs.guidances[name]
}
2019-03-03 13:11:12 +00:00
private var referralURL: String? {
guard let name = infrastructureName else {
return nil
}
return AppConstants.URLs.referrals[name]
}
2018-10-11 07:13:19 +00:00
weak var delegate: AccountViewControllerDelegate?
// MARK: StrongTableHost
2018-10-11 07:13:19 +00:00
var model: StrongTableModel<SectionType, RowType> = StrongTableModel()
2018-10-11 07:13:19 +00:00
func reloadModel() {
model.clear()
model.add(.credentials)
model.setHeader(L10n.App.Account.Sections.Credentials.header, forSection: .credentials)
model.set([.username, .password], forSection: .credentials)
2019-09-17 15:22:26 +00:00
if let _ = infrastructureName {
2019-04-05 14:17:34 +00:00
if let guidanceString = guidanceString {
if let _ = guidanceURL {
2019-04-05 14:17:34 +00:00
model.add(.guidance)
model.setFooter(guidanceString, forSection: .guidance)
model.set([.openGuide], forSection: .guidance)
} else {
model.setFooter(guidanceString, forSection: .credentials)
}
model.setHeader("", forSection: .registration)
}
2019-09-13 20:17:43 +00:00
// if let _ = referralURL {
// model.add(.registration)
// model.setFooter(L10n.Core.Account.Sections.Registration.footer(name.rawValue), forSection: .registration)
// model.set([.signUp], forSection: .registration)
2019-09-13 20:17:43 +00:00
// }
}
2018-10-11 07:13:19 +00:00
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
title = L10n.Core.Account.title
2018-10-11 07:13:19 +00:00
cellUsername?.field.text = currentCredentials?.username
cellPassword?.field.text = currentCredentials?.password
reloadModel()
2018-10-11 07:13:19 +00:00
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
cellUsername?.field.becomeFirstResponder()
}
// MARK: Actions
private func commit() {
let newCredentials = credentials
// guard !credentials.isEmpty else {
// return
// }
currentCredentials = newCredentials
delegate?.accountController(self, didEnterCredentials: newCredentials)
}
2019-04-05 14:17:34 +00:00
private func openGuidanceURL() {
guard let urlString = guidanceURL else {
return
}
UIApplication.shared.open(URL(string: urlString)!, options: [:], completionHandler: nil)
}
private func openReferralURL() {
guard let urlString = referralURL else {
return
}
UIApplication.shared.open(URL(string: urlString)!, options: [:], completionHandler: nil)
}
2018-10-11 07:13:19 +00:00
@IBAction private func done() {
view.endEditing(true)
delegate?.accountControllerDidComplete(self)
}
}
// MARK: -
extension AccountViewController: UITableViewDataSource, UITableViewDelegate, FieldTableViewCellDelegate {
enum SectionType: Int {
2018-10-22 20:17:21 +00:00
case credentials
2019-04-05 14:17:34 +00:00
case guidance
case registration
2018-10-11 07:13:19 +00:00
}
enum RowType: Int {
case username
case password
2019-04-05 14:17:34 +00:00
case openGuide
case signUp
2018-10-11 07:13:19 +00:00
}
private static let footerButtonTag = 1000
func numberOfSections(in tableView: UITableView) -> Int {
return model.numberOfSections
}
2019-04-05 14:17:34 +00:00
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return model.header(forSection: section)
2019-04-05 14:17:34 +00:00
}
2018-10-11 07:13:19 +00:00
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return model.footer(forSection: section)
2018-10-11 07:13:19 +00:00
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return model.headerHeight(for: section)
}
2018-10-11 07:13:19 +00:00
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model.numberOfRows(forSection: section)
2018-10-11 07:13:19 +00:00
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch model.row(at: indexPath) {
case .username:
2019-04-05 14:17:34 +00:00
let cell = Cells.field.dequeue(from: tableView, for: indexPath)
2018-10-11 07:13:19 +00:00
cellUsername = cell
cell.caption = L10n.Core.Account.Cells.Username.caption
cell.field.placeholder = usernamePlaceholder ?? L10n.Core.Account.Cells.Username.placeholder
2018-10-11 07:13:19 +00:00
cell.field.clearButtonMode = .always
cell.field.isSecureTextEntry = false
cell.field.text = currentCredentials?.username
cell.field.keyboardType = .emailAddress
cell.field.returnKeyType = .next
2019-03-05 08:45:29 +00:00
cell.field.textContentType = .username
2019-04-05 14:17:34 +00:00
cell.captionWidth = 120.0
cell.delegate = self
return cell
2018-10-11 07:13:19 +00:00
case .password:
2019-04-05 14:17:34 +00:00
let cell = Cells.field.dequeue(from: tableView, for: indexPath)
2018-10-11 07:13:19 +00:00
cellPassword = cell
cell.caption = L10n.Core.Account.Cells.Password.caption
cell.field.placeholder = L10n.Core.Account.Cells.Password.placeholder
2018-10-11 07:13:19 +00:00
cell.field.clearButtonMode = .always
cell.field.isSecureTextEntry = true
cell.field.text = currentCredentials?.password
cell.field.returnKeyType = .done
2019-03-05 08:45:29 +00:00
cell.field.textContentType = .password
2019-04-05 14:17:34 +00:00
cell.captionWidth = 120.0
cell.delegate = self
return cell
case .openGuide:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Core.Account.Cells.OpenGuide.caption
cell.applyAction(.current)
2019-04-05 14:17:34 +00:00
return cell
case .signUp:
guard let name = infrastructureName else {
fatalError("Sign-up shown when not a provider profile")
}
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Core.Account.Cells.Signup.caption(name)
cell.applyAction(.current)
2019-04-05 14:17:34 +00:00
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch model.row(at: indexPath) {
case .openGuide:
openGuidanceURL()
case .signUp:
openReferralURL()
default:
break
2018-10-11 07:13:19 +00:00
}
2019-04-05 14:17:34 +00:00
tableView.deselectRow(at: indexPath, animated: true)
2018-10-11 07:13:19 +00:00
}
func fieldCellDidEdit(_: FieldTableViewCell) {
commit()
}
func fieldCellDidEnter(_ cell: FieldTableViewCell) {
switch cell {
case cellUsername:
cellPassword?.field.becomeFirstResponder()
case cellPassword:
2018-10-22 20:16:59 +00:00
cellPassword?.field.resignFirstResponder()
2018-10-11 07:13:19 +00:00
done()
default:
break
}
}
}