221 lines
5.9 KiB
Swift
221 lines
5.9 KiB
Swift
|
|
||
|
import UIKit
|
||
|
import KeychainAccess
|
||
|
|
||
|
final class AuthViewController: UIViewController {
|
||
|
|
||
|
override var prefersStatusBarHidden: Bool {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
private enum TextFieldTag: Int {
|
||
|
case email
|
||
|
case password
|
||
|
}
|
||
|
|
||
|
@IBOutlet weak var txtSecret: UITextField!
|
||
|
@IBOutlet weak var imgBio: UIImageView!
|
||
|
@IBOutlet weak var lblSecret: UILabel!
|
||
|
@IBOutlet weak var containerView: UIView!
|
||
|
@IBOutlet weak var emailField: UITextField!
|
||
|
@IBOutlet weak var passwordField: UITextField!
|
||
|
@IBOutlet weak var titleLabel: UILabel!
|
||
|
@IBOutlet weak var signInButton: UIButton!
|
||
|
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
|
||
|
|
||
|
let keychain = Keychain(service: "com.zadanie.bsm")
|
||
|
|
||
|
override func viewDidLoad() {
|
||
|
super.viewDidLoad()
|
||
|
|
||
|
if(biometricType == .touchID) {
|
||
|
imgBio.image = UIImage(named: "TouchID")
|
||
|
} else if(biometricType == .faceID) {
|
||
|
imgBio.image = UIImage(named: "FaceID")
|
||
|
} else if(biometricType == .none) {
|
||
|
print("Nie ma biometrycznego czytnika")
|
||
|
}
|
||
|
|
||
|
containerView.transform = CGAffineTransform(scaleX: 0, y: 0)
|
||
|
containerView.backgroundColor = .rwGreen
|
||
|
containerView.layer.cornerRadius = 7
|
||
|
|
||
|
emailField.delegate = self
|
||
|
emailField.tintColor = .rwGreen
|
||
|
emailField.tag = TextFieldTag.email.rawValue
|
||
|
|
||
|
passwordField.delegate = self
|
||
|
passwordField.tintColor = .rwGreen
|
||
|
passwordField.tag = TextFieldTag.password.rawValue
|
||
|
|
||
|
titleLabel.isHidden = true
|
||
|
|
||
|
view.addGestureRecognizer(
|
||
|
UITapGestureRecognizer(
|
||
|
target: self,
|
||
|
action: #selector(handleTap(_:))
|
||
|
)
|
||
|
)
|
||
|
|
||
|
registerForKeyboardNotifications()
|
||
|
}
|
||
|
|
||
|
|
||
|
@IBAction func storeSecret(_ sender: Any) {
|
||
|
DispatchQueue.global().async {
|
||
|
do {
|
||
|
try self.keychain
|
||
|
.accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence)
|
||
|
.set(self.txtSecret.text!, key: "secret")
|
||
|
} catch let error {
|
||
|
print(error)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@IBAction func getSecret(_ sender: Any) {
|
||
|
DispatchQueue.global().async {
|
||
|
do {
|
||
|
let secret = try self.keychain
|
||
|
.authenticationPrompt("Użyj czynnika biometrycznego, żeby zobaczyć sekret")
|
||
|
.get("secret")
|
||
|
self.lblSecret.text = "Sekret to \(secret!)"
|
||
|
} catch let error {
|
||
|
print(error)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
override func viewDidAppear(_ animated: Bool) {
|
||
|
super.viewDidAppear(animated)
|
||
|
|
||
|
let animation = CABasicAnimation(keyPath: "transform.scale")
|
||
|
|
||
|
animation.duration = 0.3
|
||
|
animation.fromValue = 0
|
||
|
animation.toValue = 1
|
||
|
|
||
|
CATransaction.begin()
|
||
|
CATransaction.setCompletionBlock {
|
||
|
self.emailField.becomeFirstResponder()
|
||
|
self.titleLabel.isHidden = false
|
||
|
}
|
||
|
containerView.layer.add(animation, forKey: "scale")
|
||
|
containerView.transform = CGAffineTransform(scaleX: 1, y: 1)
|
||
|
CATransaction.commit()
|
||
|
}
|
||
|
|
||
|
// MARK: - Actions
|
||
|
|
||
|
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
|
||
|
view.endEditing(true)
|
||
|
}
|
||
|
|
||
|
@IBAction func signInButtonPressed() {
|
||
|
signIn()
|
||
|
}
|
||
|
|
||
|
// MARK: - Helpers
|
||
|
|
||
|
private func registerForKeyboardNotifications() {
|
||
|
NotificationCenter.default.addObserver(
|
||
|
self,
|
||
|
selector: #selector(keyboardWillShow(_:)),
|
||
|
name: NSNotification.Name.UIKeyboardWillShow,
|
||
|
object: nil
|
||
|
)
|
||
|
NotificationCenter.default.addObserver(
|
||
|
self,
|
||
|
selector: #selector(keyboardWillHide(_:)),
|
||
|
name: NSNotification.Name.UIKeyboardWillHide,
|
||
|
object: nil
|
||
|
)
|
||
|
}
|
||
|
|
||
|
private func signIn() {
|
||
|
view.endEditing(true)
|
||
|
|
||
|
guard let email = emailField.text, email.count > 0 else {
|
||
|
return
|
||
|
}
|
||
|
guard let password = passwordField.text, password.count > 0 else {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
let name = UIDevice.current.name
|
||
|
let user = User(name: name, email: email)
|
||
|
|
||
|
do {
|
||
|
try AuthController.signIn(user, password: password)
|
||
|
} catch {
|
||
|
print("Error signing in: \(error.localizedDescription)")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MARK: - Notifications
|
||
|
|
||
|
@objc internal func keyboardWillShow(_ notification: Notification) {
|
||
|
guard let userInfo = notification.userInfo else {
|
||
|
return
|
||
|
}
|
||
|
guard let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height else {
|
||
|
return
|
||
|
}
|
||
|
guard let keyboardAnimationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue else {
|
||
|
return
|
||
|
}
|
||
|
guard let keyboardAnimationCurve = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue else {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
let options = UIViewAnimationOptions(rawValue: keyboardAnimationCurve << 16)
|
||
|
bottomConstraint.constant = keyboardHeight + 32
|
||
|
|
||
|
UIView.animate(withDuration: keyboardAnimationDuration, delay: 0, options: options, animations: {
|
||
|
self.view.layoutIfNeeded()
|
||
|
}, completion: nil)
|
||
|
}
|
||
|
|
||
|
@objc internal func keyboardWillHide(_ notification: Notification) {
|
||
|
guard let userInfo = notification.userInfo else {
|
||
|
return
|
||
|
}
|
||
|
guard let keyboardAnimationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue else {
|
||
|
return
|
||
|
}
|
||
|
guard let keyboardAnimationCurve = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue else {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
let options = UIViewAnimationOptions(rawValue: keyboardAnimationCurve << 16)
|
||
|
bottomConstraint.constant = 0
|
||
|
|
||
|
UIView.animate(withDuration: keyboardAnimationDuration, delay: 0, options: options, animations: {
|
||
|
self.view.layoutIfNeeded()
|
||
|
}, completion: nil)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
extension AuthViewController: UITextFieldDelegate {
|
||
|
|
||
|
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||
|
guard let text = textField.text, text.count > 0 else {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch textField.tag {
|
||
|
case TextFieldTag.email.rawValue:
|
||
|
passwordField.becomeFirstResponder()
|
||
|
case TextFieldTag.password.rawValue:
|
||
|
signIn()
|
||
|
default:
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|