Merge branch 'charlesmchen/contactShareDesign'

pull/1/head
Matthew Chen 7 years ago
commit 8622dba39f

@ -77,7 +77,6 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
required init(contact: OWSContact) {
contactsManager = Environment.current().contactsManager
self.contact = contact
self.scrollView = UIScrollView()
super.init(nibName: nil, bundle: nil)
@ -98,15 +97,16 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
// MARK: - View Lifecycle
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIUtil.applySignalAppearence()
if let navigationController = self.navigationController {
owsFail("\(logTag) missing navigationController")
navigationController.isNavigationBarHidden = true
}
contactsManager.requestSystemContactsOnce(completion: { [weak self] _ in
guard let strongSelf = self else { return }
strongSelf.updateMode()
@ -119,18 +119,24 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
UIUtil.applySignalAppearence()
}
private var scrollView: UIScrollView
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let navigationController = self.navigationController {
owsFail("\(logTag) missing navigationController")
navigationController.isNavigationBarHidden = false
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
override func loadView() {
super.loadView()
self.view.addSubview(scrollView)
scrollView.layoutMargins = .zero
scrollView.autoPinWidthToSuperview()
scrollView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
scrollView.autoPin(toBottomLayoutGuideOf: self, withInset: 0)
self.view.backgroundColor = UIColor.white
self.view.preservesSuperviewLayoutMargins = false
self.view.backgroundColor = heroBackgroundColor()
updateContent()
@ -185,26 +191,90 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
private func updateContent() {
SwiftAssertIsOnMainThread(#function)
let rootView = self.scrollView
guard let rootView = self.view else {
owsFail("\(logTag) missing root view.")
return
}
for subview in rootView.subviews {
subview.removeFromSuperview()
}
// TODO: The design calls for no navigation bar, just a back button.
let topView = UIView.container()
topView.backgroundColor = UIColor(rgbHex: 0xefeff4)
topView.preservesSuperviewLayoutMargins = true
let topView = createTopView()
rootView.addSubview(topView)
topView.autoPinEdge(toSuperviewEdge: .top)
topView.autoPinEdge(.left, to: .left, of: self.view)
topView.autoPinEdge(.right, to: .right, of: self.view)
topView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
topView.autoPinWidthToSuperview()
// This view provides a background "below the fold".
let bottomView = UIView.container()
bottomView.backgroundColor = UIColor.white
self.view.addSubview(bottomView)
bottomView.layoutMargins = .zero
bottomView.autoPinWidthToSuperview()
bottomView.autoPinEdge(.top, to: .bottom, of: topView)
bottomView.autoPinEdge(toSuperviewEdge: .bottom)
let scrollView = UIScrollView()
scrollView.preservesSuperviewLayoutMargins = false
self.view.addSubview(scrollView)
scrollView.layoutMargins = .zero
scrollView.autoPinWidthToSuperview()
scrollView.autoPinEdge(.top, to: .bottom, of: topView)
scrollView.autoPinEdge(toSuperviewEdge: .bottom)
let fieldsView = createFieldsView()
scrollView.addSubview(fieldsView)
fieldsView.autoPinLeadingToSuperviewMargin()
fieldsView.autoPinTrailingToSuperviewMargin()
fieldsView.autoPinEdge(toSuperviewEdge: .top)
fieldsView.autoPinEdge(toSuperviewEdge: .bottom)
}
private func heroBackgroundColor() -> UIColor {
return UIColor(rgbHex: 0xefeff4)
}
private func createTopView() -> UIView {
SwiftAssertIsOnMainThread(#function)
let topView = UIView.container()
topView.backgroundColor = heroBackgroundColor()
topView.preservesSuperviewLayoutMargins = false
// Back Button
let backButtonSize = CGFloat(50)
let backButton = TappableView(actionBlock: { [weak self] _ in
guard let strongSelf = self else { return }
strongSelf.didPressDismiss()
})
backButton.autoSetDimension(.width, toSize: backButtonSize)
backButton.autoSetDimension(.height, toSize: backButtonSize)
topView.addSubview(backButton)
backButton.autoPin(toTopLayoutGuideOf: self, withInset: 0)
backButton.autoPinLeadingToSuperviewMargin()
let backIconName = (self.view.isRTL() ? "system_disclosure_indicator" : "system_disclosure_indicator_rtl")
guard let backIconImage = UIImage(named: backIconName) else {
owsFail("\(logTag) missing icon.")
return topView
}
let backIconView = UIImageView(image: backIconImage.withRenderingMode(.alwaysTemplate))
backIconView.contentMode = .scaleAspectFit
backIconView.tintColor = UIColor.black.withAlphaComponent(0.6)
backButton.addSubview(backIconView)
backIconView.autoCenterInSuperview()
// TODO: Use actual avatar.
let avatarSize = CGFloat(100)
let avatarView = UIView.container()
avatarView.backgroundColor = UIColor.ows_materialBlue
avatarView.layer.cornerRadius = avatarSize * 0.5
let avatarView = AvatarImageView()
// TODO: What's the best colorSeed value to use?
let avatarBuilder = OWSContactAvatarBuilder(nonSignalName: contact.displayName,
colorSeed: contact.displayName,
diameter: UInt(avatarSize),
contactsManager: contactsManager)
avatarView.image = avatarBuilder.build()
topView.addSubview(avatarView)
avatarView.autoPin(toTopLayoutGuideOf: self, withInset: 20)
avatarView.autoHCenterInSuperview()
@ -226,7 +296,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
if let firstPhoneNumber = contact.phoneNumbers.first {
let phoneNumberLabel = UILabel()
phoneNumberLabel.text = firstPhoneNumber.phoneNumber
phoneNumberLabel.text = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: firstPhoneNumber.phoneNumber)
phoneNumberLabel.font = UIFont.ows_dynamicTypeCaption2
phoneNumberLabel.textColor = UIColor.black
phoneNumberLabel.lineBreakMode = .byTruncatingTail
@ -297,16 +367,15 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
lastView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 15)
let bottomView = UIView.container()
bottomView.backgroundColor = UIColor.white
bottomView.layoutMargins = .zero
bottomView.preservesSuperviewLayoutMargins = false
rootView.addSubview(bottomView)
bottomView.autoPinEdge(.top, to: .bottom, of: topView)
bottomView.autoPinEdge(toSuperviewEdge: .bottom)
bottomView.autoPinEdge(.left, to: .left, of: self.view)
bottomView.autoPinEdge(.right, to: .right, of: self.view)
bottomView.setContentHuggingVerticalLow()
return topView
}
private func createFieldsView() -> UIView {
SwiftAssertIsOnMainThread(#function)
let fieldsView = UIView.container()
fieldsView.layoutMargins = .zero
fieldsView.preservesSuperviewLayoutMargins = false
var lastRow: UIView?
@ -317,7 +386,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
}
let row = UIView()
row.backgroundColor = UIColor(rgbHex: 0xdedee1)
bottomView.addSubview(row)
fieldsView.addSubview(row)
row.autoSetDimension(.height, toSize: 1)
row.autoPinLeadingToSuperviewMargin(withInset: self.hMargin)
row.autoPinTrailingToSuperviewMargin()
@ -329,7 +398,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
if lastRow != nil {
addSpacerRow()
}
bottomView.addSubview(row)
fieldsView.addSubview(row)
row.autoPinLeadingToSuperviewMargin()
row.autoPinTrailingToSuperviewMargin()
if let lastRow = lastRow {
@ -359,9 +428,10 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
// }
for phoneNumber in contact.phoneNumbers {
// TODO: Try to format the phone number nicely.
let formattedPhoneNumber = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: phoneNumber.phoneNumber)
addRow(createNameValueRow(name: phoneNumber.localizedLabel(),
value: phoneNumber.phoneNumber,
value: formattedPhoneNumber,
actionBlock: {
guard let url = NSURL(string: "tel:\(phoneNumber.phoneNumber)") else {
owsFail("\(ContactViewController.logTag) could not open phone number.")
@ -386,6 +456,8 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
// TODO: Should we present addresses here too? How?
lastRow?.autoPinEdge(toSuperviewEdge: .bottom)
return fieldsView
}
private let hMargin = CGFloat(16)
@ -411,7 +483,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
return row
}
private func createNameValueRow(name: String, value: String, actionBlock : @escaping () -> Void) -> UIView {
private func createNameValueRow(name: String, value: String?, actionBlock : @escaping () -> Void) -> UIView {
let row = TappableView(actionBlock: actionBlock)
row.layoutMargins.left = 0
row.layoutMargins.right = 0
@ -527,40 +599,38 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
func didPressSendMessage() {
Logger.info("\(logTag) \(#function)")
// TODO: We're taking the first Signal account id. We might
// want to let the user select if there's more than one.
guard let recipientId = systemContactsWithSignalAccountsForContact().first else {
owsFail("\(logTag) missing Signal recipient id.")
return
}
SignalApp.shared().presentConversation(forRecipientId: recipientId, action: .compose)
presentThreadAndPeform(action: .compose)
}
func didPressAudioCall() {
Logger.info("\(logTag) \(#function)")
// TODO: We're taking the first Signal account id. We might
// want to let the user select if there's more than one.
guard let recipientId = systemContactsWithSignalAccountsForContact().first else {
owsFail("\(logTag) missing Signal recipient id.")
return
}
SignalApp.shared().presentConversation(forRecipientId: recipientId, action: .audioCall)
presentThreadAndPeform(action: .audioCall)
}
func didPressVideoCall() {
Logger.info("\(logTag) \(#function)")
presentThreadAndPeform(action: .videoCall)
}
func presentThreadAndPeform(action: ConversationViewAction) {
// TODO: We're taking the first Signal account id. We might
// want to let the user select if there's more than one.
guard let recipientId = systemContactsWithSignalAccountsForContact().first else {
let phoneNumbers = systemContactsWithSignalAccountsForContact()
guard phoneNumbers.count > 0 else {
owsFail("\(logTag) missing Signal recipient id.")
return
}
guard phoneNumbers.count > 1 else {
let recipientId = systemContactsWithSignalAccountsForContact().first!
SignalApp.shared().presentConversation(forRecipientId: recipientId, action: action)
return
}
SignalApp.shared().presentConversation(forRecipientId: recipientId, action: .videoCall)
showPhoneNumberPicker(phoneNumbers: phoneNumbers, completion: { (recipientId) in
SignalApp.shared().presentConversation(forRecipientId: recipientId, action: action)
})
}
func didPressInvite() {
@ -582,6 +652,27 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
inviteFlow.sendSMSTo(phoneNumbers: phoneNumbers)
}
private func showPhoneNumberPicker(phoneNumbers: [String], completion :@escaping ((String) -> Void)) {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for phoneNumber in phoneNumbers {
actionSheet.addAction(UIAlertAction(title: PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: phoneNumber),
style: .default) { _ in
completion(phoneNumber)
})
}
actionSheet.addAction(OWSAlerts.cancelAction)
self.present(actionSheet, animated: true)
}
func didPressDismiss() {
Logger.info("\(self.logTag) \(#function)")
self.navigationController?.popViewController(animated: true)
}
// MARK: -
private func presentNewContactView() {

@ -3,10 +3,14 @@
//
#import "OWSContactShareView.h"
#import "OWSContactAvatarBuilder.h"
#import "Signal-Swift.h"
#import "UIColor+JSQMessages.h"
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIView+OWS.h"
#import <SignalMessaging/Environment.h>
#import <SignalMessaging/SignalMessaging-Swift.h>
#import <SignalServiceKit/OWSContact.h>
NS_ASSUME_NONNULL_BEGIN
@ -101,22 +105,19 @@ NS_ASSUME_NONNULL_BEGIN
[contentView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:self.vMargin];
[contentView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:self.vMargin];
UIView *iconCircleView = [UIView containerView];
iconCircleView.backgroundColor = [UIColor colorWithRGBHex:0x00ffff];
iconCircleView.layer.cornerRadius = self.iconSize * 0.5f;
[iconCircleView autoSetDimension:ALDimensionWidth toSize:self.iconSize];
[iconCircleView autoSetDimension:ALDimensionHeight toSize:self.iconSize];
[iconCircleView setCompressionResistanceHigh];
[iconCircleView setContentHuggingHigh];
// TODO: Use avatar, if present and downloaded. else default.
UIImage *image = [UIImage imageNamed:@"attachment_file"];
OWSAssert(image);
UIImageView *imageView = [UIImageView new];
imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.tintColor = self.bubbleBackgroundColor;
[iconCircleView addSubview:imageView];
[imageView autoCenterInSuperview];
// TODO: Use the contact's avatar if present and downloaded.
AvatarImageView *avatarView = [AvatarImageView new];
// TODO: What's the best colorSeed value to use?
OWSAvatarBuilder *avatarBuilder =
[[OWSContactAvatarBuilder alloc] initWithNonSignalName:self.contactShare.displayName
colorSeed:self.contactShare.displayName
diameter:(NSUInteger)self.iconSize
contactsManager:[Environment current].contactsManager];
avatarView.image = [avatarBuilder build];
[avatarView autoSetDimension:ALDimensionWidth toSize:self.iconSize];
[avatarView autoSetDimension:ALDimensionHeight toSize:self.iconSize];
[avatarView setCompressionResistanceHigh];
[avatarView setContentHuggingHigh];
UILabel *topLabel = [UILabel new];
topLabel.text = self.contactShare.displayName;
@ -135,7 +136,7 @@ NS_ASSUME_NONNULL_BEGIN
NSString *_Nullable firstPhoneNumber = self.contactShare.phoneNumbers.firstObject.phoneNumber;
if (firstPhoneNumber.length > 0) {
UILabel *bottomLabel = [UILabel new];
bottomLabel.text = firstPhoneNumber;
bottomLabel.text = [PhoneNumber bestEffortLocalizedPhoneNumberWithE164:firstPhoneNumber];
// TODO:
bottomLabel.textColor = [UIColor ows_darkGrayColor];
bottomLabel.lineBreakMode = NSLineBreakByTruncatingTail;
@ -166,7 +167,7 @@ NS_ASSUME_NONNULL_BEGIN
[stackView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
[stackView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
[stackView addArrangedSubview:iconCircleView];
[stackView addArrangedSubview:avatarView];
[stackView addArrangedSubview:labelsView];
[stackView addArrangedSubview:disclosureImageView];
}

@ -3000,17 +3000,14 @@ typedef OWSContact * (^OWSContactBlock)(void);
phoneNumber2,
];
OWSContactEmail *email1 = [OWSContactEmail new];
email1.emailType = OWSContactEmailType_Home;
email1.email = @"a1@b.com";
OWSContactEmail *email2 = [OWSContactEmail new];
email2.emailType = OWSContactEmailType_Custom;
email2.label = @"customer support";
email2.email = @"a2@b.com";
contact.emails = @[
email1,
email2,
];
NSMutableArray<OWSContactEmail *> *emails = [NSMutableArray new];
for (NSUInteger i = 0; i < 16; i++) {
OWSContactEmail *email = [OWSContactEmail new];
email.emailType = OWSContactEmailType_Home;
email.email = [NSString stringWithFormat:@"a%zd@b.com", i];
[emails addObject:email];
}
contact.emails = emails;
OWSContactAddress *address1 = [OWSContactAddress new];
address1.addressType = OWSContactAddressType_Home;
@ -3178,17 +3175,14 @@ typedef OWSContact * (^OWSContactBlock)(void);
phoneNumber2,
];
OWSContactEmail *email1 = [OWSContactEmail new];
email1.emailType = OWSContactEmailType_Home;
email1.email = @"a@b.com";
OWSContactEmail *email2 = [OWSContactEmail new];
email2.emailType = OWSContactEmailType_Custom;
email2.label = @"customer support";
email2.email = @"a@b.com";
contact.emails = @[
email1,
email2,
];
NSMutableArray<OWSContactEmail *> *emails = [NSMutableArray new];
for (NSUInteger i = 0; i < 16; i++) {
OWSContactEmail *email = [OWSContactEmail new];
email.emailType = OWSContactEmailType_Home;
email.email = [NSString stringWithFormat:@"a%zd@b.com", i];
[emails addObject:email];
}
contact.emails = emails;
OWSContactAddress *address1 = [OWSContactAddress new];
address1.addressType = OWSContactAddressType_Home;

@ -110,8 +110,11 @@ class ReminderView: UIView {
// Icon
let iconName = (self.isRTL() ? "system_disclosure_indicator_rtl" : "system_disclosure_indicator")
let iconImage = UIImage(named: iconName)?.withRenderingMode(.alwaysTemplate)
let iconView = UIImageView(image: iconImage)
guard let iconImage = UIImage(named: iconName) else {
owsFail("\(logTag) missing icon.")
return
}
let iconView = UIImageView(image: iconImage.withRenderingMode(.alwaysTemplate))
iconView.contentMode = .scaleAspectFit
iconView.tintColor = UIColor.black.withAlphaComponent(0.6)
container.addSubview(iconView)

@ -406,6 +406,9 @@
/* Generic button text to proceed with an action */
"CONFIRMATION_TITLE" = "Confirm";
/* Label for a contact's postal address. */
"CONTACT_ADDRESS" = "Address";
/* An indicator that a contact has been blocked. */
"CONTACT_CELL_IS_BLOCKED" = "Blocked";
@ -415,6 +418,12 @@
/* No comment provided by engineer. */
"CONTACT_DETAIL_COMM_TYPE_INSECURE" = "Unregistered Number";
/* Label for a contact's email address. */
"CONTACT_EMAIL" = "Email";
/* Label for a contact's phone number. */
"CONTACT_PHONE" = "Phone";
/* table cell subtitle when contact card has no email */
"CONTACT_PICKER_NO_EMAILS_AVAILABLE" = "No email available.";
@ -424,6 +433,9 @@
/* navbar title for contact picker when sharing a contact */
"CONTACT_PICKER_TITLE" = "Select Contact";
/* Indicates that a contact has no name. */
"CONTACT_WITHOUT_NAME" = "Unnamed Contact";
/* title for conversation settings screen */
"CONVERSATION_SETTINGS" = "Conversation Settings";

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#define COUNTRY_CODE_PREFIX @"+"
@ -30,6 +30,7 @@
+ (NSString *)bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString *)input;
+ (NSString *)bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString *)input
withSpecifiedCountryCodeString:(NSString *)countryCodeString;
+ (NSString *)bestEffortLocalizedPhoneNumberWithE164:(NSString *)phoneNumber;
+ (NSString *)regionCodeFromCountryCodeString:(NSString *)countryCodeString;

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "PhoneNumber.h"
@ -119,6 +119,45 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
return result;
}
+ (NSString *)formatIntAsEN:(int)value
{
static NSNumberFormatter *formatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
formatter = [NSNumberFormatter new];
formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
});
return [formatter stringFromNumber:@(value)];
}
+ (NSString *)bestEffortLocalizedPhoneNumberWithE164:(NSString *)phoneNumber
{
OWSAssert(phoneNumber);
PhoneNumber *_Nullable parsedPhoneNumber = [self tryParsePhoneNumberFromE164:phoneNumber];
if (!parsedPhoneNumber) {
DDLogWarn(@"%@ could not parse phone number.", self.logTag);
return phoneNumber;
}
NSNumber *_Nullable countryCode = [parsedPhoneNumber getCountryCode];
if (!countryCode) {
DDLogWarn(@"%@ parsed phone number has no country code.", self.logTag);
return phoneNumber;
}
NSString *countryCodeString = [self formatIntAsEN:countryCode.intValue];
if (countryCodeString.length < 1) {
DDLogWarn(@"%@ invalid country code.", self.logTag);
return phoneNumber;
}
NSString *_Nullable formattedPhoneNumber =
[self bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:phoneNumber
withSpecifiedRegionCode:countryCodeString];
if (!countryCode) {
DDLogWarn(@"%@ could not format phone number.", self.logTag);
return phoneNumber;
}
return formattedPhoneNumber;
}
+ (NSString *)regionCodeFromCountryCodeString:(NSString *)countryCodeString {
NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedUtil].nbPhoneNumberUtil;

@ -55,7 +55,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, nullable) NSString *namePrefix;
@property (nonatomic, nullable) NSString *middleName;
@property (nonatomic, nullable) NSString *organizationName;
@property (nonatomic, nullable) NSString *displayName;
@property (nonatomic) NSString *displayName;
@property (nonatomic) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
@property (nonatomic) NSArray<OWSContactEmail *> *emails;

@ -109,7 +109,7 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value);
@property (nonatomic, readonly, nullable) NSString *namePrefix;
@property (nonatomic, readonly, nullable) NSString *middleName;
@property (nonatomic, readonly, nullable) NSString *organizationName;
@property (nonatomic, readonly, nullable) NSString *displayName;
@property (nonatomic, readonly) NSString *displayName;
@property (nonatomic, readonly) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
@property (nonatomic, readonly) NSArray<OWSContactEmail *> *emails;

@ -49,18 +49,7 @@ NSString *NSStringForContactPhoneType(OWSContactPhoneType value)
DDLogWarn(@"%@ invalid phone number; not e164: %@.", self.logTag, self.phoneNumber);
return NO;
}
switch (self.phoneType) {
case OWSContactPhoneType_Home:
case OWSContactPhoneType_Mobile:
case OWSContactPhoneType_Work:
return YES;
case OWSContactPhoneType_Custom:
if (self.label.ows_stripped.length < 1) {
DDLogWarn(@"%@ invalid phone number; missing custom label: %@.", self.logTag, self.label);
return NO;
}
return YES;
}
return YES;
}
- (NSString *)localizedLabel
@ -73,7 +62,10 @@ NSString *NSStringForContactPhoneType(OWSContactPhoneType value)
case OWSContactPhoneType_Work:
return [CNLabeledValue localizedStringForLabel:CNLabelWork];
default:
return self.label;
if (self.label.ows_stripped.length < 1) {
return NSLocalizedString(@"CONTACT_PHONE", @"Label for a contact's phone number.");
}
return self.label.ows_stripped;
}
}
@ -130,18 +122,7 @@ NSString *NSStringForContactEmailType(OWSContactEmailType value)
DDLogWarn(@"%@ invalid email: %@.", self.logTag, self.email);
return NO;
}
switch (self.emailType) {
case OWSContactEmailType_Home:
case OWSContactEmailType_Mobile:
case OWSContactEmailType_Work:
return YES;
case OWSContactEmailType_Custom:
if (self.label.ows_stripped.length < 1) {
DDLogWarn(@"%@ invalid email; missing custom label: %@.", self.logTag, self.label);
return NO;
}
return YES;
}
}
- (NSString *)localizedLabel
@ -154,7 +135,10 @@ NSString *NSStringForContactEmailType(OWSContactEmailType value)
case OWSContactEmailType_Work:
return [CNLabeledValue localizedStringForLabel:CNLabelWork];
default:
return self.label;
if (self.label.ows_stripped.length < 1) {
return NSLocalizedString(@"CONTACT_EMAIL", @"Label for a contact's email address.");
}
return self.label.ows_stripped;
}
}
@ -217,17 +201,7 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
DDLogWarn(@"%@ invalid address; empty.", self.logTag);
return NO;
}
switch (self.addressType) {
case OWSContactAddressType_Home:
case OWSContactAddressType_Work:
return YES;
case OWSContactAddressType_Custom:
if (self.label.ows_stripped.length < 1) {
DDLogWarn(@"%@ invalid address; missing custom label: %@.", self.logTag, self.label);
return NO;
}
return YES;
}
}
- (NSString *)localizedLabel
@ -238,7 +212,10 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
case OWSContactAddressType_Work:
return [CNLabeledValue localizedStringForLabel:CNLabelWork];
default:
return self.label;
if (self.label.ows_stripped.length < 1) {
return NSLocalizedString(@"CONTACT_ADDRESS", @"Label for a contact's postal address.");
}
return self.label.ows_stripped;
}
}
@ -288,7 +265,7 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
@property (nonatomic, nullable) NSString *namePrefix;
@property (nonatomic, nullable) NSString *middleName;
@property (nonatomic, nullable) NSString *organizationName;
@property (nonatomic, nullable) NSString *displayName;
@property (nonatomic) NSString *displayName;
@property (nonatomic) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
@property (nonatomic) NSArray<OWSContactEmail *> *emails;
@ -360,10 +337,14 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
return hasValue;
}
- (nullable NSString *)displayName
- (NSString *)displayName
{
[self ensureDisplayName];
if (_displayName.length < 1) {
OWSProdLogAndFail(@"%@ could not derive a valid display name.", self.logTag);
return NSLocalizedString(@"CONTACT_WITHOUT_NAME", @"Indicates that a contact has no name.");
}
return _displayName;
}
@ -377,9 +358,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
// Fall back to using the organization name.
_displayName = self.organizationName;
}
if (_displayName.length < 1) {
OWSProdLogAndFail(@"%@ could not derive a valid display name.", self.logTag);
}
}
- (NSString *)debugDescription

Loading…
Cancel
Save