Merge branch 'charlesmchen/onboardingCleanup'

This commit is contained in:
Matthew Chen 2019-02-15 08:57:43 -05:00
commit 0e62514541
11 changed files with 235 additions and 127 deletions

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

View file

@ -31,37 +31,31 @@ public class OnboardingBaseViewController: OWSViewController {
let titleLabel = UILabel()
titleLabel.text = text
titleLabel.textColor = Theme.primaryColor
titleLabel.font = UIFont.ows_dynamicTypeTitle2.ows_mediumWeight()
titleLabel.font = UIFont.ows_dynamicTypeTitle1Clamped.ows_mediumWeight()
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.textAlignment = .center
return titleLabel
}
func explanationLabel(explanationText: String, linkText: String, selector: Selector) -> UILabel {
let explanationText = NSAttributedString(string: explanationText)
.rtlSafeAppend(NSAttributedString(string: " "))
.rtlSafeAppend(linkText,
attributes: [
NSAttributedStringKey.foregroundColor: UIColor.ows_materialBlue
])
func explanationLabel(explanationText: String) -> UILabel {
let explanationLabel = UILabel()
explanationLabel.textColor = Theme.secondaryColor
explanationLabel.font = UIFont.ows_dynamicTypeCaption1
explanationLabel.attributedText = explanationText
explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped
explanationLabel.text = explanationText
explanationLabel.numberOfLines = 0
explanationLabel.textAlignment = .center
explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.isUserInteractionEnabled = true
explanationLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: selector))
return explanationLabel
}
func button(title: String, selector: Selector) -> OWSFlatButton {
// 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,
font: OWSFlatButton.fontForHeight(buttonHeight),
font: font,
titleColor: .white,
backgroundColor: .ows_materialBlue,
target: self,
@ -70,11 +64,28 @@ public class OnboardingBaseViewController: OWSViewController {
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
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
// TODO: Is there a better way to do this?
if let navigationController = self.navigationController as? OWSNavigationController {
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
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {

View file

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

View file

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

View file

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

View file

@ -14,9 +14,6 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
view.backgroundColor = Theme.backgroundColor
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 heroImageView = UIImageView(image: heroImage)
heroImageView.contentMode = .scaleAspectFit
@ -29,12 +26,16 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
view.addSubview(titleLabel)
titleLabel.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom)
// TODO: Finalize copy.
let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_SPLASH_EXPLANATION",
comment: "Explanation in the 'onboarding splash' view."),
linkText: NSLocalizedString("ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY",
comment: "Link to the 'terms and privacy policy' in the 'onboarding splash' view."),
selector: #selector(explanationLabelTapped))
let explanationLabel = UILabel()
explanationLabel.text = NSLocalizedString("ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY",
comment: "Link to the 'terms and privacy policy' in the 'onboarding splash' view.")
explanationLabel.textColor = .ows_materialBlue
explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped
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.
let continueButton = self.button(title: NSLocalizedString("BUTTON_CONTINUE",
@ -46,9 +47,9 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
heroImageView,
UIView.spacer(withHeight: 22),
titleLabel,
UIView.spacer(withHeight: 56),
UIView.spacer(withHeight: 92),
explanationLabel,
UIView.spacer(withHeight: 40),
UIView.spacer(withHeight: 24),
continueButton
])
stackView.axis = .vertical
@ -56,23 +57,11 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)
stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins()
stackView.autoPinWidthToSuperview()
stackView.autoPin(toTopLayoutGuideOf: 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
@objc func explanationLabelTapped(sender: UIGestureRecognizer) {

View file

@ -1511,29 +1511,26 @@
/* Title of the 'onboarding Captcha' view. */
"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. */
"ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON" = "Give Access";
"ONBOARDING_PERMISSIONS_ENABLE_PERMISSIONS_BUTTON" = "Enable Permissions";
/* Link to the 'learn more' in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_LEARN_MORE_LINK" = "Learn More";
/* Explanation in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_EXPLANATION" = "Your contact information is always transmitted securely.";
/* Label for the 'not now' button in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON" = "Not Now";
/* 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. */
"ONBOARDING_PHONE_NUMBER_TITLE" = "Enter your phone number to get started";
/* Explanation in the 'onboarding splash' view. */
"ONBOARDING_SPLASH_EXPLANATION" = "By continuing, you agree to Signal's terms.";
/* Label indicating that the phone number is invalid in the 'onboarding phone number' view. */
"ONBOARDING_PHONE_NUMBER_VALIDATION_WARNING" = "Invalid number";
/* 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. */
"ONBOARDING_SPLASH_TITLE" = "Signal is the private messenger for everybody";

View file

@ -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>
@ -36,6 +36,18 @@ NS_ASSUME_NONNULL_BEGIN
@property (class, readonly, nonatomic) UIFont *ows_dynamicTypeCaption1Font;
@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
- (UIFont *)ows_italic;

View file

@ -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"
@ -97,6 +97,86 @@ NS_ASSUME_NONNULL_BEGIN
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
- (UIFont *)ows_italic