diff --git a/SignalMessaging/attachments/SharingThreadPickerViewController.m b/SignalMessaging/attachments/SharingThreadPickerViewController.m index d82985f60..51daca53a 100644 --- a/SignalMessaging/attachments/SharingThreadPickerViewController.m +++ b/SignalMessaging/attachments/SharingThreadPickerViewController.m @@ -150,22 +150,30 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); if (self.attachment.isConvertibleToContactShare) { NSData *data = self.attachment.data; - OWSContact *_Nullable contact = [OWSContacts contactForVCardData:data]; - if (!contact) { - // This should never happen since we verify that the contact can be parsed when building the attachment. - OWSFail(@"%@ could not parse contact share.", self.logTag); - [self.shareViewDelegate shareViewWasCancelled]; + Contact *_Nullable contact = [Contact contactWithVCardData:data]; + OWSContact *_Nullable contactShareRecord = [OWSContacts contactForSystemContact:contact.cnContact]; + if (!contactShareRecord) { + DDLogError(@"%@ Could not convert system contact.", self.logTag); return; } - // TODO: Populate avatar image. BOOL isProfileAvatar = NO; - NSData *_Nullable avatarImageData = nil; - contact.isProfileAvatar = isProfileAvatar; + NSData *_Nullable avatarImageData = contact.imageData; + for (NSString *recipientId in contact.textSecureIdentifiers) { + if (avatarImageData) { + break; + } + avatarImageData = [self.contactsManager profileImageDataForPhoneIdentifier:recipientId]; + if (avatarImageData) { + isProfileAvatar = YES; + } + } + contactShareRecord.isProfileAvatar = isProfileAvatar; ContactShareViewModel *contactShare = - [[ContactShareViewModel alloc] initWithContactShareRecord:contact avatarImageData:avatarImageData]; + [[ContactShareViewModel alloc] initWithContactShareRecord:contactShareRecord + avatarImageData:avatarImageData]; ApproveContactShareViewController *approvalVC = [[ApproveContactShareViewController alloc] initWithContactShare:contactShare diff --git a/SignalServiceKit/src/Contacts/Contact.h b/SignalServiceKit/src/Contacts/Contact.h index aec8c014b..72b5a31f8 100644 --- a/SignalServiceKit/src/Contacts/Contact.h +++ b/SignalServiceKit/src/Contacts/Contact.h @@ -41,6 +41,7 @@ NS_ASSUME_NONNULL_BEGIN #if TARGET_OS_IOS - (instancetype)initWithSystemContact:(CNContact *)contact NS_AVAILABLE_IOS(9_0); ++ (nullable Contact *)contactWithVCardData:(NSData *)data; - (NSString *)nameForPhoneNumber:(NSString *)recipientId; diff --git a/SignalServiceKit/src/Contacts/Contact.m b/SignalServiceKit/src/Contacts/Contact.m index 84d82b9a8..49d4d6f33 100644 --- a/SignalServiceKit/src/Contacts/Contact.m +++ b/SignalServiceKit/src/Contacts/Contact.m @@ -106,11 +106,25 @@ NS_ASSUME_NONNULL_BEGIN if (contact.thumbnailImageData) { _imageData = [contact.thumbnailImageData copy]; + } else if (contact.imageData) { + // This only occurs when sharing a contact via the share extension + _imageData = [contact.imageData copy]; } return self; } ++ (nullable Contact *)contactWithVCardData:(NSData *)data +{ + CNContact *_Nullable cnContact = [self cnContactWithVCardData:data]; + + if (!cnContact) { + return nil; + } + + return [[self alloc] initWithSystemContact:cnContact]; +} + - (nullable UIImage *)image { if (_image) { @@ -290,6 +304,28 @@ NS_ASSUME_NONNULL_BEGIN return hash; } +#pragma mark - CNContactConverters + ++ (nullable CNContact *)cnContactWithVCardData:(NSData *)data +{ + OWSAssert(data); + + NSError *error; + NSArray *_Nullable contacts = [CNContactVCardSerialization contactsWithData:data error:&error]; + if (!contacts || error) { + OWSProdLogAndFail(@"%@ could not parse vcard: %@", self.logTag, error); + return nil; + } + if (contacts.count < 1) { + OWSProdLogAndFail(@"%@ empty vcard: %@", self.logTag, error); + return nil; + } + if (contacts.count > 1) { + OWSProdLogAndFail(@"%@ more than one contact in vcard: %@", self.logTag, error); + } + return contacts.firstObject; +} + - (CNContact *)buildCNContactMergedWithNewContact:(CNContact *)newCNContact { CNMutableContact *_Nullable mergedCNContact = [self.cnContact mutableCopy]; diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContact.m b/SignalServiceKit/src/Messages/Interactions/OWSContact.m index b4fa3815e..940f00508 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSContact.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSContact.m @@ -690,11 +690,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value) } contact.addresses = addresses; - // TODO: Avatar - - // @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *imageData; - // @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *thumbnailImageData; - [contact ensureDisplayName]; return contact; diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index 0ee30616a..81891c543 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -721,7 +721,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed utiType: kUTTypeVCard as String) { customFileName = "Contact.vcf" - if let contactShare = OWSContacts.contact(forVCardData: data) { + if Contact(vCardData: data) != nil { isConvertibleToContactShare = true } else { Logger.error("\(strongSelf.logTag) could not parse vcard.")