Antidote/Antidote/EnterPinController.swift

149 lines
3.9 KiB
Swift

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import Foundation
import SnapKit
private struct Constants {
static let PinLength = 4
}
protocol EnterPinControllerDelegate: class {
func enterPinController(_ controller: EnterPinController, successWithPin pin: String)
// This method may be called only for ValidatePin state.
func enterPinControllerFailure(_ controller: EnterPinController)
}
class EnterPinController: UIViewController {
enum State {
case validatePin(validPin: String)
case setPin
}
weak var delegate: EnterPinControllerDelegate?
let state: State
var topText: String {
get {
return pinInputView.topText
}
set {
customLoadView()
pinInputView.topText = newValue
}
}
var descriptionText: String? {
get {
return pinInputView.descriptionText
}
set {
customLoadView()
pinInputView.descriptionText = newValue
}
}
fileprivate let theme: Theme
fileprivate var pinInputView: PinInputView!
fileprivate var enteredString: String = ""
init(theme: Theme, state: State) {
self.theme = theme
self.state = state
super.init(nibName: nil, bundle: nil)
}
required convenience init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
loadViewWithBackgroundColor(theme.colorForType(.NormalBackground))
createViews()
installConstraints()
pinInputView.applyColors()
}
override var shouldAutorotate : Bool {
return false
}
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
func resetEnteredPin() {
enteredString = ""
pinInputView.enteredNumbersCount = enteredString.count
}
}
extension EnterPinController: PinInputViewDelegate {
func pinInputView(_ view: PinInputView, numericButtonPressed i: Int) {
guard enteredString.count < Constants.PinLength else {
return
}
enteredString += "\(i)"
pinInputView.enteredNumbersCount = enteredString.count
if enteredString.count == Constants.PinLength {
switch state {
case .validatePin(let validPin):
if enteredString == validPin {
delegate?.enterPinController(self, successWithPin: enteredString)
}
else {
delegate?.enterPinControllerFailure(self)
}
case .setPin:
delegate?.enterPinController(self, successWithPin: enteredString)
}
}
}
func pinInputViewDeleteButtonPressed(_ view: PinInputView) {
guard enteredString.count > 0 else {
return
}
enteredString = String(enteredString.dropLast())
view.enteredNumbersCount = enteredString.count
}
}
private extension EnterPinController {
func createViews() {
pinInputView = PinInputView(pinLength: Constants.PinLength,
topColor: theme.colorForType(.LockGradientTop),
bottomColor: theme.colorForType(.LockGradientBottom))
pinInputView.delegate = self
view.addSubview(pinInputView)
}
func installConstraints() {
pinInputView.snp.makeConstraints {
$0.center.equalTo(view)
}
}
func customLoadView() {
if #available(iOS 9.0, *) {
loadViewIfNeeded()
} else {
if !isViewLoaded {
// creating view
view.setNeedsDisplay()
}
}
}
}