Dactyloidae/mobile/ios/Client/Frontend/AuthenticationManager/BasePasscodeViewController.swift
2026-06-26 21:04:09 -07:00

92 lines
3.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
import Shared
import SwiftKeychainWrapper
/// Base UIViewController subclass containing methods for displaying common error messaging
/// for the various Passcode configuration screens.
class BasePasscodeViewController: UIViewController {
var authenticationInfo: AuthenticationKeychainInfo?
var errorToast: ErrorToast?
let errorPadding: CGFloat = 10
init() {
self.authenticationInfo = KeychainWrapper.sharedAppContainerKeychain.authenticationInfo()
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIConstants.TableViewHeaderBackgroundColor
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(self.dismissAnimated))
automaticallyAdjustsScrollViewInsets = false
}
func dismissAnimated() {
self.dismiss(animated: true, completion: nil)
}
}
// MARK: - Error Helpers
extension BasePasscodeViewController {
fileprivate func displayError(_ text: String) {
errorToast?.removeFromSuperview()
errorToast = {
let toast = ErrorToast()
toast.textLabel.text = text
view.addSubview(toast)
toast.snp.makeConstraints { make in
make.center.equalTo(self.view)
make.left.greaterThanOrEqualTo(self.view).offset(errorPadding)
make.right.lessThanOrEqualTo(self.view).offset(-errorPadding)
}
return toast
}()
}
func displayLockoutError() {
displayError(AuthenticationStrings.maximumAttemptsReachedNoTime)
}
func failMismatchPasscode() {
let mismatchPasscodeError
= NSLocalizedString("Passcodes didnt match. Try again.",
tableName: "AuthenticationManager",
comment: "Error message displayed to user when their confirming passcode doesn't match the first code.")
displayError(mismatchPasscodeError)
}
func failMustBeDifferent() {
let useNewPasscodeError
= NSLocalizedString("New passcode must be different than existing code.",
tableName: "AuthenticationManager",
comment: "Error message displayed when user tries to enter the same passcode as their existing code when changing it.")
displayError(useNewPasscodeError)
}
func failIncorrectPasscode(_ inputView: PasscodeInputView) {
authenticationInfo?.recordFailedAttempt()
let numberOfAttempts = authenticationInfo?.failedAttempts ?? 0
if numberOfAttempts == AllowedPasscodeFailedAttempts {
authenticationInfo?.lockOutUser()
displayError(AuthenticationStrings.maximumAttemptsReachedNoTime)
inputView.isUserInteractionEnabled = false
resignFirstResponder()
} else {
displayError(String(format: AuthenticationStrings.incorrectAttemptsRemaining, (AllowedPasscodeFailedAttempts - numberOfAttempts)))
}
inputView.resetCode()
// Store mutations on authentication info object
KeychainWrapper.sharedAppContainerKeychain.setAuthenticationInfo(authenticationInfo)
}
}