mirror of https://github.com/oxen-io/session-ios
Merge branch 'charlesmchen/onboarding2FA'
commit
91aa9fcce6
@ -0,0 +1,176 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class Onboarding2FAViewController: OnboardingBaseViewController {
|
||||||
|
|
||||||
|
private let pinTextField = UITextField()
|
||||||
|
|
||||||
|
private var pinStrokeNormal: UIView?
|
||||||
|
private var pinStrokeError: UIView?
|
||||||
|
private let validationWarningLabel = UILabel()
|
||||||
|
private var isPinInvalid = false {
|
||||||
|
didSet {
|
||||||
|
updateValidationWarnings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func loadView() {
|
||||||
|
super.loadView()
|
||||||
|
|
||||||
|
view.backgroundColor = Theme.backgroundColor
|
||||||
|
view.layoutMargins = .zero
|
||||||
|
|
||||||
|
let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_2FA_TITLE", comment: "Title of the 'onboarding 2FA' view."))
|
||||||
|
|
||||||
|
let explanationLabel1 = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_2FA_EXPLANATION_1",
|
||||||
|
comment: "The first explanation in the 'onboarding 2FA' view."))
|
||||||
|
let explanationLabel2 = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_2FA_EXPLANATION_2",
|
||||||
|
comment: "The first explanation in the 'onboarding 2FA' view."))
|
||||||
|
explanationLabel1.font = UIFont.ows_dynamicTypeCaption1
|
||||||
|
explanationLabel2.font = UIFont.ows_dynamicTypeCaption1
|
||||||
|
|
||||||
|
pinTextField.textAlignment = .center
|
||||||
|
pinTextField.delegate = self
|
||||||
|
pinTextField.keyboardType = .numberPad
|
||||||
|
pinTextField.textColor = Theme.primaryColor
|
||||||
|
pinTextField.font = UIFont.ows_dynamicTypeBodyClamped
|
||||||
|
pinTextField.setContentHuggingHorizontalLow()
|
||||||
|
pinTextField.setCompressionResistanceHorizontalLow()
|
||||||
|
pinTextField.autoSetDimension(.height, toSize: 40)
|
||||||
|
|
||||||
|
pinStrokeNormal = pinTextField.addBottomStroke()
|
||||||
|
pinStrokeError = pinTextField.addBottomStroke(color: .ows_destructiveRed, strokeWidth: 2)
|
||||||
|
|
||||||
|
validationWarningLabel.text = NSLocalizedString("ONBOARDING_PHONE_NUMBER_VALIDATION_WARNING",
|
||||||
|
comment: "Label indicating that the phone number is invalid in the 'onboarding phone number' view.")
|
||||||
|
validationWarningLabel.textColor = .ows_destructiveRed
|
||||||
|
validationWarningLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped
|
||||||
|
validationWarningLabel.textAlignment = .center
|
||||||
|
|
||||||
|
let validationWarningRow = UIView()
|
||||||
|
validationWarningRow.addSubview(validationWarningLabel)
|
||||||
|
validationWarningLabel.ows_autoPinToSuperviewEdges()
|
||||||
|
validationWarningRow.autoSetDimension(.height, toSize: validationWarningLabel.font.lineHeight)
|
||||||
|
|
||||||
|
let forgotPinLink = self.linkButton(title: NSLocalizedString("ONBOARDING_2FA_FORGOT_PIN_LINK",
|
||||||
|
comment: "Label for the 'forgot 2FA PIN' link in the 'onboarding 2FA' view."),
|
||||||
|
selector: #selector(forgotPinLinkTapped))
|
||||||
|
|
||||||
|
let nextButton = self.button(title: NSLocalizedString("BUTTON_NEXT",
|
||||||
|
comment: "Label for the 'next' button."),
|
||||||
|
selector: #selector(nextPressed))
|
||||||
|
|
||||||
|
let topSpacer = UIView.vStretchingSpacer()
|
||||||
|
let bottomSpacer = UIView.vStretchingSpacer()
|
||||||
|
|
||||||
|
let stackView = UIStackView(arrangedSubviews: [
|
||||||
|
titleLabel,
|
||||||
|
UIView.spacer(withHeight: 10),
|
||||||
|
explanationLabel1,
|
||||||
|
UIView.spacer(withHeight: 10),
|
||||||
|
explanationLabel2,
|
||||||
|
|
||||||
|
topSpacer,
|
||||||
|
pinTextField,
|
||||||
|
UIView.spacer(withHeight: 10),
|
||||||
|
validationWarningRow,
|
||||||
|
bottomSpacer,
|
||||||
|
forgotPinLink,
|
||||||
|
UIView.spacer(withHeight: 10),
|
||||||
|
nextButton
|
||||||
|
])
|
||||||
|
stackView.axis = .vertical
|
||||||
|
stackView.alignment = .fill
|
||||||
|
stackView.layoutMargins = UIEdgeInsets(top: 20, left: 32, bottom: 20, right: 32)
|
||||||
|
stackView.isLayoutMarginsRelativeArrangement = true
|
||||||
|
view.addSubview(stackView)
|
||||||
|
stackView.autoPinWidthToSuperview()
|
||||||
|
stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
|
||||||
|
autoPinView(toBottomOfViewControllerOrKeyboard: stackView, avoidNotch: true)
|
||||||
|
|
||||||
|
// Ensure whitespace is balanced, so inputs are vertically centered.
|
||||||
|
topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)
|
||||||
|
|
||||||
|
updateValidationWarnings()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
_ = pinTextField.becomeFirstResponder()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Events
|
||||||
|
|
||||||
|
@objc func forgotPinLinkTapped() {
|
||||||
|
Logger.info("")
|
||||||
|
|
||||||
|
OWSAlerts.showAlert(title: nil, message: NSLocalizedString("REGISTER_2FA_FORGOT_PIN_ALERT_MESSAGE",
|
||||||
|
comment: "Alert message explaining what happens if you forget your 'two-factor auth pin'."))
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func nextPressed() {
|
||||||
|
Logger.info("")
|
||||||
|
|
||||||
|
tryToVerify()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func tryToVerify() {
|
||||||
|
Logger.info("")
|
||||||
|
|
||||||
|
guard let pin = pinTextField.text?.ows_stripped(),
|
||||||
|
pin.count > 0 else {
|
||||||
|
isPinInvalid = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isPinInvalid = false
|
||||||
|
|
||||||
|
onboardingController.update(twoFAPin: pin)
|
||||||
|
|
||||||
|
onboardingController.tryToVerify(fromViewController: self, completion: { (outcome) in
|
||||||
|
if outcome == .invalid2FAPin {
|
||||||
|
self.isPinInvalid = true
|
||||||
|
} else if outcome == .invalidVerificationCode {
|
||||||
|
owsFailDebug("Invalid verification code in 2FA view.")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateValidationWarnings() {
|
||||||
|
AssertIsOnMainThread()
|
||||||
|
|
||||||
|
pinStrokeNormal?.isHidden = isPinInvalid
|
||||||
|
pinStrokeError?.isHidden = !isPinInvalid
|
||||||
|
validationWarningLabel.isHidden = !isPinInvalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
extension Onboarding2FAViewController: UITextFieldDelegate {
|
||||||
|
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
let newString = string.digitsOnly
|
||||||
|
var oldText = ""
|
||||||
|
if let textFieldText = textField.text {
|
||||||
|
oldText = textFieldText
|
||||||
|
}
|
||||||
|
let left = oldText.substring(to: range.location)
|
||||||
|
let right = oldText.substring(from: range.location + range.length)
|
||||||
|
textField.text = left + newString + right
|
||||||
|
|
||||||
|
isPinInvalid = false
|
||||||
|
|
||||||
|
// Inform our caller that we took care of performing the change.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||||
|
tryToVerify()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue