mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-18 07:28:28 +02:00
Added change PIN code feature from the settings
This commit is contained in:
@@ -216,6 +216,8 @@ final class EnterPinCodeViewController: UIViewController {
|
||||
self.renderConfirmPinToDisable()
|
||||
case .inactive:
|
||||
self.renderInactive()
|
||||
case .changePin:
|
||||
self.renderChangePin()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +338,17 @@ final class EnterPinCodeViewController: UIViewController {
|
||||
self.explanatoryLabel.isHidden = true
|
||||
}
|
||||
|
||||
private func renderChangePin() {
|
||||
self.inactiveView.isHidden = true
|
||||
self.mainStackView.isHidden = false
|
||||
self.logoImageView.isHidden = true
|
||||
self.informationLabel.text = VectorL10n.pinProtectionConfirmPinToChange
|
||||
self.explanatoryLabel.isHidden = true
|
||||
self.forgotPinButton.isHidden = true
|
||||
self.bottomView.isHidden = false
|
||||
self.notAllowedPinView.isHidden = true
|
||||
}
|
||||
|
||||
private func renderPlaceholdersCount(_ count: Int, error: Bool = false) {
|
||||
UIView.animate(withDuration: 0.3) {
|
||||
for case let imageView as UIImageView in self.placeholderStackView.arrangedSubviews {
|
||||
|
||||
@@ -28,6 +28,7 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
private var originalViewMode: SetPinCoordinatorViewMode
|
||||
private var viewMode: SetPinCoordinatorViewMode
|
||||
|
||||
private var initialPin: String = ""
|
||||
private var firstPin: String = ""
|
||||
private var currentPin: String = "" {
|
||||
didSet {
|
||||
@@ -116,49 +117,12 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
switch viewMode {
|
||||
case .setPin, .setPinAfterLogin, .setPinAfterRegister:
|
||||
// choosing pin
|
||||
if firstPin.isEmpty {
|
||||
// check if this PIN is allowed
|
||||
if pinCodePreferences.notAllowedPINs.contains(currentPin) {
|
||||
viewMode = .notAllowedPin
|
||||
update(viewState: .notAllowedPin)
|
||||
return
|
||||
}
|
||||
// go to next screen
|
||||
firstPin = currentPin
|
||||
currentPin.removeAll()
|
||||
update(viewState: .confirmPin)
|
||||
} else {
|
||||
// check first and second pins
|
||||
if firstPin == currentPin {
|
||||
// complete with a little delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.coordinatorDelegate?.enterPinCodeViewModel(self, didCompleteWithPin: self.firstPin)
|
||||
}
|
||||
} else {
|
||||
update(viewState: .pinsDontMatch)
|
||||
}
|
||||
}
|
||||
updateAfterPinSet()
|
||||
case .unlock, .confirmPinToDeactivate:
|
||||
// unlocking
|
||||
if currentPin != pinCodePreferences.pin {
|
||||
// no match
|
||||
numberOfFailuresDuringEnterPIN += 1
|
||||
pinCodePreferences.numberOfPinFailures += 1
|
||||
if viewMode == .unlock && localAuthenticationService.shouldLogOutUser() {
|
||||
// log out user
|
||||
self.coordinatorDelegate?.enterPinCodeViewModelDidCompleteWithReset(self, dueToTooManyErrors: true)
|
||||
return
|
||||
}
|
||||
if numberOfFailuresDuringEnterPIN < pinCodePreferences.allowedNumberOfTrialsBeforeAlert {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: .wrongPin)
|
||||
self.currentPin.removeAll()
|
||||
}
|
||||
} else {
|
||||
viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: .wrongPinTooManyTimes)
|
||||
numberOfFailuresDuringEnterPIN = 0
|
||||
currentPin.removeAll()
|
||||
}
|
||||
updateAfterUnlockFailed()
|
||||
} else {
|
||||
// match
|
||||
// we can use biometrics anymore, if set
|
||||
@@ -169,6 +133,23 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
self.coordinatorDelegate?.enterPinCodeViewModelDidComplete(self)
|
||||
}
|
||||
}
|
||||
case .changePin:
|
||||
// unlocking
|
||||
if initialPin.isEmpty && currentPin != pinCodePreferences.pin {
|
||||
// no match
|
||||
updateAfterUnlockFailed()
|
||||
} else {
|
||||
// match or already unlocked
|
||||
if initialPin.isEmpty {
|
||||
// the user can choose a new Pin code
|
||||
initialPin = currentPin
|
||||
currentPin.removeAll()
|
||||
update(viewState: .choosePin)
|
||||
} else {
|
||||
// choosing pin
|
||||
updateAfterPinSet()
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -185,6 +166,8 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
return .choosePinAfterLogin
|
||||
case .setPinAfterRegister:
|
||||
return .choosePinAfterRegister
|
||||
case .changePin:
|
||||
return .changePin
|
||||
default:
|
||||
return .inactive
|
||||
}
|
||||
@@ -201,6 +184,8 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
update(viewState: .confirmPinToDisable)
|
||||
case .inactive:
|
||||
update(viewState: .inactive)
|
||||
case .changePin:
|
||||
update(viewState: .changePin)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -209,4 +194,49 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
private func update(viewState: EnterPinCodeViewState) {
|
||||
self.viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
private func updateAfterUnlockFailed() {
|
||||
numberOfFailuresDuringEnterPIN += 1
|
||||
pinCodePreferences.numberOfPinFailures += 1
|
||||
if viewMode == .unlock && localAuthenticationService.shouldLogOutUser() {
|
||||
// log out user
|
||||
self.coordinatorDelegate?.enterPinCodeViewModelDidCompleteWithReset(self, dueToTooManyErrors: true)
|
||||
return
|
||||
}
|
||||
if numberOfFailuresDuringEnterPIN < pinCodePreferences.allowedNumberOfTrialsBeforeAlert {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: .wrongPin)
|
||||
self.currentPin.removeAll()
|
||||
}
|
||||
} else {
|
||||
viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: .wrongPinTooManyTimes)
|
||||
numberOfFailuresDuringEnterPIN = 0
|
||||
currentPin.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateAfterPinSet() {
|
||||
if firstPin.isEmpty {
|
||||
// check if this PIN is allowed
|
||||
if pinCodePreferences.notAllowedPINs.contains(currentPin) {
|
||||
viewMode = .notAllowedPin
|
||||
update(viewState: .notAllowedPin)
|
||||
return
|
||||
}
|
||||
// go to next screen
|
||||
firstPin = currentPin
|
||||
currentPin.removeAll()
|
||||
update(viewState: .confirmPin)
|
||||
} else {
|
||||
// check first and second pins
|
||||
if firstPin == currentPin {
|
||||
// complete with a little delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.coordinatorDelegate?.enterPinCodeViewModel(self, didCompleteWithPin: self.firstPin)
|
||||
}
|
||||
} else {
|
||||
update(viewState: .pinsDontMatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ enum EnterPinCodeViewState {
|
||||
case forgotPin // after pin has been set, user tapped forgot pin
|
||||
case confirmPinToDisable // after pin has been set, confirm pin to disable pin
|
||||
case inactive // inactive state, only used when app is not active
|
||||
case changePin // pin is set, user tapped change pin from settings
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user