/
GenericPasswordCell.swift
115 lines (94 loc) · 4.17 KB
/
GenericPasswordCell.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//
// GenericPasswordCell.swift
// GenericPasswordRow
//
// Created by Diego Ernst on 9/6/16.
// Copyright © 2016 Diego Ernst. All rights reserved.
//
import Foundation
import Eureka
open class GenericPasswordCell: _FieldCell<String>, CellType {
@IBOutlet weak var visibilityButton: UIButton?
@IBOutlet weak var passwordStrengthView: PasswordStrengthView?
@IBOutlet public weak var hintLabel: UILabel?
@IBOutlet public weak var leading: NSLayoutConstraint!
@IBOutlet public weak var trailing: NSLayoutConstraint!
var genericPasswordRow: _GenericPasswordRow! {
return row as? _GenericPasswordRow
}
open var visibilityImage: (on: UIImage?, off: UIImage?) {
didSet {
setVisibilityButtonImage()
}
}
open var dynamicHeight = (collapsed: UITableView.automaticDimension, expanded: UITableView.automaticDimension) {
didSet {
let value = dynamicHeight
height = { [weak self] in
self?.hintLabel?.isHidden == true ? value.collapsed : value.expanded
}
}
}
public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
open override func setup() {
super.setup()
dynamicHeight = (collapsed: 48, expanded: 64)
textField.autocorrectionType = .no
textField.autocapitalizationType = .none
textField.keyboardType = .asciiCapable
textField.isSecureTextEntry = true
selectionStyle = .none
textField.addTarget(self, action: #selector(GenericPasswordCell.textFieldDidChange(_:)), for: .editingChanged)
visibilityButton?.addTarget(self, action: #selector(GenericPasswordCell.togglePasswordVisibility), for: .touchUpInside)
visibilityButton?.tintColor = .gray
visibilityImage = (on: Resources.image(named: "visibility"), off: Resources.image(named: "visibility_off"))
hintLabel?.alpha = 0
passwordStrengthView?.setPasswordValidator(genericPasswordRow.passwordValidator)
updatePasswordStrengthIfNeeded(animated: false)
}
override open func update() {
super.update()
textField.text = genericPasswordRow.value
textField.placeholder = genericPasswordRow.placeholder
}
@objc open func togglePasswordVisibility() {
textField.isSecureTextEntry = !textField.isSecureTextEntry
setVisibilityButtonImage()
// workaround to update cursor position
let tmpString = textField.text
textField.text = nil
textField.text = tmpString
}
fileprivate func setVisibilityButtonImage() {
visibilityButton?.setImage(textField.isSecureTextEntry ? visibilityImage.on : visibilityImage.off, for: .normal)
}
open override func textFieldDidChange(_ textField: UITextField) {
genericPasswordRow.value = textField.text
updatePasswordStrengthIfNeeded()
formViewController()?.tableView?.beginUpdates()
// this updates the height of the cell
formViewController()?.tableView?.endUpdates()
UIView.animate(withDuration: 0.3, delay: 0.2, options: [], animations: { [weak self] in
guard let me = self else { return }
me.hintLabel?.alpha = me.hintLabel?.isHidden == true ? 0 : 1
}, completion: nil)
// make the cell full visible
if let indexPath = row?.indexPath {
UIView.animate(withDuration: 0.3, delay: 0, options: .allowUserInteraction, animations: { [weak self] in
self?.formViewController()?.tableView?.scrollToRow(at: indexPath, at: .none, animated: false)
}, completion: nil)
}
}
open func updatePasswordStrengthIfNeeded(animated: Bool = true) {
guard let password = textField.text else { return }
passwordStrengthView?.updateStrength(password: password, animated: animated)
let hint = genericPasswordRow.passwordValidator.hintForPassword(password)
hintLabel?.text = hint
hintLabel?.isHidden = hint == nil || password.isEmpty
}
}