Debounce PIN entry to show the last digit before submitting. (#2017)

This commit is contained in:
Doug
2023-11-03 07:31:01 +00:00
committed by GitHub
parent 5ae6494004
commit b10d534c94
9 changed files with 58 additions and 37 deletions
@@ -60,8 +60,6 @@ enum AppLockScreenAlertType {
}
enum AppLockScreenViewAction {
/// Attempt to unlock the app with the supplied PIN code.
case submitPINCode
/// Clears the PIN code after a failure animation.
case clearPINCode
/// The user didn't heed the warnings and can't remember their PIN.
@@ -36,6 +36,16 @@ class AppLockScreenViewModel: AppLockScreenViewModelType, AppLockScreenViewModel
.weakAssign(to: \.state.numberOfPINAttempts, on: self)
.store(in: &cancellables)
context.$viewState
.map(\.bindings.pinCode)
.removeDuplicates()
.debounce(for: 0.05, scheduler: DispatchQueue.main) // Allow the last digit to be briefly shown
.sink { [weak self] pinCode in
guard pinCode.count == 4 else { return }
self?.submit(pinCode)
}
.store(in: &cancellables)
showForceLogoutAlertIfNeeded()
}
@@ -45,8 +55,6 @@ class AppLockScreenViewModel: AppLockScreenViewModelType, AppLockScreenViewModel
MXLog.info("View model: received view action: \(viewAction)")
switch viewAction {
case .submitPINCode:
submitPINCode()
case .clearPINCode:
state.bindings.pinCode = ""
case .forgotPIN:
@@ -56,8 +64,8 @@ class AppLockScreenViewModel: AppLockScreenViewModelType, AppLockScreenViewModel
// MARK: - Private
private func submitPINCode() {
guard appLockService.unlock(with: state.bindings.pinCode) else {
private func submit(_ pinCode: String) {
guard appLockService.unlock(with: pinCode) else {
handleInvalidPIN()
return
}
@@ -49,10 +49,6 @@ struct AppLockScreen: View {
.accessibilityValue(L10n.a11yDigitsEntered(context.viewState.numberOfDigitsEntered))
AppLockScreenPINKeypad(pinCode: $context.pinCode)
.onChange(of: context.pinCode) { newValue in
guard newValue.count == 4 else { return }
context.send(viewAction: .submitPINCode)
}
}
} bottomContent: {
Button(L10n.screenAppLockForgotPin) {
@@ -88,8 +88,6 @@ enum AppLockSetupPINScreenAlertType {
}
enum AppLockSetupPINScreenViewAction {
/// Confirm the entered PIN.
case submitPINCode
/// Stop entering a PIN.
case cancel
}
@@ -38,6 +38,16 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
appLockService.numberOfPINAttempts
.weakAssign(to: \.state.numberOfUnlockAttempts, on: self)
.store(in: &cancellables)
context.$viewState
.map(\.bindings.pinCode)
.removeDuplicates()
.debounce(for: 0.1, scheduler: DispatchQueue.main) // Show the last digit for long enough to be read.
.sink { [weak self] pinCode in
guard pinCode.count == 4 else { return }
self?.submit(pinCode)
}
.store(in: &cancellables)
}
// MARK: - Public
@@ -46,8 +56,6 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
MXLog.info("View model: received view action: \(viewAction)")
switch viewAction {
case .submitPINCode:
submitPINCode()
case .cancel:
actionsSubject.send(.cancel)
}
@@ -56,7 +64,7 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
// MARK: - Private
/// Handle the entered PIN code.
private func submitPINCode() {
private func submit(_ pinCode: String) {
switch state.mode {
case .create:
createPIN()
@@ -43,10 +43,6 @@ struct AppLockSetupPINScreen: View {
PINTextField(pinCode: $context.pinCode,
isSecure: context.viewState.mode == .unlock)
.focused($textFieldFocus)
.onChange(of: context.pinCode) { newValue in
guard newValue.count == 4 else { return }
context.send(viewAction: .submitPINCode)
}
}
.padding(.horizontal, 16)
.padding(.top, UIConstants.iconTopPaddingToNavigationBar)