324 lines
13 KiB
Swift
324 lines
13 KiB
Swift
//
|
|
// AccountControllerPin.swift
|
|
// Wallet
|
|
//
|
|
// Created by Saveliy Stavitsky on 12/4/20.
|
|
// Copyright © 2020 List. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
protocol AccountControllerPinDelegate: AnyObject {
|
|
|
|
func pinControllerDismiss(_ controller: AccountControllerPin)
|
|
func pinController(_ controller: AccountControllerPin, update password: String)
|
|
func pinControllerValidatePinSuccess(_ controller: AccountControllerPin)
|
|
func pinControllerClearAccountData(_ controller: AccountControllerPin)
|
|
}
|
|
|
|
final class AccountControllerPin: UIViewController {
|
|
|
|
enum AccountControllerPinType {
|
|
case old
|
|
case new
|
|
case protectionNew
|
|
}
|
|
|
|
@IBOutlet weak var logoTopConstraint: NSLayoutConstraint!
|
|
|
|
@IBOutlet var headerTitleLabel: UILabel!
|
|
@IBOutlet var headerDescriptionLabel: UILabel!
|
|
@IBOutlet var pinStackView: UIStackView!
|
|
@IBOutlet private weak var submitBtn: UIButton!
|
|
@IBOutlet private weak var haveWalletButton: UIButton!
|
|
@IBOutlet var leftButton: UIButton!
|
|
|
|
@IBOutlet var errorTopConstraint: NSLayoutConstraint!
|
|
@IBOutlet var errorTitleLabel: UILabel!
|
|
@IBOutlet var errorTryLabel: UILabel!
|
|
|
|
@IBOutlet var timeoutTitleLabel: UILabel!
|
|
@IBOutlet var timeoutLabel: UILabel!
|
|
@IBOutlet var timeoutView: UIView!
|
|
|
|
@IBOutlet private var warningView: CommonViewWarning!
|
|
|
|
weak var delegate: AccountControllerPinDelegate?
|
|
|
|
var type: AccountControllerPinType = .new
|
|
|
|
var pinValidate: ((String) -> Bool)?
|
|
var faceSubmit: (() -> Void)?
|
|
|
|
var showBackButton = true
|
|
|
|
var repeatPin: [Int] = []
|
|
var pin: [Int] = [Int]() {
|
|
didSet {
|
|
|
|
self.pinStackView.arrangedSubviews
|
|
.compactMap { $0 as? UIStackView }
|
|
.compactMap { $0.arrangedSubviews.first as? UIImageView }
|
|
.forEach { $0.image = Asset.accountPinStarEmpty.image }
|
|
|
|
self.errorTitleLabel.isHidden = true
|
|
for index in self.pin.indices where index < self.pinStackView.arrangedSubviews.count {
|
|
if let stack = pinStackView.arrangedSubviews[index] as? UIStackView {
|
|
(stack.arrangedSubviews.first as? UIImageView)?.image = Asset.accountPinStarFill.image
|
|
}
|
|
}
|
|
|
|
if self.repeatPin.count == 4,
|
|
self.pin.count == 4,
|
|
self.repeatPin != self.pin {
|
|
|
|
self.pinStackView.arrangedSubviews
|
|
.compactMap { $0 as? UIStackView }
|
|
.compactMap { $0.arrangedSubviews.first as? UIImageView }
|
|
.forEach { $0.image = Asset.accountPinStarError.image }
|
|
|
|
self.errorTitleLabel.isHidden = false
|
|
}
|
|
}
|
|
}
|
|
|
|
@IBOutlet var numbersStackView: UIStackView!
|
|
@IBOutlet var numberButtons: [UIButton]!
|
|
|
|
private var timer: Timer?
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
// print(UIApplication.shared.windows.first?.safeAreaInsets.top)
|
|
// if (UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) < 50 {
|
|
// logoTopConstraint.constant = 0
|
|
// }
|
|
|
|
self.timeoutTitleLabel.textAlignment = .center
|
|
|
|
self.warningView.makeCritical()
|
|
|
|
self.numbersStackView.spacing = UIScreen.main.bounds.height < 570 ? 8 : 24
|
|
|
|
self.timer = delayed(1, repeats: true) { [weak self] in
|
|
guard let self = self, self.pinValidate != nil else { return }
|
|
// let timeout = 3 * 60 - (Account.Service.Authorize.shared.lastPinTryTimeout() ?? 0)
|
|
// let seconds = timeout % 60 < 10 ? "0\(timeout % 60)" : "\(timeout % 60)"
|
|
// self.timeoutLabel.text = "\(timeout / 60):\(seconds)"
|
|
|
|
self.errorTryLabel.text = L10n.Account.Pin.tryCount(5 - Account.Service.Authorize.shared.getPinTries().count)
|
|
|
|
if Account.Service.Authorize.shared.getPinTries().count >= 5 {
|
|
// if Account.Service.Authorize.shared.lastPinTryTimeout()! < 3 * 60 {
|
|
self.timeoutView.isHidden = false
|
|
self.delegate?.pinControllerClearAccountData(self)
|
|
|
|
// } else {
|
|
// Account.Service.Authorize.shared.clearPinTries()
|
|
// self.timeoutView.isHidden = true
|
|
// }
|
|
} else {
|
|
self.timeoutView.isHidden = true
|
|
}
|
|
}
|
|
self.timer?.fire()
|
|
|
|
if self.pinValidate != nil {
|
|
if self.faceSubmit != nil {
|
|
self.title = "" // L10n.Account.Authorize.title
|
|
self.headerTitleLabel.text = L10n.Account.Pin.Enter.title
|
|
self.logoTopConstraint.constant = -40
|
|
} else {
|
|
self.title = "" // L10n.Account.Password.title
|
|
self.headerTitleLabel.text = type == .new ? L10n.Account.Pin.Enter.titleNew : L10n.Account.Pin.Enter.titleOld
|
|
self.logoTopConstraint.constant = -40
|
|
}
|
|
|
|
if self.showBackButton {
|
|
self.navigationItem.leftBarButtonItem = .back { [unowned self] in
|
|
self.timer?.invalidate()
|
|
self.timer = nil
|
|
self.navigationController?.dismiss(animated: true)
|
|
}
|
|
}
|
|
|
|
// Clear the background image.
|
|
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
|
|
// Clear the shadow image.
|
|
self.navigationController?.navigationBar.shadowImage = UIImage()
|
|
// Ensure the navigation bar is translucent.
|
|
self.navigationController?.navigationBar.isTranslucent = true
|
|
|
|
// navigationController?.navigationBar.layer.shadowColor = Asset.lightGray.color.cgColor
|
|
// navigationController?.navigationBar.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
|
|
// navigationController?.navigationBar.layer.shadowRadius = 4.0
|
|
// navigationController?.navigationBar.layer.shadowOpacity = 1.0
|
|
// navigationController?.navigationBar.layer.masksToBounds = false
|
|
|
|
self.leftButton.isHidden = !(Account.Service.isBiometricksEnabled) || faceSubmit == nil
|
|
self.leftButton.lzTitle = ""
|
|
self.leftButton.setImage(Asset.accountPinFaceId.image, for: .normal)
|
|
self.headerTitleLabel.font = .font(style: .regular, size: 14)
|
|
self.headerTitleLabel.textColor = Asset.textGranite.color.withAlphaComponent(0.7)
|
|
self.headerDescriptionLabel.isHidden = true
|
|
} else {
|
|
self.headerTitleLabel.font = .font(style: .bold, size: 24)
|
|
self.headerTitleLabel.textColor = Asset.textGranite.color
|
|
self.headerDescriptionLabel.isHidden = false
|
|
|
|
self.leftButton.lzTitle = L10n.Common.Button.back
|
|
if self.repeatPin.count == 0 {
|
|
self.leftButton.isHidden = true
|
|
} else {
|
|
self.leftButton.isHidden = false
|
|
self.headerTitleLabel.text = L10n.Account.Pin.Repeat.title
|
|
}
|
|
}
|
|
|
|
self.headerDescriptionLabel.font = .font(style: .regular, size: 14)
|
|
for button in self.numberButtons {
|
|
button.titleLabel?.font = .font(style: .regular, size: 28)
|
|
button.setTitleColor(Asset.textGranite.color, for: .normal)
|
|
// button.setBackgroundImage(Asset.accountPinNumberBackground.image, for: .highlighted)
|
|
}
|
|
self.leftButton.titleLabel?.font = .font(style: .medium, size: 18)
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
self.callBiometricsSignInIfEnabled()
|
|
}
|
|
|
|
private func callBiometricsSignInIfEnabled() {
|
|
if Account.Service.isBiometricksEnabled {
|
|
self.faceSubmit?()
|
|
}
|
|
}
|
|
|
|
@IBAction
|
|
private func onSubmit(_ : AnyObject?) {
|
|
}
|
|
|
|
@IBAction private func onUnderstand(_ : AnyObject?) {
|
|
Account.Service.Authorize.shared.clearPinTries()
|
|
self.delegate?.pinControllerDismiss(self)
|
|
}
|
|
|
|
@IBAction func haveWalletPrssed(_: AnyObject?) {
|
|
Alert.hint(text: L10n.Account.Onboarding.Password.hint)
|
|
}
|
|
|
|
@IBAction func numberPressed(_ sender: Any) {
|
|
if let value = (sender as? UIButton)?.tag {
|
|
switch value {
|
|
case -4:
|
|
self.leftButton.isHidden = self.faceSubmit == nil
|
|
if self.faceSubmit == nil {
|
|
self.headerTitleLabel.text = L10n.Account.Pin.Enter.title
|
|
}
|
|
self.repeatPin = []
|
|
self.pin = []
|
|
self.faceSubmit?()
|
|
case -1:
|
|
self.pin = self.pin.dropLast()
|
|
default:
|
|
if self.pin.count < 4 {
|
|
self.pin += [value]
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
//print(self.pin)
|
|
if let pinValidate,
|
|
self.pin.count == 4 {
|
|
let password = "\(self.pin[0])\(self.pin[1])\(self.pin[2])\(self.pin[3])"
|
|
if pinValidate(password) {
|
|
self.delegate?.pinControllerValidatePinSuccess(self)
|
|
} else {
|
|
for stack in (pinStackView.arrangedSubviews as? [UIStackView]) ?? [] {
|
|
(stack.arrangedSubviews.first as? UIImageView)?.image = Asset.accountPinStarError.image
|
|
}
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
|
|
self?.pin = []
|
|
self?.timer?.fire()
|
|
self?.errorTryLabel.text = L10n.Account.Pin.tryCount(5 - Account.Service.Authorize.shared.getPinTries().count)
|
|
self?.errorTryLabel.isHidden = false
|
|
self?.errorTitleLabel.isHidden = false
|
|
self?.warningView.isHidden = false
|
|
}
|
|
}
|
|
} else {
|
|
if repeatPin.count == 0,
|
|
pin.count == 4 {
|
|
leftButton.isHidden = false
|
|
headerTitleLabel.text = L10n.Account.Pin.Repeat.title
|
|
self.repeatPin = pin
|
|
pin = []
|
|
} else if repeatPin.count == 4 && pin.count == 4 && repeatPin == pin {
|
|
Account.Service.Authorize.shared.password = "\(pin[0])\(pin[1])\(pin[2])\(pin[3])"
|
|
successShow()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func successShow() {
|
|
|
|
UserDefaults.standard.setValue(true, forKey: "isPinPwdMode")
|
|
|
|
let password = "\(pin[0])\(pin[1])\(pin[2])\(pin[3])"
|
|
|
|
self.delegate?.pinController(self, update: password)
|
|
|
|
Popup.show(
|
|
title: L10n.Account.Onboarding.Success.title,
|
|
description: L10n.Account.Onboarding.Success.description,
|
|
submit: Account.Service.isBiometricksAvailable ? L10n.Account.Onboarding.Success.submit : L10n.Common.Button.ok,
|
|
in: self, { ctrl in
|
|
|
|
ctrl.dismiss(animated: true)
|
|
|
|
guard Account.Service.isBiometricksAvailable else {
|
|
self.delegate?.pinControllerDismiss(self)
|
|
return
|
|
}
|
|
|
|
let submit: (UIViewController) -> Void = { ctrl in
|
|
ctrl.dismiss(animated: true)
|
|
Account.Service.checkBiometricks { (success) in
|
|
if success {
|
|
Account.Service.isBiometricksEnabled = true
|
|
Alert.success()
|
|
self.delegate?.pinControllerDismiss(self)
|
|
} else {
|
|
Alert.error(text: L10n.Account.Onboarding.Bimetricks.error)
|
|
self.delegate?.pinControllerDismiss(self)
|
|
}
|
|
}
|
|
}
|
|
|
|
if Account.Service.isFaceIdAvailable {
|
|
Popup.show(
|
|
title: L10n.Account.Onboarding.FaceId.title,
|
|
image: Asset.commonFaceId.image,
|
|
description: L10n.Account.Onboarding.FaceId.description,
|
|
submit: L10n.Account.Onboarding.FaceId.submit,
|
|
in: self,
|
|
submit
|
|
)
|
|
} else {
|
|
Popup.show(
|
|
title: L10n.Account.Onboarding.TouchId.title,
|
|
image: Asset.commonTouchId.image,
|
|
description: L10n.Account.Onboarding.TouchId.description,
|
|
submit: L10n.Account.Onboarding.TouchId.submit,
|
|
in: self,
|
|
submit
|
|
)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|