Merge pull request #54 from TouchInstinct/feature/passCodeCount

Feature/pass code count
This commit is contained in:
Alexey Gerasimov 2018-10-22 18:33:43 +03:00 committed by GitHub
commit 9b5c16b7da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 39 deletions

View File

@ -1,5 +1,11 @@
# Changelog
### 0.3.6
- **Update**: PassCodeError, now emmit `tooManyAttempts` in any operation (*create* / *change* / *enter*) type.
- **Update**: Rename `PassCodeControllerType` to `PassCodeOperationType`.
- **Update**: `showBiometricsRequestIfNeeded` method become public.
### 0.3.5
- **Update**: Migrate to Swift 4.2 & Xcode 10. Update dependencies.

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "LeadKitAdditions"
s.version = "0.3.5"
s.version = "0.3.6"
s.summary = "iOS framework with a bunch of tools for rapid development"
s.homepage = "https://github.com/TouchInstinct/LeadKitAdditions"
s.license = "Apache License, Version 2.0"

View File

@ -21,13 +21,15 @@
//
/// Describes error, which may occur during pass code entering
/// - codesNotMatch: Different codes
/// - wrongCode: Value is remaining attemps
/// - tooManyAttempts: Attempts limit reached
public enum PassCodeError: Error {
/// Different codes
case codesNotMatch
case wrongCode(Int)
case tooManyAttempts
/// Value is remaining attemps
case wrongCode(attemptsRemaining: Int)
/// Attempts limit reached (for create, change or enter)
case tooManyAttempts(type: PassCodeOperationType)
}
public extension PassCodeError {

View File

@ -41,7 +41,7 @@ public extension PassCodeHolderProtocol {
/// Holds information about pass codes during pass code creation process
public class PassCodeHolderCreate: PassCodeHolderProtocol {
public let type: PassCodeControllerType = .create
public let type: PassCodeOperationType = .create
private var firstPassCode: String?
private var secondPassCode: String?
@ -95,7 +95,7 @@ public class PassCodeHolderCreate: PassCodeHolderProtocol {
/// Holds information about pass code during pass code entering process
public class PassCodeHolderEnter: PassCodeHolderProtocol {
public let type: PassCodeControllerType = .enter
public let type: PassCodeOperationType = .enter
public let enterStep: PassCodeControllerState = .enter
public var shouldValidate: Bool {
@ -125,7 +125,7 @@ public class PassCodeHolderEnter: PassCodeHolderProtocol {
/// Holds information about pass codes during pass code changing process
public class PassCodeHolderChange: PassCodeHolderProtocol {
public let type: PassCodeControllerType = .change
public let type: PassCodeOperationType = .change
private var oldPassCode: String?
private var newFirstPassCode: String?

View File

@ -25,7 +25,7 @@
public protocol PassCodeHolderProtocol {
/// Type of operation with pass code
var type: PassCodeControllerType { get }
var type: PassCodeOperationType { get }
/// Operation step
var enterStep: PassCodeControllerState { get }
@ -54,7 +54,7 @@ public class PassCodeHolderBuilder {
- parameter type: type of pass code controller
- returns: pass code information holder, specific by type
*/
public static func build(with type: PassCodeControllerType) -> PassCodeHolderProtocol {
public static func build(with type: PassCodeOperationType) -> PassCodeHolderProtocol {
switch type {
case .create:
return PassCodeHolderCreate()

View File

@ -32,7 +32,7 @@ public enum PinImageType {
}
/// Pass code operation type
public enum PassCodeControllerType {
public enum PassCodeOperationType {
case create
case enter
case change
@ -150,16 +150,6 @@ open class BasePassCodeViewController: UIViewController, LegacyConfigurableContr
}
}
private func showBiometricsRequestIfNeeded() {
guard viewModel.isBiometricsEnabled && viewModel.controllerType == .enter else {
return
}
viewModel.authenticateUsingBiometrics(with: biometricsAuthorizationHint,
fallback: biometricsFallbackButtonTitle,
cancel: biometricsCancelButtonTitle)
}
private func resetUI() {
resetDotsUI()
viewModel.reset()
@ -251,6 +241,17 @@ open class BasePassCodeViewController: UIViewController, LegacyConfigurableContr
fakeTextField.resignFirstResponder()
}
/// Show biometrics system UI if applicable
public func showBiometricsRequestIfNeeded() {
guard viewModel.isBiometricsEnabled && viewModel.operationType == .enter else {
return
}
viewModel.authenticateUsingBiometrics(with: biometricsAuthorizationHint,
fallback: biometricsFallbackButtonTitle,
cancel: biometricsCancelButtonTitle)
}
// MARK: - ConfigurableController
open func bindViews() {
@ -288,7 +289,7 @@ open class BasePassCodeViewController: UIViewController, LegacyConfigurableContr
open func addViews() {}
open func setAppearance() {}
open func configureAppearance() {}
open func configureBarButtons() {}

View File

@ -33,7 +33,7 @@ public enum PassCodeAuthType {
/// Base view model for passCodeViewController
open class BasePassCodeViewModel: BaseViewModel {
public let controllerType: PassCodeControllerType
public let operationType: PassCodeOperationType
public let disposeBag = DisposeBag()
@ -57,10 +57,10 @@ open class BasePassCodeViewModel: BaseViewModel {
private var attemptsNumber = 0
private lazy var passCodeHolder: PassCodeHolderProtocol = PassCodeHolderBuilder.build(with: self.controllerType)
private lazy var passCodeHolder: PassCodeHolderProtocol = PassCodeHolderBuilder.build(with: self.operationType)
public init(controllerType: PassCodeControllerType, passCodeConfiguration: PassCodeConfiguration) {
self.controllerType = controllerType
public init(operationType: PassCodeOperationType, passCodeConfiguration: PassCodeConfiguration) {
self.operationType = operationType
self.passCodeConfiguration = passCodeConfiguration
bindViewModel()
@ -95,7 +95,7 @@ open class BasePassCodeViewModel: BaseViewModel {
public func reset() {
passCodeText.value = nil
validationResultHolder.value = nil
passCodeControllerStateVariable.value = controllerType == .change ? .oldEnter : .enter
passCodeControllerStateVariable.value = operationType == .change ? .oldEnter : .enter
attemptsNumber = 0
passCodeHolder.reset()
}
@ -197,21 +197,32 @@ extension BasePassCodeViewModel {
return
}
switch passCodeHolder.type {
case .create where passCodeHolder.enterStep == .enter:
attemptsNumber += 1
case .change where passCodeHolder.enterStep == .enter:
attemptsNumber += 1
case .enter:
attemptsNumber += 1
default:
break
}
var validationResult = passCodeHolder.validate()
let passCodeValidationForPassCodeChange = passCodeHolder.type == .change && passCodeHolder.enterStep == .newEnter
// if entered (in .enter mode) code is invalid -> .wrongCode
if passCodeHolder.type == .enter,
let passCode = validationResult.passCode,
!isEnteredPassCodeValid(passCode) {
if passCodeHolder.type == .enter || passCodeValidationForPassCodeChange {
attemptsNumber += 1
let remainingAttemptsCount = passCodeConfiguration.maxAttemptsNumber - attemptsNumber
validationResult = .invalid(.wrongCode(attemptsRemaining: remainingAttemptsCount))
}
if let passCode = validationResult.passCode, !isEnteredPassCodeValid(passCode) {
validationResult = .invalid(.wrongCode(passCodeConfiguration.maxAttemptsNumber - attemptsNumber))
}
if (!validationResult.isValid && attemptsNumber == Int(passCodeConfiguration.maxAttemptsNumber)) ||
attemptsNumber > Int(passCodeConfiguration.maxAttemptsNumber) {
validationResult = .invalid(.tooManyAttempts)
}
// if entered code (in any mode) is mismatched too many times -> .tooManyAttempts
if (!validationResult.isValid && attemptsNumber == passCodeConfiguration.maxAttemptsNumber) ||
attemptsNumber > passCodeConfiguration.maxAttemptsNumber {
validationResult = .invalid(.tooManyAttempts(type: operationType))
}
if !validationResult.isValid {