|
|
@ -4,6 +4,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
#import "Contact.h"
|
|
|
|
#import "Contact.h"
|
|
|
|
#import "Cryptography.h"
|
|
|
|
#import "Cryptography.h"
|
|
|
|
|
|
|
|
#import "NSString+SSK.h"
|
|
|
|
#import "OWSPrimaryStorage.h"
|
|
|
|
#import "OWSPrimaryStorage.h"
|
|
|
|
#import "PhoneNumber.h"
|
|
|
|
#import "PhoneNumber.h"
|
|
|
|
#import "SignalRecipient.h"
|
|
|
|
#import "SignalRecipient.h"
|
|
|
@ -38,9 +39,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_cnContact = contact;
|
|
|
|
_cnContact = contact;
|
|
|
|
_firstName = [self trimName:contact.givenName];
|
|
|
|
_firstName = contact.givenName.ows_stripped;
|
|
|
|
_lastName = [self trimName:contact.familyName];
|
|
|
|
_lastName = contact.familyName.ows_stripped;
|
|
|
|
_fullName = [CNContactFormatter stringFromContact:contact style:CNContactFormatterStyleFullName];
|
|
|
|
_fullName = [Contact formattedFullNameWithCNContact:contact];
|
|
|
|
_uniqueId = contact.identifier;
|
|
|
|
_uniqueId = contact.identifier;
|
|
|
|
|
|
|
|
|
|
|
|
NSMutableArray<NSString *> *phoneNumbers = [NSMutableArray new];
|
|
|
|
NSMutableArray<NSString *> *phoneNumbers = [NSMutableArray new];
|
|
|
@ -125,11 +126,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
return _image;
|
|
|
|
return _image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSString *)trimName:(NSString *)name
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return [name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey
|
|
|
|
+ (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ([propertyKey isEqualToString:@"cnContact"] || [propertyKey isEqualToString:@"image"]) {
|
|
|
|
if ([propertyKey isEqualToString:@"cnContact"] || [propertyKey isEqualToString:@"image"]) {
|
|
|
@ -250,6 +246,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ (NSString *)formattedFullNameWithCNContact:(CNContact *)cnContact
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return [CNContactFormatter stringFromContact:cnContact style:CNContactFormatterStyleFullName].ows_stripped;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSString *)nameForPhoneNumber:(NSString *)recipientId
|
|
|
|
- (NSString *)nameForPhoneNumber:(NSString *)recipientId
|
|
|
|
{
|
|
|
|
{
|
|
|
|
OWSAssert(recipientId.length > 0);
|
|
|
|
OWSAssert(recipientId.length > 0);
|
|
|
@ -290,6 +291,62 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
return hash;
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- (CNContact *)buildCNContactMergedWithNewContact:(CNContact *)newCNContact
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
CNMutableContact *_Nullable mergedCNContact = [self.cnContact mutableCopy];
|
|
|
|
|
|
|
|
if (!mergedCNContact) {
|
|
|
|
|
|
|
|
OWSFail(@"%@ in %s mergedCNContact was unexpectedly nil", self.logTag, __PRETTY_FUNCTION__);
|
|
|
|
|
|
|
|
return [CNContact new];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Name
|
|
|
|
|
|
|
|
NSString *formattedFullName = [self.class formattedFullNameWithCNContact:mergedCNContact];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// merged all or nothing - do not try to piece-meal merge.
|
|
|
|
|
|
|
|
if (formattedFullName.length == 0) {
|
|
|
|
|
|
|
|
mergedCNContact.namePrefix = newCNContact.namePrefix.ows_stripped;
|
|
|
|
|
|
|
|
mergedCNContact.givenName = newCNContact.givenName.ows_stripped;
|
|
|
|
|
|
|
|
mergedCNContact.middleName = newCNContact.middleName.ows_stripped;
|
|
|
|
|
|
|
|
mergedCNContact.familyName = newCNContact.familyName.ows_stripped;
|
|
|
|
|
|
|
|
mergedCNContact.nameSuffix = newCNContact.nameSuffix.ows_stripped;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Phone Numbers
|
|
|
|
|
|
|
|
NSSet<PhoneNumber *> *existingPhoneNumberSet = [NSSet setWithArray:self.parsedPhoneNumbers];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NSMutableArray<CNLabeledValue<CNPhoneNumber *> *> *mergedPhoneNumbers = [mergedCNContact.phoneNumbers mutableCopy];
|
|
|
|
|
|
|
|
for (CNLabeledValue<CNPhoneNumber *> *labeledPhoneNumber in newCNContact.phoneNumbers) {
|
|
|
|
|
|
|
|
PhoneNumber *_Nullable parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:labeledPhoneNumber.value.stringValue];
|
|
|
|
|
|
|
|
if (parsedPhoneNumber && ![existingPhoneNumberSet containsObject:parsedPhoneNumber]) {
|
|
|
|
|
|
|
|
[mergedPhoneNumbers addObject:labeledPhoneNumber];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
mergedCNContact.phoneNumbers = mergedPhoneNumbers;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Emails
|
|
|
|
|
|
|
|
NSSet<NSString *> *existingEmailSet = [NSSet setWithArray:self.emails];
|
|
|
|
|
|
|
|
NSMutableArray<CNLabeledValue<NSString *> *> *mergedEmailAddresses = [mergedCNContact.emailAddresses mutableCopy];
|
|
|
|
|
|
|
|
for (CNLabeledValue<NSString *> *labeledEmail in newCNContact.emailAddresses) {
|
|
|
|
|
|
|
|
NSString *normalizedValue = labeledEmail.value.ows_stripped;
|
|
|
|
|
|
|
|
if (![existingEmailSet containsObject:normalizedValue]) {
|
|
|
|
|
|
|
|
[mergedEmailAddresses addObject:labeledEmail];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
mergedCNContact.emailAddresses = mergedEmailAddresses;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Address
|
|
|
|
|
|
|
|
// merged all or nothing - do not try to piece-meal merge.
|
|
|
|
|
|
|
|
BOOL hasExistingAddress = NO;
|
|
|
|
|
|
|
|
for (CNLabeledValue<CNPostalAddress *> *labeledPostalAddress in mergedCNContact.postalAddresses) {
|
|
|
|
|
|
|
|
hasExistingAddress = YES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hasExistingAddress) {
|
|
|
|
|
|
|
|
mergedCNContact.postalAddresses = newCNContact.postalAddresses;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return [mergedCNContact copy];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|
|
|
|
NS_ASSUME_NONNULL_END
|
|
|
|