Add contact share approval view.

This commit is contained in:
Matthew Chen 2018-05-03 14:07:49 -04:00
parent 6e18d84a10
commit 7a9acce504
7 changed files with 525 additions and 92 deletions

View File

@ -49,6 +49,7 @@
34330A5E1E787BD800DF2FB9 /* ElegantIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5D1E787BD800DF2FB9 /* ElegantIcons.ttf */; };
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34330AA21E79686200DF2FB9 /* OWSProgressView.m */; };
34382266209A4E400094FEB7 /* ApproveContactShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34382265209A4E3F0094FEB7 /* ApproveContactShareViewController.swift */; };
3438226A209B63500094FEB7 /* EditContactShareNameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34382269209B63500094FEB7 /* EditContactShareNameViewController.swift */; };
34386A51207D0C01009F5D9C /* HomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34386A4D207D0C01009F5D9C /* HomeViewController.m */; };
34386A52207D0C01009F5D9C /* HomeViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 34386A50207D0C01009F5D9C /* HomeViewCell.m */; };
34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34386A53207D271C009F5D9C /* NeverClearView.swift */; };
@ -632,6 +633,7 @@
34330AA11E79686200DF2FB9 /* OWSProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSProgressView.h; sourceTree = "<group>"; };
34330AA21E79686200DF2FB9 /* OWSProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSProgressView.m; sourceTree = "<group>"; };
34382265209A4E3F0094FEB7 /* ApproveContactShareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ApproveContactShareViewController.swift; path = SignalMessaging/attachments/ApproveContactShareViewController.swift; sourceTree = SOURCE_ROOT; };
34382269209B63500094FEB7 /* EditContactShareNameViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EditContactShareNameViewController.swift; path = SignalMessaging/attachments/EditContactShareNameViewController.swift; sourceTree = SOURCE_ROOT; };
34386A4D207D0C01009F5D9C /* HomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeViewController.m; sourceTree = "<group>"; };
34386A4E207D0C01009F5D9C /* HomeViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeViewCell.h; sourceTree = "<group>"; };
34386A4F207D0C01009F5D9C /* HomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeViewController.h; sourceTree = "<group>"; };
@ -1602,6 +1604,7 @@
344F2498200FD03200CFB4F4 /* AttachmentApprovalViewController.swift */,
344F248220069E9B00CFB4F4 /* CountryCodeViewController.h */,
344F248320069E9B00CFB4F4 /* CountryCodeViewController.m */,
34382269209B63500094FEB7 /* EditContactShareNameViewController.swift */,
346129DC1FD5C02900532771 /* LockInteractionController.h */,
346129DD1FD5C02900532771 /* LockInteractionController.m */,
344F2496200FD03200CFB4F4 /* MessageApprovalViewController.swift */,
@ -3098,6 +3101,7 @@
451F8A481FD715BA005CB9DA /* OWSContactAvatarBuilder.m in Sources */,
34382266209A4E400094FEB7 /* ApproveContactShareViewController.swift in Sources */,
4503F1C3204711D300CEE724 /* OWS107LegacySounds.m in Sources */,
3438226A209B63500094FEB7 /* EditContactShareNameViewController.swift in Sources */,
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */,
4598198F204E2F28009414F2 /* OWS108CallLoggingPreference.m in Sources */,
346129D21FD2085A00532771 /* CommonStrings.swift in Sources */,

View File

@ -14,7 +14,7 @@ class TappableView: UIView {
// MARK: - Initializers
@available(*, unavailable, message: "use init(call:) constructor instead.")
@available(*, unavailable, message: "use other constructor instead.")
required init?(coder aDecoder: NSCoder) {
fatalError("Unimplemented")
}

View File

@ -445,6 +445,21 @@
/* Label for the 'street' field of a contact's address. */
"CONTACT_FIELD_ADDRESS_STREET" = "Street";
/* Label for the 'family name' field of a contact. */
"CONTACT_FIELD_FAMILY_NAME" = "Family Name";
/* Label for the 'given name' field of a contact. */
"CONTACT_FIELD_GIVEN_NAME" = "Given Name";
/* Label for the 'middle name' field of a contact. */
"CONTACT_FIELD_MIDDLE_NAME" = "Middle Name";
/* Label for the 'name prefix' field of a contact. */
"CONTACT_FIELD_NAME_PREFIX" = "Prefix";
/* Label for the 'name suffix' field of a contact. */
"CONTACT_FIELD_NAME_SUFFIX" = "Suffix";
/* Label for a contact's phone number. */
"CONTACT_PHONE" = "Phone";
@ -460,6 +475,9 @@
/* Title for the 'Approve contact share' view. */
"CONTACT_SHARE_APPROVAL_VIEW_TITLE" = "Share Contact";
/* Title for the 'edit contact share name' view. */
"CONTACT_SHARE_EDIT_NAME_VIEW_TITLE" = "Edit Name";
/* Indicates that a contact has no name. */
"CONTACT_WITHOUT_NAME" = "Unnamed Contact";

View File

@ -15,7 +15,7 @@ public protocol ApproveContactShareViewControllerDelegate: class {
class ContactShareField: NSObject {
var isIncludedFlag = true
private var isIncludedFlag = true
func localizedLabel() -> String {
preconditionFailure("This method must be overridden")
@ -25,9 +25,13 @@ class ContactShareField: NSObject {
return isIncludedFlag
}
func setIsIncluded(isIncluded: Bool) {
func setIsIncluded(_ isIncluded: Bool) {
isIncludedFlag = isIncluded
}
func applyToContact(contact: OWSContact) {
preconditionFailure("This method must be overridden")
}
}
// MARK: -
@ -45,6 +49,17 @@ class ContactSharePhoneNumber: ContactShareField {
override func localizedLabel() -> String {
return value.localizedLabel()
}
override func applyToContact(contact: OWSContact) {
assert(isIncluded())
var values = [OWSContactPhoneNumber]()
if let oldValues = contact.phoneNumbers {
values += oldValues
}
values.append(value)
contact.phoneNumbers = values
}
}
// MARK: -
@ -62,6 +77,17 @@ class ContactShareEmail: ContactShareField {
override func localizedLabel() -> String {
return value.localizedLabel()
}
override func applyToContact(contact: OWSContact) {
assert(isIncluded())
var values = [OWSContactEmail]()
if let oldValues = contact.emails {
values += oldValues
}
values.append(value)
contact.emails = values
}
}
// MARK: -
@ -79,6 +105,17 @@ class ContactShareAddress: ContactShareField {
override func localizedLabel() -> String {
return value.localizedLabel()
}
override func applyToContact(contact: OWSContact) {
assert(isIncluded())
var values = [OWSContactAddress]()
if let oldValues = contact.addresses {
values += oldValues
}
values.append(value)
contact.addresses = values
}
}
// MARK: -
@ -158,23 +195,25 @@ class ContactShareFieldView: UIView {
guard sender.state == .recognized else {
return
}
checkbox.isSelected = !checkbox.isSelected
field.setIsIncluded(!field.isIncluded())
checkbox.isSelected = field.isIncluded()
}
}
// MARK: -
@objc
public class ApproveContactShareViewController: OWSViewController {
public class ApproveContactShareViewController: OWSViewController, EditContactShareNameViewControllerDelegate {
weak var delegate: ApproveContactShareViewControllerDelegate?
let contactsManager: OWSContactsManager
let contactsManager: OWSContactsManager
let contactShare: OWSContact
var contactShare: OWSContact
var fields = [ContactShareField]()
var fieldViews = [ContactShareFieldView]()
var nameLabel: UILabel!
// MARK: Initializers
@available(*, unavailable, message:"use other constructor instead.")
@ -194,7 +233,6 @@ public class ApproveContactShareViewController: OWSViewController {
}
func buildFields() {
var fields = [ContactShareField]()
var fieldViews = [ContactShareFieldView]()
// TODO: Avatar
@ -202,7 +240,6 @@ public class ApproveContactShareViewController: OWSViewController {
if let phoneNumbers = contactShare.phoneNumbers {
for phoneNumber in phoneNumbers {
let field = ContactSharePhoneNumber(phoneNumber)
fields.append(field)
let fieldView = ContactShareFieldView(field: field, previewViewBlock: { [weak self] _ in
guard let strongSelf = self else { return UIView() }
return strongSelf.previewView(forPhoneNumber: phoneNumber)
@ -214,7 +251,6 @@ public class ApproveContactShareViewController: OWSViewController {
if let emails = contactShare.emails {
for email in emails {
let field = ContactShareEmail(email)
fields.append(field)
let fieldView = ContactShareFieldView(field: field, previewViewBlock: { [weak self] _ in
guard let strongSelf = self else { return UIView() }
return strongSelf.previewView(forEmail: email)
@ -226,7 +262,6 @@ public class ApproveContactShareViewController: OWSViewController {
if let addresses = contactShare.addresses {
for address in addresses {
let field = ContactShareAddress(address)
fields.append(field)
let fieldView = ContactShareFieldView(field: field, previewViewBlock: { [weak self] _ in
guard let strongSelf = self else { return UIView() }
return strongSelf.previewView(forAddress: address)
@ -235,7 +270,6 @@ public class ApproveContactShareViewController: OWSViewController {
}
}
self.fields = fields
self.fieldViews = fieldViews
}
@ -290,7 +324,7 @@ public class ApproveContactShareViewController: OWSViewController {
if canShareContact() {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("ATTACHMENT_APPROVAL_SEND_BUTTON",
comment: "Label for 'send' button in the 'attachment approval' dialog."),
style: .plain, target: self, action: #selector(didPressSendButton))
style: .plain, target: self, action: #selector(didPressSendButton))
} else {
self.navigationItem.rightBarButtonItem = nil
}
@ -391,6 +425,7 @@ public class ApproveContactShareViewController: OWSViewController {
stackView.axis = .horizontal
stackView.alignment = .center
stackView.layoutMargins = .zero
stackView.spacing = 10
row.addSubview(stackView)
stackView.autoPinLeadingToSuperviewMargin()
stackView.autoPinTrailingToSuperviewMargin()
@ -398,6 +433,7 @@ public class ApproveContactShareViewController: OWSViewController {
stackView.autoPinBottomToSuperviewMargin()
let nameLabel = UILabel()
self.nameLabel = nameLabel
nameLabel.text = contactShare.displayName
nameLabel.font = UIFont.ows_dynamicTypeBody
nameLabel.textColor = UIColor.ows_materialBlue
@ -518,6 +554,24 @@ public class ApproveContactShareViewController: OWSViewController {
// MARK: -
func filteredContactShare() -> OWSContact {
let result = self.contactShare.newContact(withNamePrefix: self.contactShare.namePrefix,
givenName: self.contactShare.givenName,
middleName: self.contactShare.middleName,
familyName: self.contactShare.familyName,
nameSuffix: self.contactShare.nameSuffix)
for fieldView in fieldViews {
if fieldView.field.isIncluded() {
fieldView.field.applyToContact(contact: result)
}
}
return result
}
// MARK: -
func didPressSendButton() {
Logger.info("\(logTag) \(#function)")
@ -526,7 +580,10 @@ public class ApproveContactShareViewController: OWSViewController {
return
}
delegate.approveContactShare(self, didApproveContactShare: contactShare)
let filteredContactShare = self.filteredContactShare()
assert(filteredContactShare.ows_isValid())
delegate.approveContactShare(self, didApproveContactShare: filteredContactShare)
}
func didPressCancel() {
@ -543,6 +600,17 @@ public class ApproveContactShareViewController: OWSViewController {
func didPressEditName() {
Logger.info("\(logTag) \(#function)")
// TODO:
let view = EditContactShareNameViewController(contactShare: contactShare, delegate: self)
self.navigationController?.pushViewController(view, animated: true)
}
// MARK: - EditContactShareNameViewControllerDelegate
public func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: OWSContact) {
self.contactShare = contactShare
nameLabel.text = contactShare.displayName
self.updateNavigationBar()
}
}

View File

@ -0,0 +1,347 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import SignalServiceKit
@objc
public protocol ContactNameFieldViewDelegate: class {
func nameFieldDidChange()
}
// MARK: -
class ContactNameFieldView: UIView {
weak var delegate: ContactNameFieldViewDelegate?
let name: String
let initialValue: String?
var valueView: UITextField!
var hasUnsavedChanges = false
// MARK: - Initializers
@available(*, unavailable, message: "use other constructor instead.")
required init?(coder aDecoder: NSCoder) {
fatalError("Unimplemented")
}
required init(name: String, value: String?, delegate: ContactNameFieldViewDelegate) {
self.name = name
self.initialValue = value
self.delegate = delegate
super.init(frame: CGRect.zero)
self.isUserInteractionEnabled = true
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(wasTapped)))
createContents()
}
func createContents() {
let vMargin = CGFloat(10)
self.layoutMargins = UIEdgeInsets(top: vMargin, left: 0, bottom: vMargin, right: 0)
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .center
stackView.layoutMargins = .zero
stackView.spacing = 10
self.addSubview(stackView)
stackView.autoPinTopToSuperviewMargin()
stackView.autoPinBottomToSuperviewMargin()
stackView.autoPinLeadingToSuperviewMargin()
stackView.autoPinTrailingToSuperviewMargin()
let nameLabel = UILabel()
nameLabel.text = name
nameLabel.font = UIFont.ows_dynamicTypeBody
nameLabel.textColor = UIColor.ows_materialBlue
nameLabel.lineBreakMode = .byTruncatingTail
stackView.addArrangedSubview(nameLabel)
nameLabel.setContentHuggingHigh()
nameLabel.setCompressionResistanceHigh()
valueView = UITextField()
if let initialValue = initialValue {
valueView.text = initialValue
}
valueView.font = UIFont.ows_dynamicTypeBody
valueView.textColor = UIColor.black
stackView.addArrangedSubview(valueView)
valueView.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}
func wasTapped(sender: UIGestureRecognizer) {
Logger.info("\(self.logTag) \(#function)")
guard sender.state == .recognized else {
return
}
valueView.becomeFirstResponder()
}
func textFieldDidChange(sender: UITextField) {
Logger.info("\(self.logTag) \(#function)")
hasUnsavedChanges = true
guard let delegate = self.delegate else {
owsFail("\(logTag) missing delegate.")
return
}
delegate.nameFieldDidChange()
}
public func value() -> String {
guard let value = valueView.text else {
return ""
}
return value
}
}
// MARK: -
@objc
public protocol EditContactShareNameViewControllerDelegate: class {
func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: OWSContact)
}
// MARK: -
@objc
public class EditContactShareNameViewController: OWSViewController, ContactNameFieldViewDelegate {
weak var delegate: EditContactShareNameViewControllerDelegate?
let contactShare: OWSContact
var namePrefixView: ContactNameFieldView!
var givenNameView: ContactNameFieldView!
var middleNameView: ContactNameFieldView!
var familyNameView: ContactNameFieldView!
var nameSuffixView: ContactNameFieldView!
var fieldViews = [ContactNameFieldView]()
// MARK: Initializers
@available(*, unavailable, message:"use other constructor instead.")
required public init?(coder aDecoder: NSCoder) {
fatalError("unimplemented")
}
@objc
required public init(contactShare: OWSContact, delegate: EditContactShareNameViewControllerDelegate) {
self.contactShare = contactShare
self.delegate = delegate
super.init(nibName: nil, bundle: nil)
buildFields()
}
func buildFields() {
namePrefixView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_NAME_PREFIX", comment: "Label for the 'name prefix' field of a contact."),
value: contactShare.namePrefix, delegate: self)
givenNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_GIVEN_NAME", comment: "Label for the 'given name' field of a contact."),
value: contactShare.givenName, delegate: self)
middleNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_MIDDLE_NAME", comment: "Label for the 'middle name' field of a contact."),
value: contactShare.middleName, delegate: self)
familyNameView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_FAMILY_NAME", comment: "Label for the 'family name' field of a contact."),
value: contactShare.familyName, delegate: self)
nameSuffixView = ContactNameFieldView(name: NSLocalizedString("CONTACT_FIELD_NAME_SUFFIX", comment: "Label for the 'name suffix' field of a contact."),
value: contactShare.nameSuffix, delegate: self)
fieldViews = [
namePrefixView ,
givenNameView ,
middleNameView ,
familyNameView ,
nameSuffixView
]
}
override public var canBecomeFirstResponder: Bool {
return true
}
// MARK: - View Lifecycle
override public func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateNavigationBar()
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override public func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override public func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
override public func loadView() {
super.loadView()
self.navigationItem.title = NSLocalizedString("CONTACT_SHARE_EDIT_NAME_VIEW_TITLE",
comment: "Title for the 'edit contact share name' view.")
self.view.preservesSuperviewLayoutMargins = false
self.view.backgroundColor = UIColor.white
updateContent()
updateNavigationBar()
}
func hasUnsavedChanges() -> Bool {
for fieldView in fieldViews {
if fieldView.hasUnsavedChanges {
return true
}
}
return false
}
func updateNavigationBar() {
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(didPressCancel))
if hasUnsavedChanges() {
self.navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .save,
target: self,
action: #selector(didPressSave))
} else {
self.navigationItem.rightBarButtonItem = nil
}
}
private func updateContent() {
SwiftAssertIsOnMainThread(#function)
guard let rootView = self.view else {
owsFail("\(logTag) missing root view.")
return
}
for subview in rootView.subviews {
subview.removeFromSuperview()
}
let scrollView = UIScrollView()
scrollView.preservesSuperviewLayoutMargins = false
self.view.addSubview(scrollView)
scrollView.layoutMargins = .zero
scrollView.autoPinWidthToSuperview()
scrollView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
scrollView.autoPinEdge(toSuperviewEdge: .bottom)
let fieldsView = createFieldsView()
// See notes on how to use UIScrollView with iOS Auto Layout:
//
// https://developer.apple.com/library/content/releasenotes/General/RN-iOSSDK-6_0/
scrollView.addSubview(fieldsView)
fieldsView.autoPinLeadingToSuperviewMargin()
fieldsView.autoPinTrailingToSuperviewMargin()
fieldsView.autoPinEdge(toSuperviewEdge: .top)
fieldsView.autoPinEdge(toSuperviewEdge: .bottom)
}
private func createFieldsView() -> UIView {
SwiftAssertIsOnMainThread(#function)
let fieldsView = UIView.container()
fieldsView.layoutMargins = .zero
fieldsView.preservesSuperviewLayoutMargins = false
var lastRow: UIView?
let addSpacerRow = {
guard let prevRow = lastRow else {
owsFail("\(self.logTag) missing last row")
return
}
let row = UIView()
row.backgroundColor = UIColor(rgbHex: 0xdedee1)
fieldsView.addSubview(row)
row.autoSetDimension(.height, toSize: 1)
row.autoPinLeadingToSuperviewMargin(withInset: self.hMargin)
row.autoPinTrailingToSuperviewMargin()
row.autoPinEdge(.top, to: .bottom, of: prevRow, withOffset: 0)
lastRow = row
}
let addRow: ((UIView) -> Void) = { (row) in
if lastRow != nil {
addSpacerRow()
}
fieldsView.addSubview(row)
row.autoPinLeadingToSuperviewMargin(withInset: self.hMargin)
row.autoPinTrailingToSuperviewMargin(withInset: self.hMargin)
if let lastRow = lastRow {
row.autoPinEdge(.top, to: .bottom, of: lastRow, withOffset: 0)
} else {
row.autoPinEdge(toSuperviewEdge: .top, withInset: 0)
}
lastRow = row
}
for fieldView in fieldViews {
addRow(fieldView)
}
lastRow?.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0)
return fieldsView
}
private let hMargin = CGFloat(16)
// MARK: -
func didPressSave() {
Logger.info("\(logTag) \(#function)")
let modifiedContactShare = contactShare.copy(withNamePrefix: namePrefixView.value(),
givenName: givenNameView.value(),
middleName: middleNameView.value(),
familyName: familyNameView.value(),
nameSuffix: nameSuffixView.value())
guard let delegate = self.delegate else {
owsFail("\(logTag) missing delegate.")
return
}
delegate.editContactShareNameView(self, didEditContactShare: modifiedContactShare)
self.navigationController?.popViewController(animated: true)
}
func didPressCancel() {
Logger.info("\(logTag) \(#function)")
self.navigationController?.popViewController(animated: true)
}
// MARK: - ContactNameFieldViewDelegate
public func nameFieldDidChange() {
updateNavigationBar()
}
}

View File

@ -128,6 +128,20 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value);
- (NSString *)debugDescription;
#pragma mark - Creation and Derivation
- (OWSContact *)newContactWithNamePrefix:(nullable NSString *)namePrefix
givenName:(nullable NSString *)givenName
middleName:(nullable NSString *)middleName
familyName:(nullable NSString *)familyName
nameSuffix:(nullable NSString *)nameSuffix;
- (OWSContact *)copyContactWithNamePrefix:(nullable NSString *)namePrefix
givenName:(nullable NSString *)givenName
middleName:(nullable NSString *)middleName
familyName:(nullable NSString *)familyName
nameSuffix:(nullable NSString *)nameSuffix;
@end
#pragma mark -
@ -154,10 +168,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value);
+ (nullable OWSSignalServiceProtosDataMessageContact *)protoForContact:(OWSContact *)contact;
+ (OWSContact *_Nullable)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage;
//#pragma mark - Old Contacts
//
//+ (nullable OWSContact *)contactForOldContact:(Contact *)oldContact
@end
NS_ASSUME_NONNULL_END

View File

@ -124,7 +124,7 @@ NSString *NSStringForContactEmailType(OWSContactEmailType value)
DDLogWarn(@"%@ invalid email: %@.", self.logTag, self.email);
return NO;
}
return YES;
return YES;
}
- (NSString *)localizedLabel
@ -203,7 +203,7 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
DDLogWarn(@"%@ invalid address; empty.", self.logTag);
return NO;
}
return YES;
return YES;
}
- (NSString *)localizedLabel
@ -362,6 +362,13 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
}
}
- (void)updateDisplayName
{
_displayName = nil;
[self ensureDisplayName];
}
- (NSString *)debugDescription
{
NSMutableString *result = [NSMutableString new];
@ -400,6 +407,55 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
return result;
}
- (OWSContact *)newContactWithNamePrefix:(nullable NSString *)namePrefix
givenName:(nullable NSString *)givenName
middleName:(nullable NSString *)middleName
familyName:(nullable NSString *)familyName
nameSuffix:(nullable NSString *)nameSuffix
{
OWSContact *newContact = [OWSContact new];
[newContact setNamePrefix:namePrefix
givenName:givenName
middleName:middleName
familyName:familyName
nameSuffix:nameSuffix];
return newContact;
}
- (OWSContact *)copyContactWithNamePrefix:(nullable NSString *)namePrefix
givenName:(nullable NSString *)givenName
middleName:(nullable NSString *)middleName
familyName:(nullable NSString *)familyName
nameSuffix:(nullable NSString *)nameSuffix
{
OWSContact *contactCopy = [self copy];
[contactCopy setNamePrefix:namePrefix
givenName:givenName
middleName:middleName
familyName:familyName
nameSuffix:nameSuffix];
return contactCopy;
}
- (void)setNamePrefix:(nullable NSString *)namePrefix
givenName:(nullable NSString *)givenName
middleName:(nullable NSString *)middleName
familyName:(nullable NSString *)familyName
nameSuffix:(nullable NSString *)nameSuffix
{
self.namePrefix = namePrefix.ows_stripped;
self.givenName = givenName.ows_stripped;
self.middleName = middleName.ows_stripped;
self.familyName = familyName.ows_stripped;
self.nameSuffix = nameSuffix.ows_stripped;
[self updateDisplayName];
}
@end
#pragma mark -
@ -960,76 +1016,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
return result;
}
//#pragma mark - Old Contacts
//
//+ (nullable OWSContact *)contactForOldContact:(Contact *)oldContact
//{
// OWSAssert(oldContact);
// OWSAssert(oldContact.cnContact);
//
//// DDLogDebug(@"%@ in %s with contact: %@", self.logTag, __PRETTY_FUNCTION__, contact);
//
// return [self contactForSystemContact:oldContact.cnContact];
//
//// OWSContact *newContact = [OWSContact new];
////
//// newContact.givenName = oldContact.firstName;
//// newContact.familyName = oldContact.lastName;
////
//// NSMutableArray<
//// OWSContactPhoneNumber *> *newPhoneNumbers = [NSMutableArray new];
//// for (NSString *oldPhoneNumber in oldContact.userTextPhoneNumbers) {
//// OWSContactPhoneNumber *newPhoneNumber = [OWSContactPhoneNumber new];
//// newPhoneNumber.phoneNumber = oldPhoneNumber;
//// newPhoneNumber.phoneType = OWSContactPhoneType_Custom;
//// [newPhoneNumbers addObject:newPhoneNumber];
//// }
//// newContact.phoneNumbers = newPhoneNumbers;
////
//// NSMutableArray<
//// OWSContactEmail *> *newEmails = [NSMutableArray new];
//// for (NSString *oldEmail in oldContact.emails) {
//// OWSContactEmail *newEmail = [OWSContactEmail new];
//// newEmail.email = oldEmail;
//// newEmail.emailType = OWSContactEmailType_Custom;
//// [newEmails addObject:newEmail];
//// }
//// newContact.emails = newEmails;
////
//// @interface Contact : MTLModel
////
//// @property (nullable, readonly, nonatomic) NSString *firstName;
//// @property (nullable, readonly, nonatomic) NSString *lastName;
//// @property (readonly, nonatomic) NSString *fullName;
//// @property (readonly, nonatomic) NSString *comparableNameFirstLast;
//// @property (readonly, nonatomic) NSString *comparableNameLastFirst;
//// @property (readonly, nonatomic) NSArray<PhoneNumber *> *parsedPhoneNumbers;
//// @property (readonly, nonatomic) NSArray<NSString *> *userTextPhoneNumbers;
//// @property (readonly, nonatomic) NSArray<NSString *> *emails;
//// @property (readonly, nonatomic) NSString *uniqueId;
//// @property (nonatomic, readonly) BOOL isSignalContact;
////#if TARGET_OS_IOS
//// @property (nullable, readonly, nonatomic) UIImage *image;
//// @property (nullable, nonatomic, readonly) CNContact *cnContact;
////#endif // TARGET_OS_IOS
////
//// - (NSArray<SignalRecipient *> *)signalRecipientsWithTransaction:(YapDatabaseReadTransaction *)transaction;
//// // TODO: Remove this method.
//// - (NSArray<NSString *> *)textSecureIdentifiers;
////
////#if TARGET_OS_IOS
////
//// - (instancetype)initWithSystemContact:(CNContact *)contact NS_AVAILABLE_IOS(9_0);
////
//// - (NSString *)nameForPhoneNumber:(NSString *)recipientId;
////
////#endif // TARGET_OS_IOS
////
//// + (NSComparator)comparatorSortingNamesByFirstThenLast:(BOOL)firstNameOrdering;
////
//// @end
//}
@end
NS_ASSUME_NONNULL_END