diff --git a/CHANGELOG.md b/CHANGELOG.md index b368eda..69695ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/LeadKitAdditions.podspec b/LeadKitAdditions.podspec index 7974392..f67dce4 100644 --- a/LeadKitAdditions.podspec +++ b/LeadKitAdditions.podspec @@ -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" diff --git a/Sources/Controllers/PassCode/Model/PassCodeError.swift b/Sources/Controllers/PassCode/Model/PassCodeError.swift index ca7ebed..6e2a86b 100644 --- a/Sources/Controllers/PassCode/Model/PassCodeError.swift +++ b/Sources/Controllers/PassCode/Model/PassCodeError.swift @@ -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 { diff --git a/Sources/Controllers/PassCode/Model/PassCodeHolder.swift b/Sources/Controllers/PassCode/Model/PassCodeHolder.swift index 4780bba..874bd7a 100644 --- a/Sources/Controllers/PassCode/Model/PassCodeHolder.swift +++ b/Sources/Controllers/PassCode/Model/PassCodeHolder.swift @@ -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? diff --git a/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift b/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift index d8bcf6c..0537f08 100644 --- a/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift +++ b/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift @@ -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() diff --git a/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 4fcc766..81378fe 100644 --- a/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -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() {} diff --git a/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index de5533b..7b17c35 100644 --- a/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -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 {