From 4b8a2fa8a31fab4d8f76de2031d9c6c964a572b5 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 27 Apr 2018 15:29:19 -0400 Subject: [PATCH] Sketch out "contact share" model. --- Pods | 2 +- .../ViewControllers/DebugUI/DebugUIMessages.m | 22 +- SignalMessaging/utils/ThreadUtil.h | 2 + SignalMessaging/utils/ThreadUtil.m | 5 +- .../Devices/OWSReadReceiptsForSenderMessage.m | 3 +- .../src/Devices/OWSRecordTranscriptJob.m | 3 +- .../OWSIncomingSentMessageTranscript.h | 2 + .../OWSIncomingSentMessageTranscript.m | 2 + .../DeviceSyncing/OWSOutgoingSyncMessage.m | 3 +- .../DeviceSyncing/OWSSyncContactsMessage.m | 3 +- .../DeviceSyncing/OWSSyncGroupsMessage.m | 3 +- .../OWSSyncGroupsRequestMessage.m | 3 +- .../Messages/Interactions/OWSContactShare.h | 99 +++++++ .../Messages/Interactions/OWSContactShare.m | 259 ++++++++++++++++++ ...DisappearingMessagesConfigurationMessage.m | 3 +- .../Interactions/OWSDynamicOutgoingMessage.m | 3 +- .../Interactions/OWSEndSessionMessage.m | 3 +- .../Messages/Interactions/TSErrorMessage.m | 3 +- .../Messages/Interactions/TSIncomingMessage.h | 3 +- .../Messages/Interactions/TSIncomingMessage.m | 4 +- .../src/Messages/Interactions/TSInfoMessage.h | 3 +- .../src/Messages/Interactions/TSInfoMessage.m | 3 +- .../src/Messages/Interactions/TSMessage.h | 5 +- .../src/Messages/Interactions/TSMessage.m | 3 + .../Messages/Interactions/TSOutgoingMessage.h | 3 +- .../Messages/Interactions/TSOutgoingMessage.m | 10 +- .../src/Messages/OWSMessageManager.m | 12 +- .../src/Messages/OWSMessageSender.m | 6 +- .../src/Messages/OWSOutgoingCallMessage.m | 3 +- .../src/Messages/OWSOutgoingNullMessage.m | 3 +- .../src/Messages/OWSProfileKeyMessage.m | 3 +- 31 files changed, 450 insertions(+), 34 deletions(-) create mode 100644 SignalServiceKit/src/Messages/Interactions/OWSContactShare.h create mode 100644 SignalServiceKit/src/Messages/Interactions/OWSContactShare.m diff --git a/Pods b/Pods index e67a14d7a..7f6203376 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit e67a14d7af8c1e54e2e68aa4488a7528eb99e896 +Subproject commit 7f6203376010de8838e21a2c22546f10fc24f712 diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m index 1d6b883ec..de9055458 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m @@ -2948,6 +2948,7 @@ NS_ASSUME_NONNULL_BEGIN [ThreadUtil sendMessageWithAttachment:attachment inThread:thread quotedReplyModel:nil + contactShare:nil messageSender:messageSender ignoreErrors:YES completion:nil]; @@ -3256,7 +3257,8 @@ NS_ASSUME_NONNULL_BEGIN messageBody:randomText attachmentIds:@[] expiresInSeconds:0 - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; [message markAsReadNowWithSendReadReceipt:NO transaction:transaction]; break; } @@ -3294,7 +3296,8 @@ NS_ASSUME_NONNULL_BEGIN pointer.uniqueId, ] expiresInSeconds:0 - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; [message markAsReadNowWithSendReadReceipt:NO transaction:transaction]; break; } @@ -3680,7 +3683,8 @@ NS_ASSUME_NONNULL_BEGIN : 0)expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; DDLogError(@"%@ resurrectNewOutgoingMessages2 timestamp: %llu.", self.logTag, message.timestamp); [messages addObject:message]; } @@ -3745,7 +3749,8 @@ NS_ASSUME_NONNULL_BEGIN messageBody:randomText attachmentIds:[NSMutableArray new] expiresInSeconds:0 - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; [message markAsReadNowWithSendReadReceipt:NO transaction:transaction]; } { @@ -3758,7 +3763,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; [message saveWithTransaction:transaction]; [message updateWithFakeMessageState:TSOutgoingMessageStateSent transaction:transaction]; [message updateWithSentRecipient:recipientId transaction:transaction]; @@ -3994,7 +4000,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:isVoiceMessage groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:nil]; if (attachmentId.length > 0 && filename.length > 0) { message.attachmentFilenameMap[attachmentId] = filename; @@ -4081,7 +4088,8 @@ NS_ASSUME_NONNULL_BEGIN messageBody:messageBody attachmentIds:attachmentIds expiresInSeconds:0 - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:nil]; [message markAsReadNowWithSendReadReceipt:NO transaction:transaction]; return message; } diff --git a/SignalMessaging/utils/ThreadUtil.h b/SignalMessaging/utils/ThreadUtil.h index 130fbf492..6f80963a9 100644 --- a/SignalMessaging/utils/ThreadUtil.h +++ b/SignalMessaging/utils/ThreadUtil.h @@ -44,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - +@class OWSContactShare; @class OWSQuotedReplyModel; @class TSOutgoingMessage; @@ -71,6 +72,7 @@ NS_ASSUME_NONNULL_BEGIN + (TSOutgoingMessage *)sendMessageWithAttachment:(SignalAttachment *)attachment inThread:(TSThread *)thread quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel + contactShare:(nullable OWSContactShare *)contactShare messageSender:(OWSMessageSender *)messageSender ignoreErrors:(BOOL)ignoreErrors completion:(void (^_Nullable)(NSError *_Nullable error))completion; diff --git a/SignalMessaging/utils/ThreadUtil.m b/SignalMessaging/utils/ThreadUtil.m index a5946c5a1..ac1a23c1f 100644 --- a/SignalMessaging/utils/ThreadUtil.m +++ b/SignalMessaging/utils/ThreadUtil.m @@ -107,6 +107,7 @@ NS_ASSUME_NONNULL_BEGIN return [self sendMessageWithAttachment:attachment inThread:thread quotedReplyModel:quotedReplyModel + contactShare:nil messageSender:messageSender ignoreErrors:NO completion:completion]; @@ -115,6 +116,7 @@ NS_ASSUME_NONNULL_BEGIN + (TSOutgoingMessage *)sendMessageWithAttachment:(SignalAttachment *)attachment inThread:(TSThread *)thread quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel + contactShare:(nullable OWSContactShare *)contactShare messageSender:(OWSMessageSender *)messageSender ignoreErrors:(BOOL)ignoreErrors completion:(void (^_Nullable)(NSError *_Nullable error))completion @@ -139,7 +141,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:[attachment isVoiceMessage] groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:[quotedReplyModel buildQuotedMessage]]; + quotedMessage:[quotedReplyModel buildQuotedMessage] + contactShare:contactShare]; [messageSender enqueueAttachment:attachment.dataSource contentType:attachment.mimeType diff --git a/SignalServiceKit/src/Devices/OWSReadReceiptsForSenderMessage.m b/SignalServiceKit/src/Devices/OWSReadReceiptsForSenderMessage.m index e2f0626c9..ae7a29a48 100644 --- a/SignalServiceKit/src/Devices/OWSReadReceiptsForSenderMessage.m +++ b/SignalServiceKit/src/Devices/OWSReadReceiptsForSenderMessage.m @@ -29,7 +29,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m b/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m index d64998bf0..4c811c674 100644 --- a/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m +++ b/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m @@ -95,7 +95,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:transcript.expirationStartedAt isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:transcript.quotedMessage]; + quotedMessage:transcript.quotedMessage + contactShare:transcript.contactShare]; // TODO: When written, desktop didn't yet support sending quotedMessages, so we didn't have a // good way to test the handling of transcripts with a quotedMessage. This assertion can be delete diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h index ca97207ae..462a33069 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h @@ -4,6 +4,7 @@ NS_ASSUME_NONNULL_BEGIN +@class OWSContactShare; @class OWSSignalServiceProtosAttachmentPointer; @class OWSSignalServiceProtosDataMessage; @class OWSSignalServiceProtosSyncMessageSent; @@ -35,6 +36,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) NSArray *attachmentPointerProtos; @property (nonatomic, readonly) TSThread *thread; @property (nonatomic, readonly) TSQuotedMessage *quotedMessage; +@property (nonatomic, readonly) OWSContactShare *contactShare; @end diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m index ce97eefd1..aae503022 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m @@ -3,6 +3,7 @@ // #import "OWSIncomingSentMessageTranscript.h" +#import "OWSContactShare.h" #import "OWSMessageManager.h" #import "OWSPrimaryStorage.h" #import "OWSSignalServiceProtos.pb.h" @@ -46,6 +47,7 @@ NS_ASSUME_NONNULL_BEGIN _quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread relay:relay transaction:transaction]; + _contactShare = [OWSContactShare contactShareMessageForDataMessage:_dataMessage transaction:transaction]; return self; } diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m index 655e7c97d..af1e6efea 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m @@ -22,7 +22,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncContactsMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncContactsMessage.m index 032f29786..217acbb69 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncContactsMessage.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncContactsMessage.m @@ -38,7 +38,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m index 1b049cb45..21a9f9a0f 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m @@ -24,7 +24,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; } - (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsRequestMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsRequestMessage.m index b03cff94a..2c35a02e2 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsRequestMessage.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsRequestMessage.m @@ -28,7 +28,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContactShare.h b/SignalServiceKit/src/Messages/Interactions/OWSContactShare.h new file mode 100644 index 000000000..2090a0c37 --- /dev/null +++ b/SignalServiceKit/src/Messages/Interactions/OWSContactShare.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class OWSSignalServiceProtosDataMessage; +@class TSAttachment; +@class YapDatabaseReadWriteTransaction; + +typedef NS_ENUM(NSUInteger, OWSContactSharePhoneType) { + OWSContactSharePhoneType_Home = 1, + OWSContactSharePhoneType_Mobile, + OWSContactSharePhoneType_Work, + OWSContactSharePhoneType_Custom, +}; + +@interface OWSContactSharePhoneNumber : MTLModel + +@property (nonatomic, readonly) OWSContactSharePhoneType phoneType; +// Applies in the OWSContactSharePhoneType_Custom case. +@property (nonatomic, readonly, nullable) NSString *label; + +@property (nonatomic, readonly) NSString *phoneNumber; + +@end + +#pragma mark - + +typedef NS_ENUM(NSUInteger, OWSContactShareEmailType) { + OWSContactShareEmailType_Home = 1, + OWSContactShareEmailType_Mobile, + OWSContactShareEmailType_Work, + OWSContactShareEmailType_Custom, +}; + +@interface OWSContactShareEmail : MTLModel + +@property (nonatomic, readonly) OWSContactShareEmailType emailType; +// Applies in the OWSContactShareEmailType_Custom case. +@property (nonatomic, readonly, nullable) NSString *label; + +@property (nonatomic, readonly) NSString *email; + +@end + +#pragma mark - + +typedef NS_ENUM(NSUInteger, OWSContactShareAddressType) { + OWSContactShareAddressType_Home = 1, + OWSContactShareAddressType_Work, + OWSContactShareAddressType_Custom, +}; + +@interface OWSContactShareAddress : MTLModel + +@property (nonatomic, readonly) OWSContactShareAddressType addressType; +// Applies in the OWSContactShareAddressType_Custom case. +@property (nonatomic, readonly, nullable) NSString *label; + +@property (nonatomic, readonly, nullable) NSString *street; +@property (nonatomic, readonly, nullable) NSString *pobox; +@property (nonatomic, readonly, nullable) NSString *neighborhood; +@property (nonatomic, readonly, nullable) NSString *city; +@property (nonatomic, readonly, nullable) NSString *region; +@property (nonatomic, readonly, nullable) NSString *postcode; +@property (nonatomic, readonly, nullable) NSString *country; + +@end + +#pragma mark - + +@interface OWSContactShare : MTLModel + +@property (nonatomic, readonly, nullable) NSString *givenName; +@property (nonatomic, readonly, nullable) NSString *familyName; +@property (nonatomic, readonly, nullable) NSString *nameSuffix; +@property (nonatomic, readonly, nullable) NSString *namePrefix; +@property (nonatomic, readonly, nullable) NSString *middleName; + +@property (nonatomic, readonly, nullable) NSArray *phoneNumbers; +@property (nonatomic, readonly, nullable) NSArray *emails; +@property (nonatomic, readonly, nullable) NSArray *addresses; + +// TODO: This is provisional. +@property (nonatomic, readonly, nullable) TSAttachment *avatar; +// "Profile" avatars should _not_ be saved to device contacts. +@property (nonatomic, readonly) BOOL isProfileAvatar; + +- (instancetype)init NS_UNAVAILABLE; + ++ (OWSContactShare *_Nullable)contactShareMessageForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage + transaction:(YapDatabaseReadWriteTransaction *)transaction; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContactShare.m b/SignalServiceKit/src/Messages/Interactions/OWSContactShare.m new file mode 100644 index 000000000..25072ed3c --- /dev/null +++ b/SignalServiceKit/src/Messages/Interactions/OWSContactShare.m @@ -0,0 +1,259 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSContactShare.h" +#import "OWSSignalServiceProtos.pb.h" +#import "TSAttachment.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OWSContactSharePhoneNumber () + +@property (nonatomic) OWSContactSharePhoneType phoneType; +@property (nonatomic, nullable) NSString *label; + +@property (nonatomic) NSString *phoneNumber; + +@end + +#pragma mark - + +@implementation OWSContactSharePhoneNumber + +@end + +#pragma mark - + +@interface OWSContactShareEmail () + +@property (nonatomic) OWSContactShareEmailType emailType; +@property (nonatomic, nullable) NSString *label; + +@property (nonatomic) NSString *email; + +@end + +#pragma mark - + +@implementation OWSContactShareEmail + +@end + +#pragma mark - + +@interface OWSContactShareAddress () + +@property (nonatomic) OWSContactShareAddressType addressType; +@property (nonatomic, nullable) NSString *label; + +@property (nonatomic, nullable) NSString *street; +@property (nonatomic, nullable) NSString *pobox; +@property (nonatomic, nullable) NSString *neighborhood; +@property (nonatomic, nullable) NSString *city; +@property (nonatomic, nullable) NSString *region; +@property (nonatomic, nullable) NSString *postcode; +@property (nonatomic, nullable) NSString *country; + +@end + +#pragma mark - + +@implementation OWSContactShareAddress + +@end + +#pragma mark - + +@interface OWSContactShare () + +@property (nonatomic, nullable) NSString *givenName; +@property (nonatomic, nullable) NSString *familyName; +@property (nonatomic, nullable) NSString *nameSuffix; +@property (nonatomic, nullable) NSString *namePrefix; +@property (nonatomic, nullable) NSString *middleName; + +@property (nonatomic, nullable) NSArray *phoneNumbers; +@property (nonatomic, nullable) NSArray *emails; +@property (nonatomic, nullable) NSArray *addresses; + +@property (nonatomic, nullable) TSAttachment *avatar; +@property (nonatomic) BOOL isProfileAvatar; + +@end + +#pragma mark - + +@implementation OWSContactShare + ++ (OWSContactShare *_Nullable)contactShareMessageForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage + transaction:(YapDatabaseReadWriteTransaction *)transaction +{ + OWSAssert(dataMessage); + + if (dataMessage.contact.count < 1) { + return nil; + } + OWSAssert(dataMessage.contact.count == 1); + OWSSignalServiceProtosDataMessageContact *contactProto = dataMessage.contact.firstObject; + + OWSContactShare *contactShare = [OWSContactShare new]; + if (contactProto.hasName) { + OWSSignalServiceProtosDataMessageContactName *nameProto = contactProto.name; + + if (nameProto.hasGivenName) { + contactShare.givenName = nameProto.givenName; + } + if (nameProto.hasFamilyName) { + contactShare.familyName = nameProto.familyName; + } + if (nameProto.hasPrefix) { + contactShare.namePrefix = nameProto.prefix; + } + if (nameProto.hasSuffix) { + contactShare.nameSuffix = nameProto.suffix; + } + if (nameProto.hasMiddleName) { + contactShare.middleName = nameProto.middleName; + } + } + + NSMutableArray *phoneNumbers = [NSMutableArray new]; + for (OWSSignalServiceProtosDataMessageContactPhone *phoneNumberProto in contactProto.number) { + OWSContactSharePhoneNumber *_Nullable phoneNumber = [self phoneNumberForProto:phoneNumberProto]; + if (phoneNumber) { + [phoneNumbers addObject:phoneNumber]; + } + } + contactShare.phoneNumbers = [phoneNumbers copy]; + + NSMutableArray *emails = [NSMutableArray new]; + for (OWSSignalServiceProtosDataMessageContactEmail *emailProto in contactProto.email) { + OWSContactShareEmail *_Nullable email = [self emailForProto:emailProto]; + if (email) { + [emails addObject:email]; + } + } + contactShare.emails = [emails copy]; + + NSMutableArray *addresses = [NSMutableArray new]; + for (OWSSignalServiceProtosDataMessageContactPostalAddress *addressProto in contactProto.address) { + OWSContactShareAddress *_Nullable address = [self addressForProto:addressProto]; + if (address) { + [addresses addObject:address]; + } + } + contactShare.addresses = [addresses copy]; + + return contactShare; +} + ++ (nullable OWSContactSharePhoneNumber *)phoneNumberForProto: + (OWSSignalServiceProtosDataMessageContactPhone *)phoneNumberProto +{ + OWSContactSharePhoneNumber *result = [OWSContactSharePhoneNumber new]; + result.phoneType = OWSContactSharePhoneType_Custom; + if (phoneNumberProto.hasType) { + switch (phoneNumberProto.type) { + case OWSSignalServiceProtosDataMessageContactPhoneTypeHome: + result.phoneType = OWSContactSharePhoneType_Home; + break; + case OWSSignalServiceProtosDataMessageContactPhoneTypeMobile: + result.phoneType = OWSContactSharePhoneType_Mobile; + break; + case OWSSignalServiceProtosDataMessageContactPhoneTypeWork: + result.phoneType = OWSContactSharePhoneType_Work; + break; + default: + break; + } + } + if (phoneNumberProto.hasLabel) { + result.label = phoneNumberProto.label; + } + if (phoneNumberProto.hasValue) { + result.phoneNumber = phoneNumberProto.value; + } else { + return nil; + } + return result; +} + ++ (nullable OWSContactShareEmail *)emailForProto:(OWSSignalServiceProtosDataMessageContactEmail *)emailProto +{ + OWSContactShareEmail *result = [OWSContactShareEmail new]; + result.emailType = OWSContactShareEmailType_Custom; + if (emailProto.hasType) { + switch (emailProto.type) { + case OWSSignalServiceProtosDataMessageContactEmailTypeHome: + result.emailType = OWSContactShareEmailType_Home; + break; + case OWSSignalServiceProtosDataMessageContactEmailTypeMobile: + result.emailType = OWSContactShareEmailType_Mobile; + break; + case OWSSignalServiceProtosDataMessageContactEmailTypeWork: + result.emailType = OWSContactShareEmailType_Work; + break; + default: + break; + } + } + if (emailProto.hasLabel) { + result.label = emailProto.label; + } + if (emailProto.hasValue) { + result.email = emailProto.value; + } else { + return nil; + } + return result; +} + ++ (nullable OWSContactShareAddress *)addressForProto: + (OWSSignalServiceProtosDataMessageContactPostalAddress *)addressProto +{ + OWSContactShareAddress *result = [OWSContactShareAddress new]; + result.addressType = OWSContactShareAddressType_Custom; + if (addressProto.hasType) { + switch (addressProto.type) { + case OWSSignalServiceProtosDataMessageContactPostalAddressTypeHome: + result.addressType = OWSContactShareAddressType_Home; + break; + case OWSSignalServiceProtosDataMessageContactPostalAddressTypeWork: + result.addressType = OWSContactShareAddressType_Work; + break; + default: + break; + } + } + if (addressProto.hasLabel) { + result.label = addressProto.label; + } + if (addressProto.hasStreet) { + result.street = addressProto.street; + } + if (addressProto.hasPobox) { + result.pobox = addressProto.pobox; + } + if (addressProto.hasNeighborhood) { + result.neighborhood = addressProto.neighborhood; + } + if (addressProto.hasCity) { + result.city = addressProto.city; + } + if (addressProto.hasRegion) { + result.region = addressProto.region; + } + if (addressProto.hasPostcode) { + result.postcode = addressProto.postcode; + } + if (addressProto.hasCountry) { + result.country = addressProto.country; + } + return result; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Messages/Interactions/OWSDisappearingMessagesConfigurationMessage.m b/SignalServiceKit/src/Messages/Interactions/OWSDisappearingMessagesConfigurationMessage.m index 1d8933ce1..998cef14b 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSDisappearingMessagesConfigurationMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSDisappearingMessagesConfigurationMessage.m @@ -34,7 +34,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Messages/Interactions/OWSDynamicOutgoingMessage.m b/SignalServiceKit/src/Messages/Interactions/OWSDynamicOutgoingMessage.m index 4505d0998..a2e727738 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSDynamicOutgoingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSDynamicOutgoingMessage.m @@ -35,7 +35,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (self) { _block = block; diff --git a/SignalServiceKit/src/Messages/Interactions/OWSEndSessionMessage.m b/SignalServiceKit/src/Messages/Interactions/OWSEndSessionMessage.m index 147d0b38c..1b76988ee 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSEndSessionMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSEndSessionMessage.m @@ -19,7 +19,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; } - (BOOL)shouldBeSaved diff --git a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m index d2b4d3915..0a1dccd6c 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m @@ -65,7 +65,8 @@ NSUInteger TSErrorMessageSchemaVersion = 1; attachmentIds:@[] expiresInSeconds:0 expireStartedAt:0 - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; diff --git a/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.h b/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.h index 3e5f49fdc..51811193e 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.h @@ -49,7 +49,8 @@ NS_ASSUME_NONNULL_BEGIN messageBody:(nullable NSString *)body attachmentIds:(NSArray *)attachmentIds expiresInSeconds:(uint32_t)expiresInSeconds - quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER; + quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare NS_DESIGNATED_INITIALIZER; - (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; diff --git a/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.m b/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.m index 97944bc4f..c4e4c3835 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSIncomingMessage.m @@ -44,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN attachmentIds:(NSArray *)attachmentIds expiresInSeconds:(uint32_t)expiresInSeconds quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare { self = [super initMessageWithTimestamp:timestamp inThread:thread @@ -51,7 +52,8 @@ NS_ASSUME_NONNULL_BEGIN attachmentIds:attachmentIds expiresInSeconds:expiresInSeconds expireStartedAt:0 - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:contactShare]; if (!self) { return self; diff --git a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.h b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.h index c6378b477..cd190ed93 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.h @@ -34,7 +34,8 @@ typedef NS_ENUM(NSInteger, TSInfoMessageType) { attachmentIds:(NSArray *)attachmentIds expiresInSeconds:(uint32_t)expiresInSeconds expireStartedAt:(uint64_t)expireStartedAt - quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE; + quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; diff --git a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m index 5e19dd446..4ee76bb4d 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m @@ -52,7 +52,8 @@ NSUInteger TSInfoMessageSchemaVersion = 1; attachmentIds:@[] expiresInSeconds:0 expireStartedAt:0 - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.h b/SignalServiceKit/src/Messages/Interactions/TSMessage.h index 66c359804..f08dd66a3 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.h @@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN * Abstract message class. */ +@class OWSContactShare; @class TSAttachment; @class TSAttachmentStream; @class TSQuotedMessage; @@ -24,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) uint64_t expiresAt; @property (nonatomic, readonly) BOOL isExpiringMessage; @property (nonatomic, readonly, nullable) TSQuotedMessage *quotedMessage; +@property (nonatomic, readonly, nullable) OWSContactShare *contactShare; - (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE; @@ -33,7 +35,8 @@ NS_ASSUME_NONNULL_BEGIN attachmentIds:(NSArray *)attachmentIds expiresInSeconds:(uint32_t)expiresInSeconds expireStartedAt:(uint64_t)expireStartedAt - quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER; + quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.m b/SignalServiceKit/src/Messages/Interactions/TSMessage.m index 071aada16..98ac385cd 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.m @@ -7,6 +7,7 @@ #import "MIMETypeUtil.h" #import "NSDate+OWS.h" #import "NSString+SSK.h" +#import "OWSContactShare.h" #import "TSAttachment.h" #import "TSAttachmentStream.h" #import "TSQuotedMessage.h" @@ -65,6 +66,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4; expiresInSeconds:(uint32_t)expiresInSeconds expireStartedAt:(uint64_t)expireStartedAt quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare { self = [super initInteractionWithTimestamp:timestamp inThread:thread]; @@ -81,6 +83,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4; [self updateExpiresAt]; _receivedAtTimestamp = [NSDate ows_millisecondTimeStamp]; _quotedMessage = quotedMessage; + _contactShare = contactShare; return self; } diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h index 63a41ce03..cdcf8c852 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h @@ -84,7 +84,8 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) { expireStartedAt:(uint64_t)expireStartedAt isVoiceMessage:(BOOL)isVoiceMessage groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage - quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER; + quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare NS_DESIGNATED_INITIALIZER; - (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m index b77edc8d4..1e5b9c7a5 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m @@ -242,7 +242,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:nil]; } + (instancetype)outgoingMessageInThread:(nullable TSThread *)thread @@ -256,7 +257,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:groupMetaMessage - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; } - (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp @@ -268,6 +270,7 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt isVoiceMessage:(BOOL)isVoiceMessage groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage quotedMessage:(nullable TSQuotedMessage *)quotedMessage + contactShare:(nullable OWSContactShare *)contactShare { self = [super initMessageWithTimestamp:timestamp inThread:thread @@ -275,7 +278,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt attachmentIds:attachmentIds expiresInSeconds:expiresInSeconds expireStartedAt:expireStartedAt - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:contactShare]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 10934acae..0804cc250 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -14,6 +14,7 @@ #import "OWSAttachmentsProcessor.h" #import "OWSBlockingManager.h" #import "OWSCallMessageHandler.h" +#import "OWSContactShare.h" #import "OWSDevice.h" #import "OWSDisappearingConfigurationUpdateInfoMessage.h" #import "OWSDisappearingMessagesConfiguration.h" @@ -996,6 +997,9 @@ NS_ASSUME_NONNULL_BEGIN relay:envelope.relay transaction:transaction]; + OWSContactShare *_Nullable contactShare = + [OWSContactShare contactShareMessageForDataMessage:dataMessage transaction:transaction]; + DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu", self.logTag, envelopeAddress(envelope), @@ -1010,7 +1014,8 @@ NS_ASSUME_NONNULL_BEGIN messageBody:body attachmentIds:attachmentIds expiresInSeconds:dataMessage.expireTimer - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:contactShare]; [self finalizeIncomingMessage:incomingMessage thread:oldGroupThread @@ -1044,6 +1049,8 @@ NS_ASSUME_NONNULL_BEGIN thread:thread relay:envelope.relay transaction:transaction]; + OWSContactShare *_Nullable contactShare = + [OWSContactShare contactShareMessageForDataMessage:dataMessage transaction:transaction]; TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp @@ -1053,7 +1060,8 @@ NS_ASSUME_NONNULL_BEGIN messageBody:body attachmentIds:attachmentIds expiresInSeconds:dataMessage.expireTimer - quotedMessage:quotedMessage]; + quotedMessage:quotedMessage + contactShare:contactShare]; [self finalizeIncomingMessage:incomingMessage thread:thread diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index 5a73aa4c4..5d57b862b 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -1154,6 +1154,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } // We want the incoming message to appear after the outgoing message. + // + // TODO: We need to be careful to duplicate the attachments for + // quoted message and contact share. TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:(outgoingMessage.timestamp + 1) inThread:cThread @@ -1162,7 +1165,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; messageBody:outgoingMessage.body attachmentIds:attachmentIds expiresInSeconds:outgoingMessage.expiresInSeconds - quotedMessage:outgoingMessage.quotedMessage]; + quotedMessage:outgoingMessage.quotedMessage + contactShare:outgoingMessage.contactShare]; [incomingMessage saveWithTransaction:transaction]; }]; } diff --git a/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m b/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m index 44ac760dc..9867be0df 100644 --- a/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m +++ b/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m @@ -30,7 +30,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m b/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m index b49c106c6..05807fb69 100644 --- a/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m +++ b/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m @@ -32,7 +32,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; if (!self) { return self; } diff --git a/SignalServiceKit/src/Messages/OWSProfileKeyMessage.m b/SignalServiceKit/src/Messages/OWSProfileKeyMessage.m index be32e4066..43e619666 100644 --- a/SignalServiceKit/src/Messages/OWSProfileKeyMessage.m +++ b/SignalServiceKit/src/Messages/OWSProfileKeyMessage.m @@ -22,7 +22,8 @@ NS_ASSUME_NONNULL_BEGIN expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMessageUnspecified - quotedMessage:nil]; + quotedMessage:nil + contactShare:nil]; } - (BOOL)shouldBeSaved