mirror of
https://github.com/confirmedcode/Lockdown-iOS.git
synced 2025-12-21 12:14:02 +01:00
180 lines
7.8 KiB
Swift
180 lines
7.8 KiB
Swift
//
|
|
// EmailSignUpViewController.swift
|
|
// Lockdown
|
|
//
|
|
// Created by Johnny Lin on 12/12/19.
|
|
// Copyright © 2019 Confirmed Inc. All rights reserved.
|
|
//
|
|
// https://medium.com/jen-hamilton/swift-4-password-validation-helper-methods-f98a7ea5dcbb
|
|
|
|
import Foundation
|
|
import UIKit
|
|
import PopupDialog
|
|
import PromiseKit
|
|
|
|
class EmailSignUpViewController: BaseViewController, UITextFieldDelegate, Loadable {
|
|
|
|
struct Delegate {
|
|
var showSignIn: () -> Void = { }
|
|
}
|
|
|
|
var delegate = Delegate()
|
|
|
|
@IBOutlet weak var emailField: UITextField!
|
|
@IBOutlet weak var passwordField: UITextField!
|
|
@IBOutlet weak var lblPasswordValidation: UILabel!
|
|
var isPasswordValid = false
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
defaults.set(true, forKey: kHasSeenEmailSignup)
|
|
emailField.delegate = self
|
|
passwordField.delegate = self
|
|
setupToHideKeyboardOnTapOnView()
|
|
}
|
|
|
|
func setupToHideKeyboardOnTapOnView() {
|
|
let tap: UITapGestureRecognizer = UITapGestureRecognizer(
|
|
target: self,
|
|
action: #selector(self.dismissKeyboard))
|
|
tap.cancelsTouchesInView = false
|
|
view.addGestureRecognizer(tap)
|
|
}
|
|
|
|
@objc private func dismissKeyboard() {
|
|
view.endEditing(true)
|
|
}
|
|
|
|
@IBAction func passwordFieldDidChange(_ textField: UITextField) {
|
|
let passwordRequirements = """
|
|
Password must be at least 8 characters, contain at least one uppercase letter, \
|
|
one lowercase letter, one number, and one symbol.
|
|
"""
|
|
let attrStr = NSMutableAttributedString(
|
|
string: .localized(passwordRequirements),
|
|
attributes: [
|
|
.font: UIFont(name: "Montserrat-Regular", size: 11) ?? UIFont.systemFont(ofSize: 11),
|
|
.foregroundColor: UIColor.lightGray
|
|
])
|
|
|
|
if let txt = passwordField.text {
|
|
isPasswordValid = true
|
|
attrStr.addAttributes(setupAttributeColor(if: (txt.count >= 8)),
|
|
range: findRange(in: attrStr.string, for: .localized("at least 8 characters")))
|
|
attrStr.addAttributes(setupAttributeColor(if: (txt.rangeOfCharacter(from: CharacterSet.uppercaseLetters) != nil)),
|
|
range: findRange(in: attrStr.string, for: .localized("one uppercase letter")))
|
|
attrStr.addAttributes(setupAttributeColor(if: (txt.rangeOfCharacter(from: CharacterSet.lowercaseLetters) != nil)),
|
|
range: findRange(in: attrStr.string, for: .localized("one lowercase letter")))
|
|
attrStr.addAttributes(setupAttributeColor(if: (txt.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil)),
|
|
range: findRange(in: attrStr.string, for: .localized("one number")))
|
|
attrStr.addAttributes(setupAttributeColor(if: ((txt.rangeOfCharacter(from: CharacterSet.symbols) != nil)
|
|
|| (txt.rangeOfCharacter(from: CharacterSet.punctuationCharacters) != nil))),
|
|
range: findRange(in: attrStr.string, for: .localized("one symbol")))
|
|
} else {
|
|
isPasswordValid = false
|
|
}
|
|
|
|
lblPasswordValidation.attributedText = attrStr
|
|
}
|
|
|
|
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
|
if textField == emailField {
|
|
passwordField.becomeFirstResponder()
|
|
} else if textField == passwordField {
|
|
textField.resignFirstResponder()
|
|
createAccount()
|
|
}
|
|
return false
|
|
}
|
|
|
|
@IBAction func createAccount() {
|
|
// Do /signup (do subscription-event later, user needs to confirm email first though)
|
|
showLoadingView()
|
|
|
|
// TODO: client side preliminary password fields, email validation - server does additional checking later
|
|
|
|
firstly {
|
|
try Client.signup(email: self.emailField.text ?? "", password: self.passwordField.text ?? "")
|
|
}
|
|
.catch { error in
|
|
self.hideLoadingView()
|
|
if self.popupErrorAsNSURLError(error) {
|
|
return
|
|
} else if let apiError = error as? ApiError {
|
|
switch apiError.code {
|
|
case kApiCodeEmailNotConfirmed:
|
|
// This is the "correct" case for /signup, we are expecting "1" = email confirmation sent
|
|
do {
|
|
try setAPICredentials(email: self.emailField.text!, password: self.passwordField.text!)
|
|
setAPICredentialsConfirmed(confirmed: false)
|
|
let message = """
|
|
To finish signup, click the confirmation link in the email we just sent. \
|
|
If you don't see it, check if it's stuck in your spam folder.
|
|
"""
|
|
let popup = PopupDialog(title: "Confirm Your Email",
|
|
message: .localized(message),
|
|
image: nil,
|
|
buttonAlignment: .horizontal,
|
|
transitionStyle: .bounceDown,
|
|
preferredWidth: 270,
|
|
tapGestureDismissal: true,
|
|
panGestureDismissal: false,
|
|
hideStatusBar: false,
|
|
completion: nil)
|
|
popup.addButtons([
|
|
DefaultButton(title: .localizedOkay, dismissOnTap: true) {
|
|
self.hideLoadingView()
|
|
self.presentingViewController?.dismiss(animated: true, completion: nil)
|
|
}
|
|
])
|
|
self.present(popup, animated: true, completion: nil)
|
|
NotificationCenter.default.post(name: AccountUI.accountStateDidChange, object: self)
|
|
} catch {
|
|
self.showPopupDialog(
|
|
title: "Error Saving Credentials",
|
|
message: "Couldn't save credentials to local keychain. Please report this error to team@lockdownprivacy.com.",
|
|
acceptButton: "Okay")
|
|
}
|
|
default:
|
|
_ = self.popupErrorAsApiError(error)
|
|
}
|
|
} else {
|
|
self.showPopupDialog(title: .localized("Error Creating Email Account"),
|
|
message: "\(error)",
|
|
acceptButton: .localizedOkay)
|
|
}
|
|
}
|
|
}
|
|
|
|
@IBAction func signInClicked(_ sender: Any) {
|
|
dismiss(animated: true, completion: {
|
|
self.delegate.showSignIn()
|
|
})
|
|
}
|
|
|
|
func setupAttributeColor(if isValid: Bool) -> [NSAttributedString.Key: Any] {
|
|
if isValid {
|
|
return [NSAttributedString.Key.foregroundColor: UIColor.lightGray]
|
|
} else {
|
|
isPasswordValid = false
|
|
return [NSAttributedString.Key.foregroundColor: UIColor.red]
|
|
}
|
|
}
|
|
|
|
func findRange(in baseString: String, for substring: String) -> NSRange {
|
|
if let range = baseString.localizedStandardRange(of: substring) {
|
|
let startIndex = baseString.distance(from: baseString.startIndex, to: range.lowerBound)
|
|
let length = substring.count
|
|
return NSRange(location: startIndex, length: length)
|
|
} else {
|
|
print("Range does not exist in the base string.")
|
|
return NSRange(location: 0, length: 0)
|
|
}
|
|
}
|
|
|
|
@IBAction func cancelTapped(_ sender: Any) {
|
|
self.dismiss(animated: true, completion: nil)
|
|
}
|
|
|
|
}
|