diff --git a/src/Contacts/Contact.h b/src/Contacts/Contact.h index 7f647cc6f..692f35526 100644 --- a/src/Contacts/Contact.h +++ b/src/Contacts/Contact.h @@ -1,6 +1,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** * * Contact represents relevant information related to a contact from the user's @@ -8,31 +10,39 @@ * */ -@interface Contact : NSObject - -@property (readonly, nonatomic) NSString *firstName; -@property (readonly, nonatomic) NSString *lastName; -@property (readonly, nonatomic) NSArray *parsedPhoneNumbers; -@property (readonly, nonatomic) NSArray *userTextPhoneNumbers; -@property (readonly, nonatomic) NSArray *emails; -@property (readonly, nonatomic) NSString *notes; +@class CNContact; +@class PhoneNumber; -- (NSString *)fullName; +@interface Contact : NSObject +@property (nullable, readonly, nonatomic) NSString *firstName; +@property (nullable, readonly, nonatomic) NSString *lastName; +@property (readonly, nonatomic) NSString *fullName; +@property (readonly, nonatomic) NSArray *parsedPhoneNumbers; +@property (readonly, nonatomic) NSArray *userTextPhoneNumbers; +@property (readonly, nonatomic) NSArray *emails; +@property (readonly, nonatomic) NSString *uniqueId; +#if TARGET_OS_IOS +@property (nullable, readonly, nonatomic) UIImage *image; +@property (readonly, nonatomic) ABRecordID recordID; +@property (nullable, nonatomic, readonly) CNContact *cnContact; +#endif // TARGET_OS_IOS - (BOOL)isSignalContact; - (NSArray *)textSecureIdentifiers; #if TARGET_OS_IOS -- (instancetype)initWithContactWithFirstName:(NSString *)firstName - andLastName:(NSString *)lastName - andUserTextPhoneNumbers:(NSArray *)phoneNumbers - andImage:(UIImage *)image +- (instancetype)initWithContactWithFirstName:(nullable NSString *)firstName + andLastName:(nullable NSString *)lastName + andUserTextPhoneNumbers:(NSArray *)phoneNumbers + andImage:(nullable UIImage *)image andContactID:(ABRecordID)record; -@property (readonly, nonatomic) UIImage *image; -@property (readonly, nonatomic) ABRecordID recordID; -#endif +- (instancetype)initWithContact:(CNContact *)contact; + +#endif // TARGET_OS_IOS @end + +NS_ASSUME_NONNULL_END diff --git a/src/Contacts/Contact.m b/src/Contacts/Contact.m index 9fb63944d..1c9a4977b 100644 --- a/src/Contacts/Contact.m +++ b/src/Contacts/Contact.m @@ -3,37 +3,92 @@ #import "SignalRecipient.h" #import "TSStorageManager.h" +@import Contacts; + +NS_ASSUME_NONNULL_BEGIN + @implementation Contact #if TARGET_OS_IOS -- (instancetype)initWithContactWithFirstName:(NSString *)firstName - andLastName:(NSString *)lastName +- (instancetype)initWithContactWithFirstName:(nullable NSString *)firstName + andLastName:(nullable NSString *)lastName andUserTextPhoneNumbers:(NSArray *)phoneNumbers - andImage:(UIImage *)image - andContactID:(ABRecordID)record { + andImage:(nullable UIImage *)image + andContactID:(ABRecordID)record +{ + self = [super init]; + if (!self) { + return self; + } + + _firstName = firstName; + _lastName = lastName; + _uniqueId = [self.class uniqueIdFromABRecordId:record]; + _recordID = record; + _userTextPhoneNumbers = phoneNumbers; + _parsedPhoneNumbers = [self.class parsedPhoneNumbersFromUserTextPhoneNumbers:phoneNumbers]; + _image = image; + // Not using emails for old AB style contacts. + _emails = [NSMutableArray new]; + + return self; +} + +- (instancetype)initWithContact:(CNContact *)contact +{ self = [super init]; - if (self) { - _firstName = firstName; - _lastName = lastName; - _userTextPhoneNumbers = phoneNumbers; - _recordID = record; - _image = image; - - NSMutableArray *parsedPhoneNumbers = [NSMutableArray array]; - - for (NSString *phoneNumberString in phoneNumbers) { - PhoneNumber *phoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumberString]; - if (phoneNumber) { - [parsedPhoneNumbers addObject:phoneNumber]; - } + if (!self) { + return self; + } + + _cnContact = contact; + _firstName = contact.givenName; + _lastName = contact.familyName; + _uniqueId = contact.identifier; + + NSMutableArray *phoneNumbers = [NSMutableArray new]; + for (CNLabeledValue *phoneNumberField in contact.phoneNumbers) { + if ([phoneNumberField.value isKindOfClass:[CNPhoneNumber class]]) { + CNPhoneNumber *phoneNumber = (CNPhoneNumber *)phoneNumberField.value; + [phoneNumbers addObject:phoneNumber.stringValue]; } + } + _userTextPhoneNumbers = [phoneNumbers copy]; + _parsedPhoneNumbers = [self.class parsedPhoneNumbersFromUserTextPhoneNumbers:phoneNumbers]; + + NSMutableArray *emailAddresses = [NSMutableArray new]; + for (CNLabeledValue *emailField in contact.emailAddresses) { + if ([emailField.value isKindOfClass:[NSString class]]) { + [emailAddresses addObject:(NSString *)emailField.value]; + } + } + _emails = [emailAddresses copy]; - _parsedPhoneNumbers = parsedPhoneNumbers.copy; + if (contact.thumbnailImageData) { + _image = [UIImage imageWithData:contact.thumbnailImageData]; } return self; } -#endif + ++ (NSString *)uniqueIdFromABRecordId:(ABRecordID)recordId +{ + return [NSString stringWithFormat:@"ABRecordId:%d", recordId]; +} + +#endif // TARGET_OS_IOS + ++ (NSArray *)parsedPhoneNumbersFromUserTextPhoneNumbers:(NSArray *)userTextPhoneNumbers +{ + NSMutableArray *parsedPhoneNumbers = [NSMutableArray new]; + for (NSString *phoneNumberString in userTextPhoneNumbers) { + PhoneNumber *phoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumberString]; + if (phoneNumber) { + [parsedPhoneNumbers addObject:phoneNumber]; + } + } + return [parsedPhoneNumbers copy]; +} - (NSString *)fullName { NSMutableString *fullName = [NSMutableString string]; @@ -70,3 +125,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/src/Messages/TSMessagesManager.m b/src/Messages/TSMessagesManager.m index 94b266deb..ca29ce688 100644 --- a/src/Messages/TSMessagesManager.m +++ b/src/Messages/TSMessagesManager.m @@ -529,7 +529,7 @@ NS_ASSUME_NONNULL_BEGIN break; } default: { - DDLogWarn(@"%@ Ignoring unknown group message type:%d", self.tag, dataMessage.group.type); + DDLogWarn(@"%@ Ignoring unknown group message type:%d", self.tag, (int)dataMessage.group.type); } }