Initial implementation for AppLockSetupFlowCoordinator. (#1949)

Rename AppLockSettingsScreen to AppLockSetupSettingsScreen.
Implement forced logout and persist PIN entry attempts.
This commit is contained in:
Doug
2023-10-25 12:03:37 +01:00
committed by GitHub
parent 30b18031a0
commit c6e4dc2a37
53 changed files with 773 additions and 234 deletions
@@ -25,6 +25,8 @@ struct AppLockScreenCoordinatorParameters {
enum AppLockScreenCoordinatorAction {
/// The user has successfully unlocked the app.
case appUnlocked
/// The user failed to unlock the app (or forgot their PIN).
case forceLogout
}
final class AppLockScreenCoordinator: CoordinatorProtocol {
@@ -51,6 +53,8 @@ final class AppLockScreenCoordinator: CoordinatorProtocol {
switch action {
case .appUnlocked:
self.actionsSubject.send(.appUnlocked)
case .forceLogout:
self.actionsSubject.send(.forceLogout)
}
}
.store(in: &cancellables)
@@ -19,6 +19,8 @@ import Foundation
enum AppLockScreenViewModelAction {
/// The user has successfully unlocked the app.
case appUnlocked
/// The user failed to unlock the app (or forgot their PIN).
case forceLogout
}
struct AppLockScreenViewState: BindableState {
@@ -36,7 +38,7 @@ struct AppLockScreenViewState: BindableState {
/// The string shown in the screen's subtitle.
var subtitle: String {
if !isSubtitleWarning {
return L10n.screenAppLockSubtitle
return L10n.screenAppLockSubtitle(maximumAttempts)
} else {
return L10n.screenAppLockSubtitleWrongPin(maximumAttempts - numberOfPINAttempts)
}
@@ -50,8 +52,8 @@ struct AppLockScreenViewStateBindings {
}
enum AppLockScreenAlertType {
/// The user has failed too many times, they're being signed out.
case forceSignOut
/// The user has failed too many times, they're being logged out.
case forcedLogout
/// The user has forgotten their PIN, confirm they're happy to sign out.
case confirmResetPIN
}
@@ -31,6 +31,12 @@ class AppLockScreenViewModel: AppLockScreenViewModelType, AppLockScreenViewModel
self.appLockService = appLockService
super.init(initialViewState: AppLockScreenViewState(bindings: .init()))
appLockService.numberOfPINAttempts
.weakAssign(to: \.state.numberOfPINAttempts, on: self)
.store(in: &cancellables)
showForceLogoutAlertIfNeeded()
}
// MARK: - Public
@@ -58,24 +64,21 @@ class AppLockScreenViewModel: AppLockScreenViewModelType, AppLockScreenViewModel
state.bindings.alertInfo = .init(id: .confirmResetPIN,
title: L10n.screenAppLockSignoutAlertTitle,
message: L10n.screenAppLockSignoutAlertMessage,
primaryButton: .init(title: L10n.actionOk, action: forceSignOut),
primaryButton: .init(title: L10n.actionOk) { self.actionsSubject.send(.forceLogout) },
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
}
private func handleInvalidPIN() {
MXLog.warning("Invalid PIN code entered.")
state.numberOfPINAttempts += 1
if state.numberOfPINAttempts == 3 {
state.bindings.alertInfo = .init(id: .forceSignOut,
title: L10n.screenAppLockSignoutAlertTitle,
message: L10n.screenAppLockSignoutAlertMessage,
primaryButton: .init(title: L10n.actionOk, action: nil))
forceSignOut()
}
showForceLogoutAlertIfNeeded()
}
private func forceSignOut() {
// To be implemented.
private func showForceLogoutAlertIfNeeded() {
if state.numberOfPINAttempts >= 3 {
state.bindings.alertInfo = .init(id: .forcedLogout,
title: L10n.screenAppLockSignoutAlertTitle,
message: L10n.screenAppLockSignoutAlertMessage,
primaryButton: .init(title: L10n.actionOk) { self.actionsSubject.send(.forceLogout) })
}
}
}