Merge branch 'charlesmchen/onboardingCleanup'

pull/2/head
Matthew Chen 6 years ago
commit 0e62514541

@ -2,7 +2,7 @@
"images" : [ "images" : [
{ {
"idiom" : "universal", "idiom" : "universal",
"filename" : "Screen Shot 2019-02-12 at 2.22.35 PM.png", "filename" : "onboarding_splash.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

@ -31,37 +31,31 @@ public class OnboardingBaseViewController: OWSViewController {
let titleLabel = UILabel() let titleLabel = UILabel()
titleLabel.text = text titleLabel.text = text
titleLabel.textColor = Theme.primaryColor titleLabel.textColor = Theme.primaryColor
titleLabel.font = UIFont.ows_dynamicTypeTitle2.ows_mediumWeight() titleLabel.font = UIFont.ows_dynamicTypeTitle1Clamped.ows_mediumWeight()
titleLabel.numberOfLines = 0 titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping titleLabel.lineBreakMode = .byWordWrapping
titleLabel.textAlignment = .center titleLabel.textAlignment = .center
return titleLabel return titleLabel
} }
func explanationLabel(explanationText: String, linkText: String, selector: Selector) -> UILabel { func explanationLabel(explanationText: String) -> UILabel {
let explanationText = NSAttributedString(string: explanationText)
.rtlSafeAppend(NSAttributedString(string: " "))
.rtlSafeAppend(linkText,
attributes: [
NSAttributedStringKey.foregroundColor: UIColor.ows_materialBlue
])
let explanationLabel = UILabel() let explanationLabel = UILabel()
explanationLabel.textColor = Theme.secondaryColor explanationLabel.textColor = Theme.secondaryColor
explanationLabel.font = UIFont.ows_dynamicTypeCaption1 explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped
explanationLabel.attributedText = explanationText explanationLabel.text = explanationText
explanationLabel.numberOfLines = 0 explanationLabel.numberOfLines = 0
explanationLabel.textAlignment = .center explanationLabel.textAlignment = .center
explanationLabel.lineBreakMode = .byWordWrapping explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.isUserInteractionEnabled = true
explanationLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: selector))
return explanationLabel return explanationLabel
} }
func button(title: String, selector: Selector) -> OWSFlatButton { func button(title: String, selector: Selector) -> OWSFlatButton {
// TODO: Make sure this all fits if dynamic font sizes are maxed out. // TODO: Make sure this all fits if dynamic font sizes are maxed out.
let buttonHeight: CGFloat = 48 let font = UIFont.ows_dynamicTypeBodyClamped.ows_mediumWeight()
// Button height should be 48pt if the font is 17pt.
let buttonHeight = font.pointSize * 48 / 17
let button = OWSFlatButton.button(title: title, let button = OWSFlatButton.button(title: title,
font: OWSFlatButton.fontForHeight(buttonHeight), font: font,
titleColor: .white, titleColor: .white,
backgroundColor: .ows_materialBlue, backgroundColor: .ows_materialBlue,
target: self, target: self,
@ -70,11 +64,28 @@ public class OnboardingBaseViewController: OWSViewController {
return button return button
} }
func linkButton(title: String, selector: Selector) -> OWSFlatButton {
// TODO: Make sure this all fits if dynamic font sizes are maxed out.
let font = UIFont.ows_dynamicTypeBodyClamped.ows_mediumWeight()
// Button height should be 48pt if the font is 17pt.
let buttonHeight = font.pointSize * 48 / 17
let button = OWSFlatButton.button(title: title,
font: font,
titleColor: .ows_materialBlue,
backgroundColor: .white,
target: self,
selector: selector)
button.autoSetDimension(.height, toSize: buttonHeight)
return button
}
// MARK: - View Lifecycle // MARK: - View Lifecycle
public override func viewWillAppear(_ animated: Bool) { public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
// TODO: Is there a better way to do this? // TODO: Is there a better way to do this?
if let navigationController = self.navigationController as? OWSNavigationController { if let navigationController = self.navigationController as? OWSNavigationController {
SignalApp.shared().signUpFlowNavigationController = navigationController SignalApp.shared().signUpFlowNavigationController = navigationController
@ -83,6 +94,12 @@ public class OnboardingBaseViewController: OWSViewController {
} }
} }
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
// MARK: - Orientation // MARK: - Orientation
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask { public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {

@ -73,8 +73,6 @@ public class OnboardingCaptchaViewController: OnboardingBaseViewController {
public override func viewWillAppear(_ animated: Bool) { public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
loadContent() loadContent()
} }
@ -93,12 +91,6 @@ public class OnboardingCaptchaViewController: OnboardingBaseViewController {
webView.scrollView.contentOffset = .zero webView.scrollView.contentOffset = .zero
} }
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}
// MARK: - Notifications // MARK: - Notifications
@objc func didBecomeActive() { @objc func didBecomeActive() {

@ -12,10 +12,7 @@ public class OnboardingPermissionsViewController: OnboardingBaseViewController {
super.loadView() super.loadView()
view.backgroundColor = Theme.backgroundColor view.backgroundColor = Theme.backgroundColor
view.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32) view.layoutMargins = .zero
// TODO:
// navigationItem.title = NSLocalizedString("SETTINGS_BACKUP", comment: "Label for the backup view in app settings.")
navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("NAVIGATION_ITEM_SKIP_BUTTON", comment: "A button to skip a view."), navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("NAVIGATION_ITEM_SKIP_BUTTON", comment: "A button to skip a view."),
style: .plain, style: .plain,
@ -23,58 +20,42 @@ public class OnboardingPermissionsViewController: OnboardingBaseViewController {
action: #selector(skipWasPressed)) action: #selector(skipWasPressed))
let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PERMISSIONS_TITLE", comment: "Title of the 'onboarding permissions' view.")) let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PERMISSIONS_TITLE", comment: "Title of the 'onboarding permissions' view."))
view.addSubview(titleLabel)
titleLabel.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom)
// TODO: Finalize copy.
let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_PERMISSIONS_EXPLANATION", let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_PERMISSIONS_EXPLANATION",
comment: "Explanation in the 'onboarding permissions' view."), comment: "Explanation in the 'onboarding permissions' view."))
linkText: NSLocalizedString("ONBOARDING_PERMISSIONS_LEARN_MORE_LINK",
comment: "Link to the 'learn more' in the 'onboarding permissions' view."),
selector: #selector(explanationLabelTapped))
// TODO: Make sure this all fits if dynamic font sizes are maxed out. // TODO: Make sure this all fits if dynamic font sizes are maxed out.
let giveAccessButton = self.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON", let giveAccessButton = self.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_ENABLE_PERMISSIONS_BUTTON",
comment: "Label for the 'give access' button in the 'onboarding permissions' view."), comment: "Label for the 'give access' button in the 'onboarding permissions' view."),
selector: #selector(giveAccessPressed)) selector: #selector(giveAccessPressed))
let notNowButton = self.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON", let notNowButton = self.linkButton(title: NSLocalizedString("ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON",
comment: "Label for the 'not now' button in the 'onboarding permissions' view."), comment: "Label for the 'not now' button in the 'onboarding permissions' view."),
selector: #selector(notNowPressed)) selector: #selector(notNowPressed))
let buttonStack = UIStackView(arrangedSubviews: [ let topSpacer = UIView.vStretchingSpacer()
giveAccessButton, let bottomSpacer = UIView.vStretchingSpacer()
notNowButton
])
buttonStack.axis = .vertical
buttonStack.alignment = .fill
buttonStack.spacing = 12
let stackView = UIStackView(arrangedSubviews: [ let stackView = UIStackView(arrangedSubviews: [
titleLabel,
UIView.spacer(withHeight: 20),
explanationLabel, explanationLabel,
buttonStack topSpacer,
giveAccessButton,
UIView.spacer(withHeight: 12),
notNowButton,
bottomSpacer
]) ])
stackView.axis = .vertical stackView.axis = .vertical
stackView.alignment = .fill stackView.alignment = .fill
stackView.spacing = 40 stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)
stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView) view.addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins() stackView.autoPinWidthToSuperview()
stackView.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: 20, relation: .greaterThanOrEqual) stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
NSLayoutConstraint.autoSetPriority(.defaultHigh) { stackView.autoPin(toBottomLayoutGuideOf: self, withInset: 0)
stackView.autoVCenterInSuperview()
}
}
public override func viewWillAppear(_ animated: Bool) { // Ensure whitespace is balanced, so inputs are vertically centered.
super.viewWillAppear(animated) topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)
self.navigationController?.isNavigationBarHidden = false
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.isNavigationBarHidden = false
} }
// MARK: Request Access // MARK: Request Access
@ -117,13 +98,6 @@ public class OnboardingPermissionsViewController: OnboardingBaseViewController {
onboardingController.onboardingPermissionsWasSkipped(viewController: self) onboardingController.onboardingPermissionsWasSkipped(viewController: self)
} }
@objc func explanationLabelTapped(sender: UIGestureRecognizer) {
guard sender.state == .recognized else {
return
}
// TODO:
}
@objc func giveAccessPressed() { @objc func giveAccessPressed() {
Logger.info("") Logger.info("")

@ -20,6 +20,10 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
private let callingCodeLabel = UILabel() private let callingCodeLabel = UILabel()
private let phoneNumberTextField = UITextField() private let phoneNumberTextField = UITextField()
private var nextButton: OWSFlatButton? private var nextButton: OWSFlatButton?
private var phoneStrokeNormal: UIView?
private var phoneStrokeError: UIView?
private let validationWarningLabel = UILabel()
private var isPhoneNumberInvalid = false
override public func loadView() { override public func loadView() {
super.loadView() super.loadView()
@ -29,9 +33,6 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
view.backgroundColor = Theme.backgroundColor view.backgroundColor = Theme.backgroundColor
view.layoutMargins = .zero view.layoutMargins = .zero
// TODO:
// navigationItem.title = NSLocalizedString("SETTINGS_BACKUP", comment: "Label for the backup view in app settings.")
let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PHONE_NUMBER_TITLE", comment: "Title of the 'onboarding phone number' view.")) let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PHONE_NUMBER_TITLE", comment: "Title of the 'onboarding phone number' view."))
// Country // Country
@ -39,7 +40,7 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
let rowHeight: CGFloat = 40 let rowHeight: CGFloat = 40
countryNameLabel.textColor = Theme.primaryColor countryNameLabel.textColor = Theme.primaryColor
countryNameLabel.font = UIFont.ows_dynamicTypeBody countryNameLabel.font = UIFont.ows_dynamicTypeBodyClamped
countryNameLabel.setContentHuggingHorizontalLow() countryNameLabel.setContentHuggingHorizontalLow()
countryNameLabel.setCompressionResistanceHorizontalLow() countryNameLabel.setCompressionResistanceHorizontalLow()
@ -61,26 +62,27 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
countryRow.isUserInteractionEnabled = true countryRow.isUserInteractionEnabled = true
countryRow.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryRowTapped))) countryRow.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryRowTapped)))
countryRow.autoSetDimension(.height, toSize: rowHeight) countryRow.autoSetDimension(.height, toSize: rowHeight)
addBottomStroke(countryRow) _ = addBottomStroke(countryRow)
callingCodeLabel.textColor = Theme.primaryColor callingCodeLabel.textColor = Theme.primaryColor
callingCodeLabel.font = UIFont.ows_dynamicTypeBody callingCodeLabel.font = UIFont.ows_dynamicTypeBodyClamped
callingCodeLabel.setContentHuggingHorizontalHigh() callingCodeLabel.setContentHuggingHorizontalHigh()
callingCodeLabel.setCompressionResistanceHorizontalHigh() callingCodeLabel.setCompressionResistanceHorizontalHigh()
callingCodeLabel.isUserInteractionEnabled = true callingCodeLabel.isUserInteractionEnabled = true
callingCodeLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryCodeTapped))) callingCodeLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryCodeTapped)))
addBottomStroke(callingCodeLabel) _ = addBottomStroke(callingCodeLabel)
callingCodeLabel.autoSetDimension(.width, toSize: rowHeight, relation: .greaterThanOrEqual) callingCodeLabel.autoSetDimension(.width, toSize: rowHeight, relation: .greaterThanOrEqual)
phoneNumberTextField.textAlignment = .left phoneNumberTextField.textAlignment = .left
phoneNumberTextField.delegate = self phoneNumberTextField.delegate = self
phoneNumberTextField.keyboardType = .numberPad phoneNumberTextField.keyboardType = .numberPad
phoneNumberTextField.textColor = Theme.primaryColor phoneNumberTextField.textColor = Theme.primaryColor
phoneNumberTextField.font = UIFont.ows_dynamicTypeBody phoneNumberTextField.font = UIFont.ows_dynamicTypeBodyClamped
phoneNumberTextField.setContentHuggingHorizontalLow() phoneNumberTextField.setContentHuggingHorizontalLow()
phoneNumberTextField.setCompressionResistanceHorizontalLow() phoneNumberTextField.setCompressionResistanceHorizontalLow()
addBottomStroke(phoneNumberTextField) phoneStrokeNormal = addBottomStroke(phoneNumberTextField)
phoneStrokeError = addBottomStroke(phoneNumberTextField, color: .ows_destructiveRed, strokeWidth: 2)
let phoneNumberRow = UIStackView(arrangedSubviews: [ let phoneNumberRow = UIStackView(arrangedSubviews: [
callingCodeLabel, callingCodeLabel,
@ -92,6 +94,16 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
phoneNumberRow.autoSetDimension(.height, toSize: rowHeight) phoneNumberRow.autoSetDimension(.height, toSize: rowHeight)
callingCodeLabel.autoMatch(.height, to: .height, of: phoneNumberTextField) callingCodeLabel.autoMatch(.height, to: .height, of: phoneNumberTextField)
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
let validationWarningRow = UIView()
validationWarningRow.addSubview(validationWarningLabel)
validationWarningLabel.autoPinHeightToSuperview()
validationWarningLabel.autoPinEdge(toSuperviewEdge: .trailing)
// TODO: Finalize copy. // TODO: Finalize copy.
let nextButton = self.button(title: NSLocalizedString("BUTTON_NEXT", let nextButton = self.button(title: NSLocalizedString("BUTTON_NEXT",
@ -107,6 +119,8 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
countryRow, countryRow,
UIView.spacer(withHeight: 8), UIView.spacer(withHeight: 8),
phoneNumberRow, phoneNumberRow,
UIView.spacer(withHeight: 8),
validationWarningRow,
bottomSpacer, bottomSpacer,
nextButton nextButton
]) ])
@ -115,34 +129,43 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32) stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)
stackView.isLayoutMarginsRelativeArrangement = true stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView) view.addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins() stackView.autoPinWidthToSuperview()
stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0) stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
autoPinView(toBottomOfViewControllerOrKeyboard: stackView, avoidNotch: true) autoPinView(toBottomOfViewControllerOrKeyboard: stackView, avoidNotch: true)
// Ensure whitespace is balanced, so inputs are vertically centered. // Ensure whitespace is balanced, so inputs are vertically centered.
topSpacer.autoMatch(.height, to: .height, of: bottomSpacer) topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)
validationWarningLabel.autoPinEdge(.leading, to: .leading, of: phoneNumberTextField)
}
private func addBottomStroke(_ view: UIView) -> UIView {
return addBottomStroke(view, color: Theme.middleGrayColor, strokeWidth: CGHairlineWidth())
} }
private func addBottomStroke(_ view: UIView) { private func addBottomStroke(_ view: UIView, color: UIColor, strokeWidth: CGFloat) -> UIView {
let strokeView = UIView() let strokeView = UIView()
strokeView.backgroundColor = Theme.middleGrayColor strokeView.backgroundColor = color
view.addSubview(strokeView) view.addSubview(strokeView)
strokeView.autoSetDimension(.height, toSize: CGHairlineWidth()) strokeView.autoSetDimension(.height, toSize: strokeWidth)
strokeView.autoPinWidthToSuperview() strokeView.autoPinWidthToSuperview()
strokeView.autoPinEdge(toSuperviewEdge: .bottom) strokeView.autoPinEdge(toSuperviewEdge: .bottom)
return strokeView
} }
// MARK: - View Lifecycle
public override func viewWillAppear(_ animated: Bool) { public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false isPhoneNumberInvalid = false
updateViewState()
} }
public override func viewDidAppear(_ animated: Bool) { public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
self.navigationController?.isNavigationBarHidden = false
phoneNumberTextField.becomeFirstResponder() phoneNumberTextField.becomeFirstResponder()
if tsAccountManager.isReregistering() { if tsAccountManager.isReregistering() {
@ -202,11 +225,12 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
let countryState = OnboardingCountryState(countryName: countryName, callingCode: callingCode, countryCode: countryCode) let countryState = OnboardingCountryState(countryName: countryName, callingCode: callingCode, countryCode: countryCode)
onboardingController.update(countryState: countryState) onboardingController.update(countryState: countryState)
updateState()
phoneNumberTextField.text = phoneNumberWithoutCallingCode phoneNumberTextField.text = phoneNumberWithoutCallingCode
// Don't let user edit their phone number while re-registering. // Don't let user edit their phone number while re-registering.
phoneNumberTextField.isEnabled = false phoneNumberTextField.isEnabled = false
updateViewState()
} }
// MARK: - // MARK: -
@ -236,18 +260,30 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
lastRegisteredPhoneNumber.count > 0, lastRegisteredPhoneNumber.count > 0,
lastRegisteredPhoneNumber.hasPrefix(callingCode) { lastRegisteredPhoneNumber.hasPrefix(callingCode) {
phoneNumberTextField.text = lastRegisteredPhoneNumber.substring(from: callingCode.count) phoneNumberTextField.text = lastRegisteredPhoneNumber.substring(from: callingCode.count)
} else if let phoneNumber = onboardingController.phoneNumber {
phoneNumberTextField.text = phoneNumber.userInput
} }
updateState() updateViewState()
} }
private func updateState() { private func updateViewState() {
AssertIsOnMainThread() AssertIsOnMainThread()
countryNameLabel.text = countryName countryNameLabel.text = countryName
callingCodeLabel.text = callingCode callingCodeLabel.text = callingCode
self.phoneNumberTextField.placeholder = ViewControllerUtils.examplePhoneNumber(forCountryCode: countryCode, callingCode: callingCode) self.phoneNumberTextField.placeholder = ViewControllerUtils.examplePhoneNumber(forCountryCode: countryCode, callingCode: callingCode)
updateValidationWarnings()
}
private func updateValidationWarnings() {
AssertIsOnMainThread()
phoneStrokeNormal?.isHidden = isPhoneNumberInvalid
phoneStrokeError?.isHidden = !isPhoneNumberInvalid
validationWarningLabel.isHidden = !isPhoneNumberInvalid
} }
// MARK: - Events // MARK: - Events
@ -291,6 +327,10 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
private func parseAndTryToRegister() { private func parseAndTryToRegister() {
guard let phoneNumberText = phoneNumberTextField.text?.ows_stripped(), guard let phoneNumberText = phoneNumberTextField.text?.ows_stripped(),
phoneNumberText.count > 0 else { phoneNumberText.count > 0 else {
isPhoneNumberInvalid = false
updateValidationWarnings()
OWSAlerts.showAlert(title: OWSAlerts.showAlert(title:
NSLocalizedString("REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_TITLE", NSLocalizedString("REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_TITLE",
comment: "Title of alert indicating that users needs to enter a phone number to register."), comment: "Title of alert indicating that users needs to enter a phone number to register."),
@ -304,6 +344,10 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
guard let localNumber = PhoneNumber.tryParsePhoneNumber(fromUserSpecifiedText: phoneNumber), guard let localNumber = PhoneNumber.tryParsePhoneNumber(fromUserSpecifiedText: phoneNumber),
localNumber.toE164().count > 0, localNumber.toE164().count > 0,
PhoneNumberValidator().isValidForRegistration(phoneNumber: localNumber) else { PhoneNumberValidator().isValidForRegistration(phoneNumber: localNumber) else {
isPhoneNumberInvalid = false
updateValidationWarnings()
OWSAlerts.showAlert(title: OWSAlerts.showAlert(title:
NSLocalizedString("REGISTRATION_VIEW_INVALID_PHONE_NUMBER_ALERT_TITLE", NSLocalizedString("REGISTRATION_VIEW_INVALID_PHONE_NUMBER_ALERT_TITLE",
comment: "Title of alert indicating that users needs to enter a valid phone number to register."), comment: "Title of alert indicating that users needs to enter a valid phone number to register."),
@ -339,6 +383,9 @@ extension OnboardingPhoneNumberViewController: UITextFieldDelegate {
// TODO: Fix auto-format of phone numbers. // TODO: Fix auto-format of phone numbers.
ViewControllerUtils.phoneNumber(textField, shouldChangeCharactersIn: range, replacementString: string, countryCode: countryCode) ViewControllerUtils.phoneNumber(textField, shouldChangeCharactersIn: range, replacementString: string, countryCode: countryCode)
isPhoneNumberInvalid = false
updateValidationWarnings()
// Inform our caller that we took care of performing the change. // Inform our caller that we took care of performing the change.
return false return false
} }
@ -370,7 +417,7 @@ extension OnboardingPhoneNumberViewController: CountryCodeViewControllerDelegate
onboardingController.update(countryState: countryState) onboardingController.update(countryState: countryState)
updateState() updateViewState()
// Trigger the formatting logic with a no-op edit. // Trigger the formatting logic with a no-op edit.
_ = textField(phoneNumberTextField, shouldChangeCharactersIn: NSRange(location: 0, length: 0), replacementString: "") _ = textField(phoneNumberTextField, shouldChangeCharactersIn: NSRange(location: 0, length: 0), replacementString: "")

@ -14,9 +14,6 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
view.backgroundColor = Theme.backgroundColor view.backgroundColor = Theme.backgroundColor
view.layoutMargins = .zero view.layoutMargins = .zero
// TODO:
// navigationItem.title = NSLocalizedString("SETTINGS_BACKUP", comment: "Label for the backup view in app settings.")
let heroImage = UIImage(named: "onboarding_splash_hero") let heroImage = UIImage(named: "onboarding_splash_hero")
let heroImageView = UIImageView(image: heroImage) let heroImageView = UIImageView(image: heroImage)
heroImageView.contentMode = .scaleAspectFit heroImageView.contentMode = .scaleAspectFit
@ -29,12 +26,16 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
view.addSubview(titleLabel) view.addSubview(titleLabel)
titleLabel.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom) titleLabel.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom)
// TODO: Finalize copy. let explanationLabel = UILabel()
let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_SPLASH_EXPLANATION", explanationLabel.text = NSLocalizedString("ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY",
comment: "Explanation in the 'onboarding splash' view."), comment: "Link to the 'terms and privacy policy' in the 'onboarding splash' view.")
linkText: NSLocalizedString("ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY", explanationLabel.textColor = .ows_materialBlue
comment: "Link to the 'terms and privacy policy' in the 'onboarding splash' view."), explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped
selector: #selector(explanationLabelTapped)) explanationLabel.numberOfLines = 0
explanationLabel.textAlignment = .center
explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.isUserInteractionEnabled = true
explanationLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(explanationLabelTapped)))
// TODO: Make sure this all fits if dynamic font sizes are maxed out. // TODO: Make sure this all fits if dynamic font sizes are maxed out.
let continueButton = self.button(title: NSLocalizedString("BUTTON_CONTINUE", let continueButton = self.button(title: NSLocalizedString("BUTTON_CONTINUE",
@ -46,9 +47,9 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
heroImageView, heroImageView,
UIView.spacer(withHeight: 22), UIView.spacer(withHeight: 22),
titleLabel, titleLabel,
UIView.spacer(withHeight: 56), UIView.spacer(withHeight: 92),
explanationLabel, explanationLabel,
UIView.spacer(withHeight: 40), UIView.spacer(withHeight: 24),
continueButton continueButton
]) ])
stackView.axis = .vertical stackView.axis = .vertical
@ -56,23 +57,11 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32) stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)
stackView.isLayoutMarginsRelativeArrangement = true stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView) view.addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins() stackView.autoPinWidthToSuperview()
stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0) stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
stackView.autoPin(toBottomLayoutGuideOf: self, withInset: 0) stackView.autoPin(toBottomLayoutGuideOf: self, withInset: 0)
} }
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
// MARK: - Events // MARK: - Events
@objc func explanationLabelTapped(sender: UIGestureRecognizer) { @objc func explanationLabelTapped(sender: UIGestureRecognizer) {

@ -1511,29 +1511,26 @@
/* Title of the 'onboarding Captcha' view. */ /* Title of the 'onboarding Captcha' view. */
"ONBOARDING_CAPTCHA_TITLE" = "We need to verify that you're human"; "ONBOARDING_CAPTCHA_TITLE" = "We need to verify that you're human";
/* Explanation in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_EXPLANATION" = "ONBOARDING_PERMISSIONS_EXPLANATION";
/* Label for the 'give access' button in the 'onboarding permissions' view. */ /* Label for the 'give access' button in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON" = "Give Access"; "ONBOARDING_PERMISSIONS_ENABLE_PERMISSIONS_BUTTON" = "Enable Permissions";
/* Link to the 'learn more' in the 'onboarding permissions' view. */ /* Explanation in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_LEARN_MORE_LINK" = "Learn More"; "ONBOARDING_PERMISSIONS_EXPLANATION" = "Your contact information is always transmitted securely.";
/* Label for the 'not now' button in the 'onboarding permissions' view. */ /* Label for the 'not now' button in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON" = "Not Now"; "ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON" = "Not Now";
/* Title of the 'onboarding permissions' view. */ /* Title of the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_TITLE" = "We need access to your contacts and notifications"; "ONBOARDING_PERMISSIONS_TITLE" = "Signal can let you know when you get a message (and who it is from)";
/* Title of the 'onboarding phone number' view. */ /* Title of the 'onboarding phone number' view. */
"ONBOARDING_PHONE_NUMBER_TITLE" = "Enter your phone number to get started"; "ONBOARDING_PHONE_NUMBER_TITLE" = "Enter your phone number to get started";
/* Explanation in the 'onboarding splash' view. */ /* Label indicating that the phone number is invalid in the 'onboarding phone number' view. */
"ONBOARDING_SPLASH_EXPLANATION" = "By continuing, you agree to Signal's terms."; "ONBOARDING_PHONE_NUMBER_VALIDATION_WARNING" = "Invalid number";
/* Link to the 'terms and privacy policy' in the 'onboarding splash' view. */ /* Link to the 'terms and privacy policy' in the 'onboarding splash' view. */
"ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY" = "Terms and Privacy Policy"; "ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY" = "Terms & Privacy Policy";
/* Title of the 'onboarding splash' view. */ /* Title of the 'onboarding splash' view. */
"ONBOARDING_SPLASH_TITLE" = "Signal is the private messenger for everybody"; "ONBOARDING_SPLASH_TITLE" = "Signal is the private messenger for everybody";

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@ -36,6 +36,18 @@ NS_ASSUME_NONNULL_BEGIN
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption1Font; @property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption1Font;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption2Font; @property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption2Font;
#pragma mark - Dynamic Type Clamped
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeTitle1ClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeTitle2ClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeTitle3ClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeHeadlineClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeBodyClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeSubheadlineClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeFootnoteClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption1ClampedFont;
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption2ClampedFont;
#pragma mark - Styles #pragma mark - Styles
- (UIFont *)ows_italic; - (UIFont *)ows_italic;

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
#import "UIFont+OWS.h" #import "UIFont+OWS.h"
@ -97,6 +97,86 @@ NS_ASSUME_NONNULL_BEGIN
return [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2]; return [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2];
} }
#pragma mark - Dynamic Type Clamped
+ (UIFont *)preferredFontForTextStyleClamped:(UIFontTextStyle)fontTextStyle
{
// We clamp the dynamic type sizes at the max size available
// without "larger accessibility sizes" enabled.
static NSDictionary<UIFontTextStyle, NSNumber *> *maxPointSizeMap = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
maxPointSizeMap = @{
UIFontTextStyleTitle1 : @(34.0),
UIFontTextStyleTitle2 : @(28.0),
UIFontTextStyleTitle3 : @(26.0),
UIFontTextStyleHeadline : @(23.0),
UIFontTextStyleBody : @(23.0),
UIFontTextStyleSubheadline : @(21.0),
UIFontTextStyleFootnote : @(19.0),
UIFontTextStyleCaption1 : @(18.0),
UIFontTextStyleCaption2 : @(17.0),
};
});
UIFont *font = [UIFont preferredFontForTextStyle:fontTextStyle];
NSNumber *_Nullable maxPointSize = maxPointSizeMap[fontTextStyle];
if (maxPointSize) {
if (maxPointSize.floatValue < font.pointSize) {
return [font fontWithSize:maxPointSize.floatValue];
}
} else {
OWSFailDebug(@"Missing max point size for style: %@", fontTextStyle);
}
return font;
}
+ (UIFont *)ows_dynamicTypeTitle1ClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleTitle1];
}
+ (UIFont *)ows_dynamicTypeTitle2ClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleTitle2];
}
+ (UIFont *)ows_dynamicTypeTitle3ClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleTitle3];
}
+ (UIFont *)ows_dynamicTypeHeadlineClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleHeadline];
}
+ (UIFont *)ows_dynamicTypeBodyClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleBody];
}
+ (UIFont *)ows_dynamicTypeSubheadlineClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleSubheadline];
}
+ (UIFont *)ows_dynamicTypeFootnoteClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleFootnote];
}
+ (UIFont *)ows_dynamicTypeCaption1ClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleCaption1];
}
+ (UIFont *)ows_dynamicTypeCaption2ClampedFont
{
return [UIFont preferredFontForTextStyleClamped:UIFontTextStyleCaption2];
}
#pragma mark - Styles #pragma mark - Styles
- (UIFont *)ows_italic - (UIFont *)ows_italic

Loading…
Cancel
Save