Sketch out the 'onboarding profile' view.

This commit is contained in:
Matthew Chen 2019-02-15 16:46:06 -05:00
parent d81e9d41fb
commit afcacbb55c
12 changed files with 468 additions and 31 deletions

View File

@ -166,6 +166,7 @@
3496957421A301A100DCFE74 /* OWSBackupAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496956B21A301A100DCFE74 /* OWSBackupAPI.swift */; };
349EA07C2162AEA800F7B17F /* OWS111UDAttributesMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */; };
34A4C61E221613D00042EF2E /* OnboardingVerificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */; };
34A4C62022175C5C0042EF2E /* OnboardingProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */; };
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */; };
34A6C28021E503E700B5B12E /* OWSImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */; };
34A8B3512190A40E00218A25 /* MediaAlbumCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A8B3502190A40E00218A25 /* MediaAlbumCellView.swift */; };
@ -848,6 +849,7 @@
3496956D21A301A100DCFE74 /* OWSBackupIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackupIO.h; sourceTree = "<group>"; };
349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS111UDAttributesMigration.swift; sourceTree = "<group>"; };
34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingVerificationViewController.swift; sourceTree = "<group>"; };
34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingProfileViewController.swift; sourceTree = "<group>"; };
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS2FARegistrationViewController.m; sourceTree = "<group>"; };
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS2FARegistrationViewController.h; sourceTree = "<group>"; };
34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSImagePickerController.swift; sourceTree = "<group>"; };
@ -1474,6 +1476,7 @@
3448E15D221333F5004B052E /* OnboardingController.swift */,
3448E15B22133274004B052E /* OnboardingPermissionsViewController.swift */,
3448E16322135FFA004B052E /* OnboardingPhoneNumberViewController.swift */,
34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */,
3448E15F22134C88004B052E /* OnboardingSplashViewController.swift */,
34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */,
346E9D5321B040B600562252 /* RegistrationController.swift */,
@ -3491,6 +3494,7 @@
343A65981FC4CFE7000477A1 /* ConversationScrollButton.m in Sources */,
34386A51207D0C01009F5D9C /* HomeViewController.m in Sources */,
34D1F0A91F867BFC0066283D /* ConversationViewCell.m in Sources */,
34A4C62022175C5C0042EF2E /* OnboardingProfileViewController.swift in Sources */,
4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */,
EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */,
45CD81EF1DC030E7004C9430 /* SyncPushTokensJob.swift in Sources */,

View File

@ -8,6 +8,7 @@
// Separate iOS Frameworks from other imports.
#import "AppSettingsViewController.h"
#import "AttachmentUploadView.h"
#import "AvatarViewHelper.h"
#import "ContactCellView.h"
#import "ContactTableViewCell.h"
#import "ConversationViewCell.h"

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
@protocol AvatarViewHelperDelegate <NSObject>
- (NSString *)avatarActionSheetTitle;
- (nullable NSString *)avatarActionSheetTitle;
- (void)avatarDidChange:(UIImage *)image;

View File

@ -482,6 +482,19 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
[self.searchResultsController viewDidAppear:animated];
self.hasEverAppeared = YES;
dispatch_async(dispatch_get_main_queue(), ^{
OnboardingController *onboardingController = [OnboardingController new];
[onboardingController
updateWithPhoneNumber:[[OnboardingPhoneNumber alloc] initWithE164:@"+13213214321" userInput:@"3213214321"]];
// UIViewController *view = [onboardingController initialViewController];
UIViewController *view =
[[OnboardingProfileViewController alloc] initWithOnboardingController:onboardingController];
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:view];
[self presentViewController:navigationController animated:YES completion:nil];
});
}
- (void)viewDidDisappear:(BOOL)animated

View File

@ -612,7 +612,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - AvatarViewHelperDelegate
- (NSString *)avatarActionSheetTitle
- (nullable NSString *)avatarActionSheetTitle
{
return NSLocalizedString(
@"NEW_GROUP_ADD_PHOTO_ACTION", @"Action Sheet title prompting the user for a group avatar");

View File

@ -573,7 +573,7 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
#pragma mark - AvatarViewHelperDelegate
- (NSString *)avatarActionSheetTitle
- (nullable NSString *)avatarActionSheetTitle
{
return NSLocalizedString(
@"PROFILE_VIEW_AVATAR_ACTIONSHEET_TITLE", @"Action Sheet title prompting the user for a profile avatar");

View File

@ -450,3 +450,21 @@ public class OnboardingController: NSObject {
}
}
}
// MARK: -
public extension UIView {
public func addBottomStroke() -> UIView {
return addBottomStroke(color: Theme.middleGrayColor, strokeWidth: CGHairlineWidth())
}
public func addBottomStroke(color: UIColor, strokeWidth: CGFloat) -> UIView {
let strokeView = UIView()
strokeView.backgroundColor = color
addSubview(strokeView)
strokeView.autoSetDimension(.height, toSize: strokeWidth)
strokeView.autoPinWidthToSuperview()
strokeView.autoPinEdge(toSuperviewEdge: .bottom)
return strokeView
}
}

View File

@ -62,7 +62,7 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
countryRow.isUserInteractionEnabled = true
countryRow.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryRowTapped)))
countryRow.autoSetDimension(.height, toSize: rowHeight)
_ = addBottomStroke(countryRow)
_ = countryRow.addBottomStroke()
callingCodeLabel.textColor = Theme.primaryColor
callingCodeLabel.font = UIFont.ows_dynamicTypeBodyClamped
@ -70,7 +70,7 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
callingCodeLabel.setCompressionResistanceHorizontalHigh()
callingCodeLabel.isUserInteractionEnabled = true
callingCodeLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(countryCodeTapped)))
_ = addBottomStroke(callingCodeLabel)
_ = callingCodeLabel.addBottomStroke()
callingCodeLabel.autoSetDimension(.width, toSize: rowHeight, relation: .greaterThanOrEqual)
phoneNumberTextField.textAlignment = .left
@ -81,8 +81,8 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
phoneNumberTextField.setContentHuggingHorizontalLow()
phoneNumberTextField.setCompressionResistanceHorizontalLow()
phoneStrokeNormal = addBottomStroke(phoneNumberTextField)
phoneStrokeError = addBottomStroke(phoneNumberTextField, color: .ows_destructiveRed, strokeWidth: 2)
phoneStrokeNormal = phoneNumberTextField.addBottomStroke()
phoneStrokeError = phoneNumberTextField.addBottomStroke(color: .ows_destructiveRed, strokeWidth: 2)
let phoneNumberRow = UIStackView(arrangedSubviews: [
callingCodeLabel,
@ -140,20 +140,6 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
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, color: UIColor, strokeWidth: CGFloat) -> UIView {
let strokeView = UIView()
strokeView.backgroundColor = color
view.addSubview(strokeView)
strokeView.autoSetDimension(.height, toSize: strokeWidth)
strokeView.autoPinWidthToSuperview()
strokeView.autoPinEdge(toSuperviewEdge: .bottom)
return strokeView
}
// MARK: - View Lifecycle
public override func viewWillAppear(_ animated: Bool) {

View File

@ -0,0 +1,412 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@objc
public class OnboardingProfileViewController: OnboardingBaseViewController {
// private var titleLabel: UILabel?
// private let phoneNumberTextField = UITextField()
// private let onboardingCodeView = OnboardingCodeView()
// private var codeStateLink: OWSFlatButton?
// private let errorLabel = UILabel()
private let avatarView = AvatarImageView()
private let nameTextfield = UITextField()
private var avatar: UIImage?
private let cameraCircle = UIView.container()
private let avatarViewHelper = AvatarViewHelper()
override public func loadView() {
super.loadView()
avatarViewHelper.delegate = self
view.backgroundColor = Theme.backgroundColor
view.layoutMargins = .zero
let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PROFILE_TITLE", comment: "Title of the 'onboarding profile' view."))
let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_PROFILE_EXPLANATION",
comment: "Explanation in the 'onboarding profile' view."))
let nextButton = self.button(title: NSLocalizedString("BUTTON_NEXT",
comment: "Label for the 'next' button."),
selector: #selector(nextPressed))
avatarView.autoSetDimensions(to: CGSize(width: CGFloat(avatarSize), height: CGFloat(avatarSize)))
let cameraImageView = UIImageView()
cameraImageView.image = UIImage(named: "settings-avatar-camera")
cameraCircle.backgroundColor = Theme.backgroundColor
cameraCircle.addSubview(cameraImageView)
let cameraCircleDiameter: CGFloat = 40
cameraCircle.autoSetDimensions(to: CGSize(width: cameraCircleDiameter, height: cameraCircleDiameter))
cameraCircle.layer.shadowColor = UIColor(white: 0, alpha: 0.15).cgColor
cameraCircle.layer.shadowRadius = 5
cameraCircle.layer.shadowOffset = CGSize(width: 1, height: 1)
cameraCircle.layer.shadowOpacity = 1
cameraCircle.layer.cornerRadius = cameraCircleDiameter * 0.5
cameraCircle.clipsToBounds = false
cameraImageView.autoCenterInSuperview()
let avatarWrapper = UIView.container()
avatarWrapper.isUserInteractionEnabled = true
avatarWrapper.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(avatarTapped)))
avatarWrapper.addSubview(avatarView)
avatarView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 4, leading: 4, bottom: 4, trailing: 4))
avatarWrapper.addSubview(cameraCircle)
cameraCircle.autoPinEdge(toSuperviewEdge: .trailing)
cameraCircle.autoPinEdge(toSuperviewEdge: .bottom)
nameTextfield.textAlignment = .left
nameTextfield.delegate = self
nameTextfield.returnKeyType = .done
nameTextfield.textColor = Theme.primaryColor
// nameTextfield.tintColor = UIColor.ows_materialBlue
nameTextfield.font = UIFont.ows_dynamicTypeBodyClamped
nameTextfield.placeholder = NSLocalizedString("ONBOARDING_PROFILE_NAME_PLACEHOLDER",
comment: "Placeholder text for the profile name in the 'onboarding profile' view.")
nameTextfield.setContentHuggingHorizontalLow()
nameTextfield.setCompressionResistanceHorizontalLow()
let nameWrapper = UIView.container()
nameWrapper.setCompressionResistanceHorizontalLow()
nameWrapper.setContentHuggingHorizontalLow()
nameWrapper.addSubview(nameTextfield)
nameTextfield.autoPinWidthToSuperview()
nameTextfield.autoPinEdge(toSuperviewEdge: .top, withInset: 8)
nameTextfield.autoPinEdge(toSuperviewEdge: .bottom, withInset: 8)
_ = nameWrapper.addBottomStroke()
let profileRow = UIStackView(arrangedSubviews: [
avatarWrapper,
nameWrapper
])
profileRow.axis = .horizontal
profileRow.alignment = .center
profileRow.spacing = 8
let topSpacer = UIView.vStretchingSpacer()
let bottomSpacer = UIView.vStretchingSpacer()
let stackView = UIStackView(arrangedSubviews: [
titleLabel,
topSpacer,
profileRow,
UIView.spacer(withHeight: 25),
explanationLabel,
UIView.spacer(withHeight: 20),
nextButton,
bottomSpacer
])
stackView.axis = .vertical
stackView.alignment = .fill
stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, 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)
updateAvatarView()
}
private let avatarSize: UInt = 80
private func updateAvatarView() {
if let avatar = avatar {
avatarView.image = avatar
cameraCircle.isHidden = true
return
}
let defaultAvatar = OWSContactAvatarBuilder(forLocalUserWithDiameter: avatarSize).buildDefaultImage()
avatarView.image = defaultAvatar
cameraCircle.isHidden = false
}
// // MARK: - Code State
//
// private let countdownDuration: TimeInterval = 60
// private var codeCountdownTimer: Timer?
// private var codeCountdownStart: NSDate?
//
// deinit {
// if let codeCountdownTimer = codeCountdownTimer {
// codeCountdownTimer.invalidate()
// }
// }
//
// private func startCodeCountdown() {
// codeCountdownStart = NSDate()
// codeCountdownTimer = Timer.weakScheduledTimer(withTimeInterval: 1, target: self, selector: #selector(codeCountdownTimerFired), userInfo: nil, repeats: true)
// }
//
// @objc
// public func codeCountdownTimerFired() {
// guard let codeCountdownStart = codeCountdownStart else {
// owsFailDebug("Missing codeCountdownStart.")
// return
// }
// guard let codeCountdownTimer = codeCountdownTimer else {
// owsFailDebug("Missing codeCountdownTimer.")
// return
// }
//
// let countdownInterval = abs(codeCountdownStart.timeIntervalSinceNow)
//
// guard countdownInterval < countdownDuration else {
// // Countdown complete.
// codeCountdownTimer.invalidate()
// self.codeCountdownTimer = nil
//
// if codeState != .pending {
// owsFailDebug("Unexpected codeState: \(codeState)")
// }
// codeState = .possiblyNotDelivered
// updateCodeState()
// return
// }
//
// // Update the "code state" UI to reflect the countdown.
// updateCodeState()
// }
//
// private func updateCodeState() {
// AssertIsOnMainThread()
//
// guard let codeCountdownStart = codeCountdownStart else {
// owsFailDebug("Missing codeCountdownStart.")
// return
// }
// guard let titleLabel = titleLabel else {
// owsFailDebug("Missing titleLabel.")
// return
// }
// guard let codeStateLink = codeStateLink else {
// owsFailDebug("Missing codeStateLink.")
// return
// }
//
// var e164PhoneNumber = ""
// if let phoneNumber = onboardingController.phoneNumber {
// e164PhoneNumber = phoneNumber.e164
// }
// let formattedPhoneNumber = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: e164PhoneNumber)
//
// // Update titleLabel
// switch codeState {
// case .pending, .possiblyNotDelivered:
// titleLabel.text = String(format: NSLocalizedString("ONBOARDING_VERIFICATION_TITLE_DEFAULT_FORMAT",
// comment: "Format for the title of the 'onboarding verification' view. Embeds {{the user's phone number}}."),
// formattedPhoneNumber)
// case .resent:
// titleLabel.text = String(format: NSLocalizedString("ONBOARDING_VERIFICATION_TITLE_RESENT_FORMAT",
// comment: "Format for the title of the 'onboarding verification' view after the verification code has been resent. Embeds {{the user's phone number}}."),
// formattedPhoneNumber)
// }
//
// // Update codeStateLink
// switch codeState {
// case .pending:
// let countdownInterval = abs(codeCountdownStart.timeIntervalSinceNow)
// let countdownRemaining = max(0, countdownDuration - countdownInterval)
// let formattedCountdown = OWSFormat.formatDurationSeconds(Int(round(countdownRemaining)))
// let text = String(format: NSLocalizedString("ONBOARDING_VERIFICATION_CODE_COUNTDOWN_FORMAT",
// comment: "Format for the label of the 'pending code' label of the 'onboarding verification' view. Embeds {{the time until the code can be resent}}."),
// formattedCountdown)
// codeStateLink.setTitle(title: text, font: .ows_dynamicTypeBodyClamped, titleColor: Theme.secondaryColor)
//// codeStateLink.setBackgroundColors(upColor: Theme.backgroundColor)
// case .possiblyNotDelivered:
// codeStateLink.setTitle(title: NSLocalizedString("ONBOARDING_VERIFICATION_ORIGINAL_CODE_MISSING_LINK",
// comment: "Label for link that can be used when the original code did not arrive."),
// font: .ows_dynamicTypeBodyClamped,
// titleColor: .ows_materialBlue)
// case .resent:
// codeStateLink.setTitle(title: NSLocalizedString("ONBOARDING_VERIFICATION_RESENT_CODE_MISSING_LINK",
// comment: "Label for link that can be used when the resent code did not arrive."),
// font: .ows_dynamicTypeBodyClamped,
// titleColor: .ows_materialBlue)
// }
// }
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
_ = nameTextfield.becomeFirstResponder()
}
// MARK: - Events
@objc func avatarTapped(sender: UIGestureRecognizer) {
guard sender.state == .recognized else {
return
}
showAvatarActionSheet()
}
@objc func nextPressed() {
Logger.info("")
// TODO:
// parseAndTryToRegister()
}
private func showAvatarActionSheet() {
AssertIsOnMainThread()
Logger.info("")
avatarViewHelper.showChangeAvatarUI()
// let alert = UIAlertController(title: NSLocalizedString("CHECK_FOR_BACKUP_FAILED_TITLE",
// comment: "Title for alert shown when the app failed to check for an existing backup."),
// message: NSLocalizedString("CHECK_FOR_BACKUP_FAILED_MESSAGE",
// comment: "Message for alert shown when the app failed to check for an existing backup."),
// preferredStyle: .alert)
// alert.addAction(UIAlertAction(title: NSLocalizedString("REGISTER_FAILED_TRY_AGAIN", comment: ""),
// style: .default) { (_) in
// self.checkCanImportBackup(fromView: view)
// })
// alert.addAction(UIAlertAction(title: NSLocalizedString("CHECK_FOR_BACKUP_DO_NOT_RESTORE", comment: "The label for the 'do not restore backup' button."),
// style: .destructive) { (_) in
// self.showProfileView(fromView: view)
// })
// view.present(alert, animated: true)
}
// @objc func backLinkTapped() {
// Logger.info("")
//
// self.navigationController?.popViewController(animated: true)
// }
//
// @objc func resendCodeLinkTapped() {
// Logger.info("")
//
// switch codeState {
// case .pending:
// // Ignore taps until the countdown expires.
// break
// case .possiblyNotDelivered, .resent:
// showResendActionSheet()
// }
// }
//
// private func showResendActionSheet() {
// Logger.info("")
//
// let actionSheet = UIAlertController(title: NSLocalizedString("ONBOARDING_VERIFICATION_RESEND_CODE_ALERT_TITLE",
// comment: "Title for the 'resend code' alert in the 'onboarding verification' view."),
// message: NSLocalizedString("ONBOARDING_VERIFICATION_RESEND_CODE_ALERT_MESSAGE",
// comment: "Message for the 'resend code' alert in the 'onboarding verification' view."),
// preferredStyle: .actionSheet)
//
// actionSheet.addAction(UIAlertAction(title: NSLocalizedString("ONBOARDING_VERIFICATION_RESEND_CODE_BY_SMS_BUTTON",
// comment: "Label for the 'resend code by SMS' button in the 'onboarding verification' view."),
// style: .default) { _ in
// self.onboardingController.tryToRegister(fromViewController: self, smsVerification: true)
// })
// actionSheet.addAction(UIAlertAction(title: NSLocalizedString("ONBOARDING_VERIFICATION_RESEND_CODE_BY_VOICE_BUTTON",
// comment: "Label for the 'resend code by voice' button in the 'onboarding verification' view."),
// style: .default) { _ in
// self.onboardingController.tryToRegister(fromViewController: self, smsVerification: false)
// })
// actionSheet.addAction(OWSAlerts.cancelAction)
//
// self.present(actionSheet, animated: true)
// }
//
// private func tryToVerify() {
// Logger.info("")
//
// guard onboardingCodeView.isComplete else {
// return
// }
//
// setHasInvalidCode(false)
//
// onboardingController.tryToVerify(fromViewController: self, verificationCode: onboardingCodeView.verificationCode, pin: nil, isInvalidCodeCallback: {
// self.setHasInvalidCode(true)
// })
// }
//
// private func setHasInvalidCode(_ value: Bool) {
// onboardingCodeView.setHasError(value)
// errorLabel.isHidden = !value
// }
//}
//
//// MARK: -
//
//extension OnboardingProfileViewController: OnboardingCodeViewDelegate {
// public func codeViewDidChange() {
// AssertIsOnMainThread()
//
// setHasInvalidCode(false)
//
// tryToVerify()
// }
}
// MARK: -
extension OnboardingProfileViewController: UITextFieldDelegate {
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// // 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 true
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// parseAndTryToRegister()
return false
}
}
// MARK: -
extension OnboardingProfileViewController: AvatarViewHelperDelegate {
public func avatarActionSheetTitle() -> String? {
return nil
}
public func avatarDidChange(_ image: UIImage) {
AssertIsOnMainThread()
let maxDiameter = CGFloat(kOWSProfileManager_MaxAvatarDiameter)
avatar = image.resizedImage(toFillPixelSize: CGSize(width: maxDiameter,
height: maxDiameter))
updateAvatarView()
}
public func fromViewController() -> UIViewController {
return self
}
public func hasClearAvatarAction() -> Bool {
return avatar != nil
}
public func clearAvatar() {
avatar = nil
updateAvatarView()
}
public func clearAvatarActionLabel() -> String {
return NSLocalizedString("PROFILE_VIEW_CLEAR_AVATAR", comment: "Label for action that clear's the user's profile avatar")
}
}

View File

@ -133,14 +133,8 @@ private class OnboardingCodeView: UIView {
digitView.addSubview(digitLabel)
digitLabel.autoCenterInSuperview()
let strokeView = UIView.container()
if hasStroke {
strokeView.backgroundColor = Theme.primaryColor
digitView.addSubview(strokeView)
strokeView.autoPinWidthToSuperview()
strokeView.autoPinEdge(toSuperviewEdge: .bottom)
strokeView.autoSetDimension(.height, toSize: 1)
}
let strokeColor = (hasStroke ? Theme.primaryColor : UIColor.clear)
let strokeView = digitView.addBottomStroke(color: strokeColor, strokeWidth: 1)
let vMargin: CGFloat = 4
let cellHeight: CGFloat = digitLabel.font.lineHeight + vMargin * 2

View File

@ -485,7 +485,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - AvatarViewHelperDelegate
- (NSString *)avatarActionSheetTitle
- (nullable NSString *)avatarActionSheetTitle
{
return NSLocalizedString(
@"NEW_GROUP_ADD_PHOTO_ACTION", @"Action Sheet title prompting the user for a group avatar");

View File

@ -1529,6 +1529,15 @@
/* Label indicating that the phone number is invalid in the 'onboarding phone number' view. */
"ONBOARDING_PHONE_NUMBER_VALIDATION_WARNING" = "Invalid number";
/* Explanation in the 'onboarding profile' view. */
"ONBOARDING_PROFILE_EXPLANATION" = "Signal profiles are end-to-end encrypted and the Signal service never has access to this information.";
/* Placeholder text for the profile name in the 'onboarding profile' view. */
"ONBOARDING_PROFILE_NAME_PLACEHOLDER" = "Your Name";
/* Title of the 'onboarding profile' view. */
"ONBOARDING_PROFILE_TITLE" = "Set up your profile";
/* Link to the 'terms and privacy policy' in the 'onboarding splash' view. */
"ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY" = "Terms & Privacy Policy";