Signal-iOS/Signal/Registration/UserInterface/RegistrationPinAttemptsExhaustedAndMustCreateNewPinViewController.swift
Adam Sharp b42710cf90 Work around use of deprecated UIButton API
The old UIButton API is still functional as long as we don't use
UIButton.Configuration, so we can safely ignore these warnings until we're
ready to adopt the configuration API across the codebase.
2024-07-03 14:27:48 -04:00

181 lines
6.3 KiB
Swift

//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import SafariServices
import SignalServiceKit
import SignalUI
public struct RegistrationPinAttemptsExhaustedViewState: Equatable {
public enum Mode: Equatable {
/// We've already registered and were attempting to restore backups from kbs
/// but ran out of guesses; we can proceed without backups.
case restoringBackup
/// We were attempting to use the PIN to bypass sms-based registration.
/// We may or may not need the PIN for reglock later; for now we can fall back
/// to sms based verification.
case restoringRegistrationRecoveryPassword
}
public let mode: Mode
}
// MARK: - RegistrationPinAttemptsExhaustedAndMustCreateNewPinPresenter
protocol RegistrationPinAttemptsExhaustedAndMustCreateNewPinPresenter: AnyObject {
func acknowledgePinGuessesExhausted()
}
// MARK: - RegistrationPinAttemptsExhaustedAndMustCreateNewPinViewController
class RegistrationPinAttemptsExhaustedAndMustCreateNewPinViewController: OWSViewController {
private var learnMoreURL: URL { URL(string: "https://support.signal.org/hc/articles/360007059792")! }
private var state: RegistrationPinAttemptsExhaustedViewState
public init(
state: RegistrationPinAttemptsExhaustedViewState,
presenter: RegistrationPinAttemptsExhaustedAndMustCreateNewPinPresenter
) {
self.state = state
self.presenter = presenter
super.init()
}
public func updateState(_ newState: RegistrationPinAttemptsExhaustedViewState) {
self.state = newState
self.render()
}
@available(*, unavailable)
public override init() {
owsFail("This should not be called")
}
// MARK: Internal state
private weak var presenter: RegistrationPinAttemptsExhaustedAndMustCreateNewPinPresenter?
public override func viewDidLoad() {
super.viewDidLoad()
initialRender()
}
public override func themeDidChange() {
super.themeDidChange()
render()
}
// MARK: Rendering
private lazy var titleLabel: UILabel = {
let result = UILabel.titleLabelForRegistration(text: OWSLocalizedString(
"ONBOARDING_PIN_ATTEMPTS_EXHAUSTED_TITLE",
comment: "Title of the 'onboarding pin attempts exhausted' view when reglock is disabled."
))
result.accessibilityIdentifier = "registration.pinAttemptsExhausted.titleLabel"
return result
}()
private lazy var explanationLabel: UILabel = {
let result = UILabel.explanationLabelForRegistration(text: "")
result.accessibilityIdentifier = "registration.pinAttemptsExhausted.explanationLabel"
return result
}()
private lazy var continueButton: OWSButton = {
let result = OWSButton(title: "") { [weak self] in
self?.presenter?.acknowledgePinGuessesExhausted()
}
result.dimsWhenHighlighted = true
result.layer.cornerRadius = 8
result.backgroundColor = .ows_accentBlue
result.titleLabel?.font = UIFont.dynamicTypeBody.semibold()
result.titleLabel?.numberOfLines = 0
result.ows_contentEdgeInsets = .init(margin: 14)
result.autoSetDimension(.height, toSize: 48, relation: .greaterThanOrEqual)
return result
}()
private lazy var learnMoreButton: OWSFlatButton = {
let result = OWSFlatButton.button(
title: OWSLocalizedString(
"ONBOARDING_PIN_ATTEMPTS_EXHAUSTED_LEARN_MORE",
comment: "Label for the 'learn more' link when reglock is disabled in the 'onboarding pin attempts exhausted' view."
),
font: UIFont.dynamicTypeBody.semibold(),
titleColor: Theme.accentBlueColor,
backgroundColor: .clear,
target: self,
selector: #selector(didTapLearnMoreButton)
)
result.accessibilityIdentifier = "registration.pinAttemptsExhausted.learnMoreButton"
return result
}()
private func initialRender() {
navigationItem.setHidesBackButton(true, animated: false)
let stackView = UIStackView()
stackView.axis = .vertical
stackView.layoutMargins = UIEdgeInsets.layoutMarginsForRegistration(
traitCollection.horizontalSizeClass
)
stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView)
stackView.autoPinEdgesToSuperviewMargins()
stackView.addArrangedSubview(titleLabel)
stackView.setCustomSpacing(12, after: titleLabel)
stackView.addArrangedSubview(explanationLabel)
stackView.addArrangedSubview(UIView.vStretchingSpacer())
stackView.addArrangedSubview(continueButton)
stackView.setCustomSpacing(24, after: continueButton)
stackView.addArrangedSubview(learnMoreButton)
render()
}
private func render() {
view.backgroundColor = Theme.backgroundColor
titleLabel.textColor = Theme.primaryTextColor
explanationLabel.textColor = Theme.secondaryTextAndIconColor
learnMoreButton.setTitleColor(Theme.accentBlueColor)
switch state.mode {
case .restoringBackup:
explanationLabel.text = OWSLocalizedString(
"ONBOARDING_PIN_ATTEMPTS_EXHAUSTED_EXPLANATION",
comment: "Explanation of the 'onboarding pin attempts exhausted' view when reglock is disabled."
)
continueButton.setTitle(
OWSLocalizedString(
"ONBOARDING_2FA_CREATE_NEW_PIN",
comment: "Label for the 'create new pin' button when reglock is disabled during onboarding."
),
for: .normal
)
case .restoringRegistrationRecoveryPassword:
explanationLabel.text = OWSLocalizedString(
"ONBOARDING_PIN_ATTEMPTS_EXHAUSTED_WITH_UNKNOWN_REGLOCK_EXPLANATION",
comment: "Explanation of the 'onboarding pin attempts exhausted' view when it is unknown if reglock is enabled."
)
continueButton.setTitle(CommonStrings.continueButton, for: .normal)
}
}
// MARK: Events
@objc
private func didTapLearnMoreButton() {
present(SFSafariViewController(url: self.learnMoreURL), animated: true)
}
}