Merge branch 'charlesmchen/contactShareModel'

This commit is contained in:
Matthew Chen 2018-05-01 16:10:13 -04:00
commit 11591416e6
36 changed files with 1829 additions and 128 deletions

2
Pods

@ -1 +1 @@
Subproject commit e67a14d7af8c1e54e2e68aa4488a7528eb99e896
Subproject commit 086242800e27b3ee431ad23e9f29f3358e813059

View file

@ -13,6 +13,7 @@
#import <SignalServiceKit/MIMETypeUtil.h>
#import <SignalServiceKit/NSDate+OWS.h>
#import <SignalServiceKit/OWSBatchMessageProcessor.h>
#import <SignalServiceKit/OWSContact+Private.h>
#import <SignalServiceKit/OWSDisappearingConfigurationUpdateInfoMessage.h>
#import <SignalServiceKit/OWSDisappearingMessagesConfiguration.h>
#import <SignalServiceKit/OWSMessageUtils.h>
@ -43,36 +44,11 @@ NS_ASSUME_NONNULL_BEGIN
return @"Messages";
}
- (nullable OWSTableSection *)sectionForThread:(nullable TSThread *)thread
- (NSArray<OWSTableItem *> *)itemsForActions:(NSArray<DebugUIMessagesAction *> *)actions
{
OWSAssert(thread);
NSMutableArray<OWSTableItem *> *items = [NSMutableArray new];
[items addObject:[OWSTableItem itemWithTitle:@"Delete all messages in thread"
actionBlock:^{
[DebugUIMessages deleteAllMessagesInThread:thread];
}]];
for (DebugUIMessagesAction *action in @[
[DebugUIMessages sendMessageVariationsAction:thread],
// Send Media
[DebugUIMessages sendAllMediaAction:thread],
[DebugUIMessages sendRandomMediaAction:thread],
// Fake Media
[DebugUIMessages fakeAllMediaAction:thread],
[DebugUIMessages fakeRandomMediaAction:thread],
// Fake Text
[DebugUIMessages fakeAllTextAction:thread],
[DebugUIMessages fakeRandomTextAction:thread],
// Sequences
[DebugUIMessages allFakeSequencesAction:thread],
// Quoted Replies
[DebugUIMessages allQuotedReplyAction:thread],
// Exemplary
[DebugUIMessages allFakeAction:thread],
[DebugUIMessages allFakeBackDatedAction:thread],
]) {
for (DebugUIMessagesAction *action in actions) {
[items addObject:[OWSTableItem itemWithTitle:action.label
actionBlock:^{
// For "all in group" actions, do each subaction in the group
@ -89,6 +65,41 @@ NS_ASSUME_NONNULL_BEGIN
}]];
}
return items;
}
- (nullable OWSTableSection *)sectionForThread:(nullable TSThread *)thread
{
OWSAssert(thread);
NSMutableArray<OWSTableItem *> *items = [NSMutableArray new];
[items addObject:[OWSTableItem itemWithTitle:@"Delete all messages in thread"
actionBlock:^{
[DebugUIMessages deleteAllMessagesInThread:thread];
}]];
[items addObjectsFromArray:[self itemsForActions:@[
[DebugUIMessages sendMessageVariationsAction:thread],
// Send Media
[DebugUIMessages sendAllMediaAction:thread],
[DebugUIMessages sendRandomMediaAction:thread],
// Fake Media
[DebugUIMessages fakeAllMediaAction:thread],
[DebugUIMessages fakeRandomMediaAction:thread],
// Fake Text
[DebugUIMessages fakeAllTextAction:thread],
[DebugUIMessages fakeRandomTextAction:thread],
// Sequences
[DebugUIMessages allFakeSequencesAction:thread],
// Quoted Replies
[DebugUIMessages allQuotedReplyAction:thread],
// Exemplary
[DebugUIMessages allFakeAction:thread],
[DebugUIMessages allFakeBackDatedAction:thread],
[DebugUIMessages allShareContactAction:thread],
]]];
[items addObjectsFromArray:@[
#pragma mark - Actions
@ -809,6 +820,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:YES
isRead:NO
quotedMessage:nil
contactShare:nil
transaction:transaction];
// This is a hack to "back-date" the message.
@ -1741,6 +1753,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:NO
isRead:NO
quotedMessage:nil
contactShare:nil
transaction:transaction];
}];
}
@ -1788,6 +1801,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:isDelivered
isRead:isRead
quotedMessage:nil
contactShare:nil
transaction:transaction];
}];
}
@ -1961,6 +1975,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:quotedMessageIsDelivered
isRead:quotedMessageIsRead
quotedMessage:nil
contactShare:nil
transaction:transaction];
OWSAssert(messageToQuote);
quotedMessage = [[OWSQuotedReplyModel quotedReplyForMessage:messageToQuote transaction:transaction]
@ -1985,6 +2000,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:replyIsDelivered
isRead:replyIsRead
quotedMessage:quotedMessage
contactShare:nil
transaction:transaction];
}
}
@ -2642,6 +2658,7 @@ NS_ASSUME_NONNULL_BEGIN
[actions addObjectsFromArray:[self allFakeSequenceActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allFakeQuotedReplyActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allFakeBackDatedActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allShareContactActions:thread includeLabels:includeLabels]];
return actions;
}
@ -2832,6 +2849,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:NO
isRead:NO
quotedMessage:nil
contactShare:nil
transaction:transaction];
[message setReceivedAtTimestamp:(uint64_t)((int64_t)[NSDate ows_millisecondTimeStamp] + dateOffset)];
[message saveWithTransaction:transaction];
@ -2882,6 +2900,144 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
typedef OWSContact * (^OWSContactBlock)(void);
+ (DebugUIMessagesAction *)fakeShareContactMessageAction:(TSThread *)thread
label:(NSString *)label
contactBlock:(OWSContactBlock)contactBlock
{
OWSAssert(thread);
return [DebugUIMessagesSingleAction
actionWithLabel:[NSString stringWithFormat:@"Fake Contact Share (%@)", label]
unstaggeredActionBlock:^(NSUInteger index, YapDatabaseReadWriteTransaction *transaction) {
OWSContact *contact = contactBlock();
TSOutgoingMessage *message = [self createFakeOutgoingMessage:thread
messageBody:nil
fakeAssetLoader:nil
messageState:TSOutgoingMessageStateSent
isDelivered:NO
isRead:NO
quotedMessage:nil
contactShare:contact
transaction:transaction];
[message saveWithTransaction:transaction];
}];
}
+ (NSArray<DebugUIMessagesAction *> *)allShareContactActions:(TSThread *)thread includeLabels:(BOOL)includeLabels
{
OWSAssert(thread);
NSMutableArray<DebugUIMessagesAction *> *actions = [NSMutableArray new];
if (includeLabels) {
[actions addObject:[self fakeOutgoingTextMessageAction:thread
messageState:TSOutgoingMessageStateSent
text:@"⚠️ Share Contact ⚠️"]];
}
[actions addObject:[self fakeShareContactMessageAction:thread
label:@"Name & Number"
contactBlock:^{
OWSContact *contact = [OWSContact new];
contact.givenName = @"Alice";
OWSContactPhoneNumber *phoneNumber = [OWSContactPhoneNumber new];
phoneNumber.phoneType = OWSContactPhoneType_Home;
phoneNumber.phoneNumber = @"+13213214321";
contact.phoneNumbers = @[
phoneNumber,
];
return contact;
}]];
[actions addObject:[self fakeShareContactMessageAction:thread
label:@"Name & Email"
contactBlock:^{
OWSContact *contact = [OWSContact new];
contact.givenName = @"Bob";
OWSContactEmail *email = [OWSContactEmail new];
email.emailType = OWSContactEmailType_Home;
email.email = @"a@b.com";
contact.emails = @[
email,
];
return contact;
}]];
[actions addObject:[self fakeShareContactMessageAction:thread
label:@"Complicated"
contactBlock:^{
OWSContact *contact = [OWSContact new];
contact.givenName = @"Alice";
contact.familyName = @"Carol";
contact.middleName = @"Bob";
contact.namePrefix = @"Ms.";
contact.nameSuffix = @"Esq.";
contact.organizationName = @"Falafel Hut";
contact.displayName = @"Ms. Alice Bob Carol Esq.";
OWSContactPhoneNumber *phoneNumber1 = [OWSContactPhoneNumber new];
phoneNumber1.phoneType = OWSContactPhoneType_Home;
phoneNumber1.phoneNumber = @"+13213214321";
OWSContactPhoneNumber *phoneNumber2 = [OWSContactPhoneNumber new];
phoneNumber2.phoneType = OWSContactPhoneType_Custom;
phoneNumber2.label = @"Carphone";
phoneNumber2.phoneNumber = @"+13332221111";
contact.phoneNumbers = @[
phoneNumber1,
phoneNumber2,
];
OWSContactEmail *email1 = [OWSContactEmail new];
email1.emailType = OWSContactEmailType_Home;
email1.email = @"a@b.com";
OWSContactEmail *email2 = [OWSContactEmail new];
email2.emailType = OWSContactEmailType_Custom;
email2.label = @"customer support";
email2.email = @"a@b.com";
contact.emails = @[
email1,
email2,
];
OWSContactAddress *address1 = [OWSContactAddress new];
address1.addressType = OWSContactAddressType_Home;
address1.street = @"123 home st.";
address1.neighborhood = @"round the bend.";
address1.city = @"homeville";
address1.region = @"HO";
address1.postcode = @"12345";
address1.country = @"USA";
OWSContactAddress *address2 = [OWSContactAddress new];
address2.addressType = OWSContactAddressType_Custom;
address2.label = @"Otra casa";
address2.pobox = @"caja 123";
address2.street = @"123 casa calle";
address2.city = @"barrio norte";
address2.region = @"AB";
address2.postcode = @"53421";
address2.country = @"MX";
contact.addresses = @[
address1,
address2,
];
// TODO: Avatar
return contact;
}]];
return actions;
}
+ (DebugUIMessagesAction *)allShareContactAction:(TSThread *)thread
{
OWSAssert(thread);
return [DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Fake Share Contact"
subactions:[self allShareContactActions:thread includeLabels:YES]];
}
#pragma mark -
+ (NSString *)randomOversizeText
{
NSMutableString *message = [NSMutableString new];
@ -2948,6 +3104,7 @@ NS_ASSUME_NONNULL_BEGIN
[ThreadUtil sendMessageWithAttachment:attachment
inThread:thread
quotedReplyModel:nil
contactShare:nil
messageSender:messageSender
ignoreErrors:YES
completion:nil];
@ -3256,7 +3413,8 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:randomText
attachmentIds:@[]
expiresInSeconds:0
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
[message markAsReadNowWithSendReadReceipt:NO transaction:transaction];
break;
}
@ -3268,6 +3426,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:NO
isRead:NO
quotedMessage:nil
contactShare:nil
transaction:transaction];
break;
}
@ -3294,7 +3453,8 @@ NS_ASSUME_NONNULL_BEGIN
pointer.uniqueId,
]
expiresInSeconds:0
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
[message markAsReadNowWithSendReadReceipt:NO transaction:transaction];
break;
}
@ -3320,6 +3480,7 @@ NS_ASSUME_NONNULL_BEGIN
isRead:NO
isVoiceMessage:NO
quotedMessage:nil
contactShare:nil
transaction:transaction];
break;
}
@ -3680,7 +3841,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 +3907,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 +3921,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];
@ -3937,6 +4101,7 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:(BOOL)isDelivered
isRead:(BOOL)isRead
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(thread);
@ -3962,6 +4127,7 @@ NS_ASSUME_NONNULL_BEGIN
isRead:isRead
isVoiceMessage:attachment.isVoiceMessage
quotedMessage:quotedMessage
contactShare:contactShare
transaction:transaction];
}
@ -3974,11 +4140,12 @@ NS_ASSUME_NONNULL_BEGIN
isRead:(BOOL)isRead
isVoiceMessage:(BOOL)isVoiceMessage
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(thread);
OWSAssert(transaction);
OWSAssert(messageBody.length > 0 || attachmentId.length > 0);
OWSAssert(messageBody.length > 0 || attachmentId.length > 0 || contactShare);
NSMutableArray<NSString *> *attachmentIds = [NSMutableArray new];
if (attachmentId) {
@ -3994,7 +4161,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:isVoiceMessage
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:quotedMessage];
quotedMessage:quotedMessage
contactShare:contactShare];
if (attachmentId.length > 0 && filename.length > 0) {
message.attachmentFilenameMap[attachmentId] = filename;
@ -4081,7 +4249,8 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:messageBody
attachmentIds:attachmentIds
expiresInSeconds:0
quotedMessage:quotedMessage];
quotedMessage:quotedMessage
contactShare:nil];
[message markAsReadNowWithSendReadReceipt:NO transaction:transaction];
return message;
}

View file

@ -44,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
@class OWSContact;
@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 OWSContact *)contactShare
messageSender:(OWSMessageSender *)messageSender
ignoreErrors:(BOOL)ignoreErrors
completion:(void (^_Nullable)(NSError *_Nullable error))completion;

View file

@ -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 OWSContact *)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

View file

@ -107,11 +107,12 @@ message DataMessage {
message Contact {
message Name {
optional string givenName = 1;
optional string familyName = 2;
optional string prefix = 3;
optional string suffix = 4;
optional string middleName = 5;
optional string givenName = 1;
optional string familyName = 2;
optional string prefix = 3;
optional string suffix = 4;
optional string middleName = 5;
optional string displayName = 6;
}
message Phone {
@ -158,11 +159,17 @@ message DataMessage {
optional string country = 9;
}
optional Name name = 1;
repeated Phone number = 3;
repeated Email email = 4;
repeated PostalAddress address = 5;
optional AttachmentPointer avatar = 6;
message Avatar {
optional AttachmentPointer avatar = 1;
optional bool isProfile = 2;
}
optional Name name = 1;
repeated Phone number = 3;
repeated Email email = 4;
repeated PostalAddress address = 5;
optional Avatar avatar = 6;
optional string organization = 7;
}
optional string body = 1;

View file

@ -29,7 +29,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;
}

View file

@ -95,7 +95,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:transcript.expirationStartedAt
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:transcript.quotedMessage];
quotedMessage:transcript.quotedMessage
contactShare:transcript.contact];
// 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

View file

@ -4,6 +4,7 @@
NS_ASSUME_NONNULL_BEGIN
@class OWSContact;
@class OWSSignalServiceProtosAttachmentPointer;
@class OWSSignalServiceProtosDataMessage;
@class OWSSignalServiceProtosSyncMessageSent;
@ -30,11 +31,12 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) BOOL isGroupUpdate;
@property (nonatomic, readonly) BOOL isExpirationTimerUpdate;
@property (nonatomic, readonly) BOOL isEndSessionMessage;
@property (nullable, nonatomic, readonly) NSData *groupId;
@property (nonatomic, readonly, nullable) NSData *groupId;
@property (nonatomic, readonly) NSString *body;
@property (nonatomic, readonly) NSArray<OWSSignalServiceProtosAttachmentPointer *> *attachmentPointerProtos;
@property (nonatomic, readonly) TSThread *thread;
@property (nonatomic, readonly) TSQuotedMessage *quotedMessage;
@property (nonatomic, readonly, nullable) TSQuotedMessage *quotedMessage;
@property (nonatomic, readonly, nullable) OWSContact *contact;
@end

View file

@ -3,6 +3,7 @@
//
#import "OWSIncomingSentMessageTranscript.h"
#import "OWSContact.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];
_contact = [OWSContacts contactForDataMessage:_dataMessage];
return self;
}

View file

@ -22,7 +22,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;

View file

@ -38,7 +38,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;
}

View file

@ -24,7 +24,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder

View file

@ -28,7 +28,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;
}

View file

@ -0,0 +1,69 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSContact.h"
NS_ASSUME_NONNULL_BEGIN
// These private interfaces expose setter accessors to facilitate
// construction of fake messages, etc.
@interface OWSContactPhoneNumber (Private)
@property (nonatomic) OWSContactPhoneType phoneType;
@property (nonatomic, nullable) NSString *label;
@property (nonatomic) NSString *phoneNumber;
@end
#pragma mark -
@interface OWSContactEmail (Private)
@property (nonatomic) OWSContactEmailType emailType;
@property (nonatomic, nullable) NSString *label;
@property (nonatomic) NSString *email;
@end
#pragma mark -
@interface OWSContactAddress (Private)
@property (nonatomic) OWSContactAddressType 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 -
@interface OWSContact (Private)
@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) NSString *organizationName;
@property (nonatomic, nullable) NSString *displayName;
@property (nonatomic, nullable) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
@property (nonatomic, nullable) NSArray<OWSContactEmail *> *emails;
@property (nonatomic, nullable) NSArray<OWSContactAddress *> *addresses;
@property (nonatomic, nullable) TSAttachment *avatar;
@property (nonatomic) BOOL isProfileAvatar;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,135 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <Mantle/MTLModel.h>
NS_ASSUME_NONNULL_BEGIN
@class CNContact;
@class OWSSignalServiceProtosDataMessage;
@class OWSSignalServiceProtosDataMessage;
@class OWSSignalServiceProtosDataMessageContact;
@class TSAttachment;
@class YapDatabaseReadWriteTransaction;
typedef NS_ENUM(NSUInteger, OWSContactPhoneType) {
OWSContactPhoneType_Home = 1,
OWSContactPhoneType_Mobile,
OWSContactPhoneType_Work,
OWSContactPhoneType_Custom,
};
@interface OWSContactPhoneNumber : MTLModel
@property (nonatomic, readonly) OWSContactPhoneType phoneType;
// Applies in the OWSContactPhoneType_Custom case.
@property (nonatomic, readonly, nullable) NSString *label;
@property (nonatomic, readonly) NSString *phoneNumber;
- (BOOL)ows_isValid;
@end
#pragma mark -
typedef NS_ENUM(NSUInteger, OWSContactEmailType) {
OWSContactEmailType_Home = 1,
OWSContactEmailType_Mobile,
OWSContactEmailType_Work,
OWSContactEmailType_Custom,
};
@interface OWSContactEmail : MTLModel
@property (nonatomic, readonly) OWSContactEmailType emailType;
// Applies in the OWSContactEmailType_Custom case.
@property (nonatomic, readonly, nullable) NSString *label;
@property (nonatomic, readonly) NSString *email;
- (BOOL)ows_isValid;
@end
#pragma mark -
typedef NS_ENUM(NSUInteger, OWSContactAddressType) {
OWSContactAddressType_Home = 1,
OWSContactAddressType_Work,
OWSContactAddressType_Custom,
};
@interface OWSContactAddress : MTLModel
@property (nonatomic, readonly) OWSContactAddressType addressType;
// Applies in the OWSContactAddressType_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;
- (BOOL)ows_isValid;
@end
#pragma mark -
@interface OWSContact : 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) NSString *organizationName;
@property (nonatomic, readonly, nullable) NSString *displayName;
@property (nonatomic, readonly, nullable) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
@property (nonatomic, readonly, nullable) NSArray<OWSContactEmail *> *emails;
@property (nonatomic, readonly, nullable) NSArray<OWSContactAddress *> *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;
- (BOOL)ows_isValid;
@end
#pragma mark -
@interface OWSContacts : NSObject
#pragma mark - VCard Serialization
+ (nullable CNContact *)systemContactForVCardData:(NSData *)data;
+ (nullable NSData *)vCardDataForSystemContact:(CNContact *)systemContact;
#pragma mark - System Contact Conversion
+ (nullable OWSContact *)contactForSystemContact:(CNContact *)systemContact;
+ (nullable CNContact *)systemContactForContact:(OWSContact *)contact;
#pragma mark -
+ (nullable OWSContact *)contactForVCardData:(NSData *)data;
+ (nullable NSData *)vCardDataContact:(OWSContact *)contact;
#pragma mark - Proto Serialization
+ (nullable OWSSignalServiceProtosDataMessageContact *)protoForContact:(OWSContact *)contact;
+ (OWSContact *_Nullable)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,778 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSContact.h"
#import "NSString+SSK.h"
#import "OWSContact+Private.h"
#import "OWSSignalServiceProtos.pb.h"
#import "PhoneNumber.h"
#import "TSAttachment.h"
#import <YapDatabase/YapDatabaseTransaction.h>
@import Contacts;
NS_ASSUME_NONNULL_BEGIN
@interface OWSContactPhoneNumber ()
@property (nonatomic) OWSContactPhoneType phoneType;
@property (nonatomic, nullable) NSString *label;
@property (nonatomic) NSString *phoneNumber;
@end
#pragma mark -
@implementation OWSContactPhoneNumber
- (BOOL)ows_isValid
{
if (![PhoneNumber tryParsePhoneNumberFromE164:self.phoneNumber]) {
return NO;
}
switch (self.phoneType) {
case OWSContactPhoneType_Home:
case OWSContactPhoneType_Mobile:
case OWSContactPhoneType_Work:
return YES;
case OWSContactPhoneType_Custom:
return self.label.ows_stripped.length > 0;
}
}
@end
#pragma mark -
@interface OWSContactEmail ()
@property (nonatomic) OWSContactEmailType emailType;
@property (nonatomic, nullable) NSString *label;
@property (nonatomic) NSString *email;
@end
#pragma mark -
@implementation OWSContactEmail
- (BOOL)ows_isValid
{
if (self.email.ows_stripped.length < 1) {
return NO;
}
switch (self.emailType) {
case OWSContactEmailType_Home:
case OWSContactEmailType_Mobile:
case OWSContactEmailType_Work:
return YES;
case OWSContactEmailType_Custom:
return self.label.ows_stripped.length > 0;
}
}
@end
#pragma mark -
@interface OWSContactAddress ()
@property (nonatomic) OWSContactAddressType 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 OWSContactAddress
- (BOOL)ows_isValid
{
if (self.street.ows_stripped.length < 1 && self.pobox.ows_stripped.length < 1
&& self.neighborhood.ows_stripped.length < 1 && self.city.ows_stripped.length < 1
&& self.region.ows_stripped.length < 1 && self.postcode.ows_stripped.length < 1
&& self.country.ows_stripped.length < 1) {
return NO;
}
switch (self.addressType) {
case OWSContactAddressType_Home:
case OWSContactAddressType_Work:
return YES;
case OWSContactAddressType_Custom:
return self.label.ows_stripped.length > 0;
}
}
@end
#pragma mark -
@interface OWSContact ()
@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) NSString *organizationName;
@property (nonatomic, nullable) NSString *displayName;
@property (nonatomic, nullable) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
@property (nonatomic, nullable) NSArray<OWSContactEmail *> *emails;
@property (nonatomic, nullable) NSArray<OWSContactAddress *> *addresses;
@property (nonatomic, nullable) TSAttachment *avatar;
@property (nonatomic) BOOL isProfileAvatar;
@end
#pragma mark -
@implementation OWSContact
- (BOOL)ows_isValid
{
if (self.displayName.ows_stripped.length) {
return NO;
}
// Contact is valid if at least one entry is valid.
for (OWSContactPhoneNumber *phoneNumber in self.phoneNumbers) {
if (phoneNumber.ows_isValid) {
return YES;
}
}
for (OWSContactEmail *email in self.emails) {
if (email.ows_isValid) {
return YES;
}
}
for (OWSContactAddress *address in self.addresses) {
if (address.ows_isValid) {
return YES;
}
}
return NO;
}
@end
#pragma mark -
@implementation OWSContacts
#pragma mark - VCard Serialization
+ (nullable CNContact *)systemContactForVCardData:(NSData *)data
{
OWSAssert(data);
NSError *error;
NSArray<CNContact *> *_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;
}
+ (nullable NSData *)vCardDataForSystemContact:(CNContact *)systemContact
{
OWSAssert(systemContact);
NSError *error;
NSData *_Nullable data = [CNContactVCardSerialization dataWithContacts:@[
systemContact,
]
error:&error];
if (!data || error) {
OWSProdLogAndFail(@"%@ could not serialize to vcard: %@", self.logTag, error);
return nil;
}
if (data.length < 1) {
OWSProdLogAndFail(@"%@ empty vcard data: %@", self.logTag, error);
return nil;
}
return data;
}
#pragma mark - System Contact Conversion
+ (nullable OWSContact *)contactForSystemContact:(CNContact *)systemContact
{
if (!systemContact) {
OWSProdLogAndFail(@"%@ Missing contact.", self.logTag);
return nil;
}
OWSContact *contact = [OWSContact new];
contact.givenName = systemContact.givenName.ows_stripped;
contact.middleName = systemContact.middleName.ows_stripped;
contact.familyName = systemContact.familyName.ows_stripped;
contact.namePrefix = systemContact.namePrefix.ows_stripped;
contact.nameSuffix = systemContact.nameSuffix.ows_stripped;
// TODO: Verify.
contact.displayName = [CNContactFormatter stringFromContact:systemContact style:CNContactFormatterStyleFullName];
contact.organizationName = systemContact.organizationName.ows_stripped;
NSMutableArray<OWSContactPhoneNumber *> *phoneNumbers = [NSMutableArray new];
for (CNLabeledValue<CNPhoneNumber *> *phoneNumberField in systemContact.phoneNumbers) {
OWSContactPhoneNumber *phoneNumber = [OWSContactPhoneNumber new];
phoneNumber.phoneNumber = phoneNumberField.value.stringValue;
if ([phoneNumberField.label isEqualToString:CNLabelHome]) {
phoneNumber.phoneType = OWSContactPhoneType_Home;
} else if ([phoneNumberField.label isEqualToString:CNLabelWork]) {
phoneNumber.phoneType = OWSContactPhoneType_Work;
} else if ([phoneNumberField.label isEqualToString:CNLabelPhoneNumberMobile]) {
phoneNumber.phoneType = OWSContactPhoneType_Mobile;
} else {
phoneNumber.phoneType = OWSContactPhoneType_Custom;
phoneNumber.label = phoneNumberField.label;
}
if (phoneNumber.ows_isValid) {
[phoneNumbers addObject:phoneNumber];
}
}
contact.phoneNumbers = phoneNumbers;
NSMutableArray<OWSContactEmail *> *emails = [NSMutableArray new];
for (CNLabeledValue *emailField in systemContact.emailAddresses) {
OWSContactEmail *email = [OWSContactEmail new];
email.email = emailField.value;
if ([emailField.label isEqualToString:CNLabelHome]) {
email.emailType = OWSContactEmailType_Home;
} else if ([emailField.label isEqualToString:CNLabelWork]) {
email.emailType = OWSContactEmailType_Work;
} else {
email.emailType = OWSContactEmailType_Custom;
email.label = emailField.label;
}
if (email.ows_isValid) {
[emails addObject:email];
}
}
contact.emails = emails;
NSMutableArray<OWSContactAddress *> *addresses = [NSMutableArray new];
for (CNLabeledValue<CNPostalAddress *> *addressField in systemContact.postalAddresses) {
OWSContactAddress *address = [OWSContactAddress new];
address.street = addressField.value.street;
// TODO: Is this the correct mapping?
// address.neighborhood = addressField.value.subLocality;
address.city = addressField.value.city;
// TODO: Is this the correct mapping?
// address.region = addressField.value.subAdministrativeArea;
address.region = addressField.value.state;
address.postcode = addressField.value.postalCode;
// TODO: Should we be using 2-letter codes, 3-letter codes or names?
address.country = addressField.value.ISOCountryCode;
if ([addressField.label isEqualToString:CNLabelHome]) {
address.addressType = OWSContactAddressType_Home;
} else if ([addressField.label isEqualToString:CNLabelWork]) {
address.addressType = OWSContactAddressType_Work;
} else {
address.addressType = OWSContactAddressType_Custom;
address.label = addressField.label;
}
if (address.ows_isValid) {
[addresses addObject:address];
}
}
contact.addresses = addresses;
// TODO: Avatar
// @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *imageData;
// @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *thumbnailImageData;
if (contact.ows_isValid) {
return contact;
} else {
return nil;
}
}
+ (nullable CNContact *)systemContactForContact:(OWSContact *)contact
{
if (!contact) {
OWSProdLogAndFail(@"%@ Missing contact.", self.logTag);
return nil;
}
if (!contact.ows_isValid) {
OWSProdLogAndFail(@"%@ Invalid contact.", self.logTag);
return nil;
}
CNMutableContact *systemContact = [CNMutableContact new];
systemContact.givenName = contact.givenName;
systemContact.middleName = contact.middleName;
systemContact.familyName = contact.familyName;
systemContact.namePrefix = contact.namePrefix;
systemContact.nameSuffix = contact.nameSuffix;
// We don't need to set display name, it's implicit for system contacts.
systemContact.organizationName = contact.organizationName;
NSMutableArray<CNLabeledValue<CNPhoneNumber *> *> *systemPhoneNumbers = [NSMutableArray new];
for (OWSContactPhoneNumber *phoneNumber in contact.phoneNumbers) {
if (!phoneNumber.ows_isValid) {
OWSProdLogAndFail(@"%@ invalid phone number.", self.logTag);
continue;
}
switch (phoneNumber.phoneType) {
case OWSContactPhoneType_Home:
[systemPhoneNumbers
addObject:[CNLabeledValue
labeledValueWithLabel:CNLabelHome
value:[CNPhoneNumber
phoneNumberWithStringValue:phoneNumber.phoneNumber]]];
break;
case OWSContactPhoneType_Mobile:
[systemPhoneNumbers
addObject:[CNLabeledValue
labeledValueWithLabel:CNLabelPhoneNumberMobile
value:[CNPhoneNumber
phoneNumberWithStringValue:phoneNumber.phoneNumber]]];
break;
case OWSContactPhoneType_Work:
[systemPhoneNumbers
addObject:[CNLabeledValue
labeledValueWithLabel:CNLabelWork
value:[CNPhoneNumber
phoneNumberWithStringValue:phoneNumber.phoneNumber]]];
break;
case OWSContactPhoneType_Custom:
[systemPhoneNumbers
addObject:[CNLabeledValue
labeledValueWithLabel:phoneNumber.label
value:[CNPhoneNumber
phoneNumberWithStringValue:phoneNumber.phoneNumber]]];
break;
}
}
systemContact.phoneNumbers = systemPhoneNumbers;
NSMutableArray<CNLabeledValue<NSString *> *> *systemEmails = [NSMutableArray new];
for (OWSContactEmail *email in contact.emails) {
if (!email.ows_isValid) {
OWSProdLogAndFail(@"%@ invalid email.", self.logTag);
continue;
}
switch (email.emailType) {
case OWSContactEmailType_Home:
[systemEmails addObject:[CNLabeledValue labeledValueWithLabel:CNLabelHome value:email.email]];
break;
case OWSContactEmailType_Mobile:
[systemEmails addObject:[CNLabeledValue labeledValueWithLabel:@"Mobile" value:email.email]];
break;
case OWSContactEmailType_Work:
[systemEmails addObject:[CNLabeledValue labeledValueWithLabel:CNLabelWork value:email.email]];
break;
case OWSContactEmailType_Custom:
[systemEmails addObject:[CNLabeledValue labeledValueWithLabel:email.label value:email.email]];
break;
}
}
systemContact.emailAddresses = systemEmails;
NSMutableArray<CNLabeledValue<CNPostalAddress *> *> *systemAddresses = [NSMutableArray new];
for (OWSContactAddress *address in contact.addresses) {
if (!address.ows_isValid) {
OWSProdLogAndFail(@"%@ invalid address.", self.logTag);
continue;
}
CNMutablePostalAddress *systemAddress = [CNMutablePostalAddress new];
systemAddress.street = address.street;
// TODO: Is this the correct mapping?
// systemAddress.subLocality = address.neighborhood;
systemAddress.city = address.city;
// TODO: Is this the correct mapping?
// systemAddress.subAdministrativeArea = address.region;
systemAddress.state = address.region;
systemAddress.postalCode = address.postcode;
// TODO: Should we be using 2-letter codes, 3-letter codes or names?
systemAddress.ISOCountryCode = address.country;
switch (address.addressType) {
case OWSContactAddressType_Home:
[systemAddresses addObject:[CNLabeledValue labeledValueWithLabel:CNLabelHome value:systemAddress]];
break;
case OWSContactAddressType_Work:
[systemAddresses addObject:[CNLabeledValue labeledValueWithLabel:CNLabelWork value:systemAddress]];
break;
case OWSContactAddressType_Custom:
[systemAddresses addObject:[CNLabeledValue labeledValueWithLabel:address.label value:systemAddress]];
break;
}
}
systemContact.postalAddresses = systemAddresses;
// TODO: Avatar
// @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *imageData;
// @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *thumbnailImageData;
return systemContact;
}
#pragma mark -
+ (nullable OWSContact *)contactForVCardData:(NSData *)data
{
OWSAssert(data);
CNContact *_Nullable systemContact = [self systemContactForVCardData:data];
if (!systemContact) {
return nil;
}
return [self contactForSystemContact:systemContact];
}
+ (nullable NSData *)vCardDataContact:(OWSContact *)contact
{
OWSAssert(contact);
CNContact *_Nullable systemContact = [self systemContactForContact:contact];
if (!systemContact) {
return nil;
}
return [self vCardDataForSystemContact:systemContact];
}
#pragma mark - Proto Serialization
+ (nullable OWSSignalServiceProtosDataMessageContact *)protoForContact:(OWSContact *)contact
{
OWSAssert(contact);
if (!contact.ows_isValid) {
OWSProdLogAndFail(@"%@ contact share is invalid.", self.logTag);
return nil;
}
OWSSignalServiceProtosDataMessageContactBuilder *contactBuilder =
[OWSSignalServiceProtosDataMessageContactBuilder new];
OWSSignalServiceProtosDataMessageContactNameBuilder *nameBuilder =
[OWSSignalServiceProtosDataMessageContactNameBuilder new];
if (contact.givenName.ows_stripped.length > 0) {
nameBuilder.givenName = contact.givenName.ows_stripped;
}
if (contact.familyName.ows_stripped.length > 0) {
nameBuilder.familyName = contact.familyName.ows_stripped;
}
if (contact.middleName.ows_stripped.length > 0) {
nameBuilder.middleName = contact.middleName.ows_stripped;
}
if (contact.namePrefix.ows_stripped.length > 0) {
nameBuilder.prefix = contact.namePrefix.ows_stripped;
}
if (contact.nameSuffix.ows_stripped.length > 0) {
nameBuilder.suffix = contact.nameSuffix.ows_stripped;
}
[contactBuilder setNameBuilder:nameBuilder];
for (OWSContactPhoneNumber *phoneNumber in contact.phoneNumbers) {
if (!phoneNumber.ows_isValid) {
OWSProdLogAndFail(@"%@ phone number is invalid.", self.logTag);
continue;
}
OWSSignalServiceProtosDataMessageContactPhoneBuilder *phoneBuilder =
[OWSSignalServiceProtosDataMessageContactPhoneBuilder new];
phoneBuilder.value = phoneNumber.phoneNumber;
if (phoneBuilder.label.ows_stripped.length > 0) {
phoneBuilder.label = phoneBuilder.label.ows_stripped;
}
switch (phoneNumber.phoneType) {
case OWSContactPhoneType_Home:
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeHome;
break;
case OWSContactPhoneType_Mobile:
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeMobile;
break;
case OWSContactPhoneType_Work:
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeWork;
break;
case OWSContactPhoneType_Custom:
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeCustom;
break;
}
[contactBuilder addNumber:phoneBuilder.build];
}
for (OWSContactEmail *email in contact.emails) {
if (!email.ows_isValid) {
OWSProdLogAndFail(@"%@ email is invalid.", self.logTag);
continue;
}
OWSSignalServiceProtosDataMessageContactEmailBuilder *emailBuilder =
[OWSSignalServiceProtosDataMessageContactEmailBuilder new];
emailBuilder.value = email.email;
if (emailBuilder.label.ows_stripped.length > 0) {
emailBuilder.label = emailBuilder.label.ows_stripped;
}
switch (email.emailType) {
case OWSContactEmailType_Home:
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeHome;
break;
case OWSContactEmailType_Mobile:
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeMobile;
break;
case OWSContactEmailType_Work:
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeWork;
break;
case OWSContactEmailType_Custom:
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeCustom;
break;
}
[contactBuilder addEmail:emailBuilder.build];
}
for (OWSContactAddress *address in contact.addresses) {
if (!address.ows_isValid) {
OWSProdLogAndFail(@"%@ address is invalid.", self.logTag);
continue;
}
OWSSignalServiceProtosDataMessageContactPostalAddressBuilder *addressBuilder =
[OWSSignalServiceProtosDataMessageContactPostalAddressBuilder new];
if (addressBuilder.label.ows_stripped.length > 0) {
addressBuilder.label = addressBuilder.label.ows_stripped;
}
if (addressBuilder.street.ows_stripped.length > 0) {
addressBuilder.street = addressBuilder.street.ows_stripped;
}
if (addressBuilder.pobox.ows_stripped.length > 0) {
addressBuilder.pobox = addressBuilder.pobox.ows_stripped;
}
if (addressBuilder.neighborhood.ows_stripped.length > 0) {
addressBuilder.neighborhood = addressBuilder.neighborhood.ows_stripped;
}
if (addressBuilder.city.ows_stripped.length > 0) {
addressBuilder.city = addressBuilder.city.ows_stripped;
}
if (addressBuilder.region.ows_stripped.length > 0) {
addressBuilder.region = addressBuilder.region.ows_stripped;
}
if (addressBuilder.postcode.ows_stripped.length > 0) {
addressBuilder.postcode = addressBuilder.postcode.ows_stripped;
}
if (addressBuilder.country.ows_stripped.length > 0) {
addressBuilder.country = addressBuilder.country.ows_stripped;
}
[contactBuilder addAddress:addressBuilder.build];
}
// TODO: avatar
OWSSignalServiceProtosDataMessageContact *contactProto = [contactBuilder build];
if (contactProto.number.count < 1 && contactProto.email.count < 1 && contactProto.address.count < 1) {
OWSProdLogAndFail(@"%@ contact has neither phone, email or address.", self.logTag);
return nil;
}
return contactProto;
}
+ (OWSContact *_Nullable)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage
{
OWSAssert(dataMessage);
if (dataMessage.contact.count < 1) {
return nil;
}
OWSAssert(dataMessage.contact.count == 1);
OWSSignalServiceProtosDataMessageContact *contactProto = dataMessage.contact.firstObject;
OWSContact *contact = [OWSContact new];
if (contactProto.hasOrganization) {
contact.organizationName = contactProto.organization.ows_stripped;
}
if (contactProto.hasName) {
OWSSignalServiceProtosDataMessageContactName *nameProto = contactProto.name;
if (nameProto.hasGivenName) {
contact.givenName = nameProto.givenName.ows_stripped;
}
if (nameProto.hasFamilyName) {
contact.familyName = nameProto.familyName.ows_stripped;
}
if (nameProto.hasPrefix) {
contact.namePrefix = nameProto.prefix.ows_stripped;
}
if (nameProto.hasSuffix) {
contact.nameSuffix = nameProto.suffix.ows_stripped;
}
if (nameProto.hasMiddleName) {
contact.middleName = nameProto.middleName.ows_stripped;
}
if (nameProto.hasDisplayName) {
contact.displayName = nameProto.displayName.ows_stripped;
}
}
NSMutableArray<OWSContactPhoneNumber *> *phoneNumbers = [NSMutableArray new];
for (OWSSignalServiceProtosDataMessageContactPhone *phoneNumberProto in contactProto.number) {
OWSContactPhoneNumber *_Nullable phoneNumber = [self phoneNumberForProto:phoneNumberProto];
if (phoneNumber) {
[phoneNumbers addObject:phoneNumber];
}
}
contact.phoneNumbers = [phoneNumbers copy];
NSMutableArray<OWSContactEmail *> *emails = [NSMutableArray new];
for (OWSSignalServiceProtosDataMessageContactEmail *emailProto in contactProto.email) {
OWSContactEmail *_Nullable email = [self emailForProto:emailProto];
if (email) {
[emails addObject:email];
}
}
contact.emails = [emails copy];
NSMutableArray<OWSContactAddress *> *addresses = [NSMutableArray new];
for (OWSSignalServiceProtosDataMessageContactPostalAddress *addressProto in contactProto.address) {
OWSContactAddress *_Nullable address = [self addressForProto:addressProto];
if (address) {
[addresses addObject:address];
}
}
contact.addresses = [addresses copy];
// TODO: Avatar
return contact;
}
+ (nullable OWSContactPhoneNumber *)phoneNumberForProto:
(OWSSignalServiceProtosDataMessageContactPhone *)phoneNumberProto
{
OWSContactPhoneNumber *result = [OWSContactPhoneNumber new];
result.phoneType = OWSContactPhoneType_Custom;
if (phoneNumberProto.hasType) {
switch (phoneNumberProto.type) {
case OWSSignalServiceProtosDataMessageContactPhoneTypeHome:
result.phoneType = OWSContactPhoneType_Home;
break;
case OWSSignalServiceProtosDataMessageContactPhoneTypeMobile:
result.phoneType = OWSContactPhoneType_Mobile;
break;
case OWSSignalServiceProtosDataMessageContactPhoneTypeWork:
result.phoneType = OWSContactPhoneType_Work;
break;
default:
break;
}
}
if (phoneNumberProto.hasLabel) {
result.label = phoneNumberProto.label.ows_stripped;
}
if (phoneNumberProto.hasValue) {
result.phoneNumber = phoneNumberProto.value.ows_stripped;
} else {
return nil;
}
if (!result.ows_isValid) {
return nil;
}
return result;
}
+ (nullable OWSContactEmail *)emailForProto:(OWSSignalServiceProtosDataMessageContactEmail *)emailProto
{
OWSContactEmail *result = [OWSContactEmail new];
result.emailType = OWSContactEmailType_Custom;
if (emailProto.hasType) {
switch (emailProto.type) {
case OWSSignalServiceProtosDataMessageContactEmailTypeHome:
result.emailType = OWSContactEmailType_Home;
break;
case OWSSignalServiceProtosDataMessageContactEmailTypeMobile:
result.emailType = OWSContactEmailType_Mobile;
break;
case OWSSignalServiceProtosDataMessageContactEmailTypeWork:
result.emailType = OWSContactEmailType_Work;
break;
default:
break;
}
}
if (emailProto.hasLabel) {
result.label = emailProto.label.ows_stripped;
}
if (emailProto.hasValue) {
result.email = emailProto.value.ows_stripped;
} else {
return nil;
}
if (!result.ows_isValid) {
return nil;
}
return result;
}
+ (nullable OWSContactAddress *)addressForProto:(OWSSignalServiceProtosDataMessageContactPostalAddress *)addressProto
{
OWSContactAddress *result = [OWSContactAddress new];
result.addressType = OWSContactAddressType_Custom;
if (addressProto.hasType) {
switch (addressProto.type) {
case OWSSignalServiceProtosDataMessageContactPostalAddressTypeHome:
result.addressType = OWSContactAddressType_Home;
break;
case OWSSignalServiceProtosDataMessageContactPostalAddressTypeWork:
result.addressType = OWSContactAddressType_Work;
break;
default:
break;
}
}
if (addressProto.hasLabel) {
result.label = addressProto.label.ows_stripped;
}
if (addressProto.hasStreet) {
result.street = addressProto.street.ows_stripped;
}
if (addressProto.hasPobox) {
result.pobox = addressProto.pobox.ows_stripped;
}
if (addressProto.hasNeighborhood) {
result.neighborhood = addressProto.neighborhood.ows_stripped;
}
if (addressProto.hasCity) {
result.city = addressProto.city.ows_stripped;
}
if (addressProto.hasRegion) {
result.region = addressProto.region.ows_stripped;
}
if (addressProto.hasPostcode) {
result.postcode = addressProto.postcode.ows_stripped;
}
if (addressProto.hasCountry) {
result.country = addressProto.country.ows_stripped;
}
if (!result.ows_isValid) {
return nil;
}
return result;
}
@end
NS_ASSUME_NONNULL_END

View file

@ -34,7 +34,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;
}

View file

@ -35,7 +35,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (self) {
_block = block;

View file

@ -19,7 +19,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
}
- (BOOL)shouldBeSaved

View file

@ -33,7 +33,8 @@ typedef NS_ENUM(int32_t, TSErrorMessageType) {
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contact NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -65,7 +65,8 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
attachmentIds:@[]
expiresInSeconds:0
expireStartedAt:0
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;

View file

@ -18,7 +18,8 @@ NS_ASSUME_NONNULL_BEGIN
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare NS_UNAVAILABLE;
/**
* Inits an incoming group message that expires.
@ -49,7 +50,8 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER;
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -44,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)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;

View file

@ -34,7 +34,8 @@ typedef NS_ENUM(NSInteger, TSInfoMessageType) {
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contact NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -52,7 +52,8 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
attachmentIds:@[]
expiresInSeconds:0
expireStartedAt:0
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;

View file

@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
* Abstract message class.
*/
@class OWSContact;
@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) OWSContact *contactShare;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
@ -33,7 +35,8 @@ NS_ASSUME_NONNULL_BEGIN
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER;
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -7,6 +7,7 @@
#import "MIMETypeUtil.h"
#import "NSDate+OWS.h"
#import "NSString+SSK.h"
#import "OWSContact.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 OWSContact *)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;
}
@ -258,6 +261,9 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
return bodyDescription;
} else if (attachmentDescription.length > 0) {
return attachmentDescription;
} else if (self.contactShare) {
// TODO: Include properly formatted name.
return @"👤";
} else {
OWSFail(@"%@ message has neither body nor attachment.", self.logTag);
// TODO: We should do better here.

View file

@ -74,7 +74,8 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare NS_UNAVAILABLE;
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
@ -84,7 +85,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 OWSContact *)contactShare NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -4,6 +4,8 @@
#import "TSOutgoingMessage.h"
#import "NSDate+OWS.h"
#import "NSString+SSK.h"
#import "OWSContact.h"
#import "OWSMessageSender.h"
#import "OWSOutgoingSyncMessage.h"
#import "OWSPrimaryStorage.h"
@ -242,7 +244,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:quotedMessage];
quotedMessage:quotedMessage
contactShare:nil];
}
+ (instancetype)outgoingMessageInThread:(nullable TSThread *)thread
@ -256,7 +259,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:groupMetaMessage
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
}
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp
@ -268,6 +272,7 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
isVoiceMessage:(BOOL)isVoiceMessage
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare
{
self = [super initMessageWithTimestamp:timestamp
inThread:thread
@ -275,7 +280,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:expireStartedAt
quotedMessage:quotedMessage];
quotedMessage:quotedMessage
contactShare:contactShare];
if (!self) {
return self;
}
@ -780,48 +786,69 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
}
[builder setAttachmentsArray:attachments];
}
// Quoted Attachment
TSQuotedMessage *quotedMessage = self.quotedMessage;
if (quotedMessage) {
OWSSignalServiceProtosDataMessageQuoteBuilder *quoteBuilder = [OWSSignalServiceProtosDataMessageQuoteBuilder new];
[quoteBuilder setId:quotedMessage.timestamp];
[quoteBuilder setAuthor:quotedMessage.authorId];
BOOL hasQuotedText = NO;
BOOL hasQuotedAttachment = NO;
if (self.quotedMessage.body.length > 0) {
hasQuotedText = YES;
[quoteBuilder setText:quotedMessage.body];
}
if (quotedMessage.quotedAttachments) {
for (OWSAttachmentInfo *attachment in quotedMessage.quotedAttachments) {
hasQuotedAttachment = YES;
// Quoted Reply
OWSSignalServiceProtosDataMessageQuoteBuilder *_Nullable quotedMessageBuilder = self.quotedMessageBuilder;
if (quotedMessageBuilder) {
[builder setQuoteBuilder:quotedMessageBuilder];
}
OWSSignalServiceProtosDataMessageQuoteQuotedAttachmentBuilder *quotedAttachmentBuilder = [OWSSignalServiceProtosDataMessageQuoteQuotedAttachmentBuilder new];
quotedAttachmentBuilder.contentType = attachment.contentType;
quotedAttachmentBuilder.fileName = attachment.sourceFilename;
if (attachment.thumbnailAttachmentStreamId) {
quotedAttachmentBuilder.thumbnail =
[self buildProtoForAttachmentId:attachment.thumbnailAttachmentStreamId];
}
[quoteBuilder addAttachments:[quotedAttachmentBuilder build]];
}
}
if (hasQuotedText || hasQuotedAttachment) {
[builder setQuoteBuilder:quoteBuilder];
} else {
OWSFail(@"%@ Invalid quoted message data.", self.logTag);
// Contact Share
if (self.contactShare) {
OWSSignalServiceProtosDataMessageContact *_Nullable contactProto =
[OWSContacts protoForContact:self.contactShare];
if (contactProto) {
[builder addContact:contactProto];
}
}
return builder;
}
- (nullable OWSSignalServiceProtosDataMessageQuoteBuilder *)quotedMessageBuilder
{
if (!self.quotedMessage) {
return nil;
}
TSQuotedMessage *quotedMessage = self.quotedMessage;
OWSSignalServiceProtosDataMessageQuoteBuilder *quoteBuilder = [OWSSignalServiceProtosDataMessageQuoteBuilder new];
[quoteBuilder setId:quotedMessage.timestamp];
[quoteBuilder setAuthor:quotedMessage.authorId];
BOOL hasQuotedText = NO;
BOOL hasQuotedAttachment = NO;
if (self.quotedMessage.body.length > 0) {
hasQuotedText = YES;
[quoteBuilder setText:quotedMessage.body];
}
if (quotedMessage.quotedAttachments) {
for (OWSAttachmentInfo *attachment in quotedMessage.quotedAttachments) {
hasQuotedAttachment = YES;
OWSSignalServiceProtosDataMessageQuoteQuotedAttachmentBuilder *quotedAttachmentBuilder =
[OWSSignalServiceProtosDataMessageQuoteQuotedAttachmentBuilder new];
quotedAttachmentBuilder.contentType = attachment.contentType;
quotedAttachmentBuilder.fileName = attachment.sourceFilename;
if (attachment.thumbnailAttachmentStreamId) {
quotedAttachmentBuilder.thumbnail =
[self buildProtoForAttachmentId:attachment.thumbnailAttachmentStreamId];
}
[quoteBuilder addAttachments:[quotedAttachmentBuilder build]];
}
}
if (hasQuotedText || hasQuotedAttachment) {
return quoteBuilder;
} else {
OWSFail(@"%@ Invalid quoted message data.", self.logTag);
return nil;
}
}
// recipientId is nil when building "sent" sync messages for messages sent to groups.
- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *_Nullable)recipientId
{

View file

@ -14,6 +14,7 @@
#import "OWSAttachmentsProcessor.h"
#import "OWSBlockingManager.h"
#import "OWSCallMessageHandler.h"
#import "OWSContact.h"
#import "OWSDevice.h"
#import "OWSDisappearingConfigurationUpdateInfoMessage.h"
#import "OWSDisappearingMessagesConfiguration.h"
@ -996,6 +997,8 @@ NS_ASSUME_NONNULL_BEGIN
relay:envelope.relay
transaction:transaction];
OWSContact *_Nullable contact = [OWSContacts contactForDataMessage:dataMessage];
DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu",
self.logTag,
envelopeAddress(envelope),
@ -1010,7 +1013,8 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer
quotedMessage:quotedMessage];
quotedMessage:quotedMessage
contactShare:contact];
[self finalizeIncomingMessage:incomingMessage
thread:oldGroupThread
@ -1044,6 +1048,7 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread
relay:envelope.relay
transaction:transaction];
OWSContact *_Nullable contact = [OWSContacts contactForDataMessage:dataMessage];
TSIncomingMessage *incomingMessage =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
@ -1053,7 +1058,8 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer
quotedMessage:quotedMessage];
quotedMessage:quotedMessage
contactShare:contact];
[self finalizeIncomingMessage:incomingMessage
thread:thread

View file

@ -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];
}];
}

View file

@ -30,7 +30,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;
}

View file

@ -32,7 +32,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
if (!self) {
return self;
}

View file

@ -22,7 +22,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUnspecified
quotedMessage:nil];
quotedMessage:nil
contactShare:nil];
}
- (BOOL)shouldBeSaved

View file

@ -27,6 +27,8 @@
@class OWSSignalServiceProtosDataMessage;
@class OWSSignalServiceProtosDataMessageBuilder;
@class OWSSignalServiceProtosDataMessageContact;
@class OWSSignalServiceProtosDataMessageContactAvatar;
@class OWSSignalServiceProtosDataMessageContactAvatarBuilder;
@class OWSSignalServiceProtosDataMessageContactBuilder;
@class OWSSignalServiceProtosDataMessageContactEmail;
@class OWSSignalServiceProtosDataMessageContactEmailBuilder;
@ -1075,23 +1077,28 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
#define Contact_email @"email"
#define Contact_address @"address"
#define Contact_avatar @"avatar"
#define Contact_organization @"organization"
@interface OWSSignalServiceProtosDataMessageContact : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasOrganization_:1;
BOOL hasName_:1;
BOOL hasAvatar_:1;
NSString* organization;
OWSSignalServiceProtosDataMessageContactName* name;
OWSSignalServiceProtosAttachmentPointer* avatar;
OWSSignalServiceProtosDataMessageContactAvatar* avatar;
NSMutableArray * numberArray;
NSMutableArray * emailArray;
NSMutableArray * addressArray;
}
- (BOOL) hasName;
- (BOOL) hasAvatar;
- (BOOL) hasOrganization;
@property (readonly, strong) OWSSignalServiceProtosDataMessageContactName* name;
@property (readonly, strong) NSArray<OWSSignalServiceProtosDataMessageContactPhone*> * number;
@property (readonly, strong) NSArray<OWSSignalServiceProtosDataMessageContactEmail*> * email;
@property (readonly, strong) NSArray<OWSSignalServiceProtosDataMessageContactPostalAddress*> * address;
@property (readonly, strong) OWSSignalServiceProtosAttachmentPointer* avatar;
@property (readonly, strong) OWSSignalServiceProtosDataMessageContactAvatar* avatar;
@property (readonly, strong) NSString* organization;
- (OWSSignalServiceProtosDataMessageContactPhone*)numberAtIndex:(NSUInteger)index;
- (OWSSignalServiceProtosDataMessageContactEmail*)emailAtIndex:(NSUInteger)index;
- (OWSSignalServiceProtosDataMessageContactPostalAddress*)addressAtIndex:(NSUInteger)index;
@ -1119,6 +1126,7 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
#define Name_prefix @"prefix"
#define Name_suffix @"suffix"
#define Name_middleName @"middleName"
#define Name_displayName @"displayName"
@interface OWSSignalServiceProtosDataMessageContactName : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasGivenName_:1;
@ -1126,22 +1134,26 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
BOOL hasPrefix_:1;
BOOL hasSuffix_:1;
BOOL hasMiddleName_:1;
BOOL hasDisplayName_:1;
NSString* givenName;
NSString* familyName;
NSString* prefix;
NSString* suffix;
NSString* middleName;
NSString* displayName;
}
- (BOOL) hasGivenName;
- (BOOL) hasFamilyName;
- (BOOL) hasPrefix;
- (BOOL) hasSuffix;
- (BOOL) hasMiddleName;
- (BOOL) hasDisplayName;
@property (readonly, strong) NSString* givenName;
@property (readonly, strong) NSString* familyName;
@property (readonly, strong) NSString* prefix;
@property (readonly, strong) NSString* suffix;
@property (readonly, strong) NSString* middleName;
@property (readonly, strong) NSString* displayName;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
@ -1202,6 +1214,11 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (NSString*) middleName;
- (OWSSignalServiceProtosDataMessageContactNameBuilder*) setMiddleName:(NSString*) value;
- (OWSSignalServiceProtosDataMessageContactNameBuilder*) clearMiddleName;
- (BOOL) hasDisplayName;
- (NSString*) displayName;
- (OWSSignalServiceProtosDataMessageContactNameBuilder*) setDisplayName:(NSString*) value;
- (OWSSignalServiceProtosDataMessageContactNameBuilder*) clearDisplayName;
@end
#define Phone_value @"value"
@ -1474,6 +1491,68 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (OWSSignalServiceProtosDataMessageContactPostalAddressBuilder*) clearCountry;
@end
#define Avatar_avatar @"avatar"
#define Avatar_isProfile @"isProfile"
@interface OWSSignalServiceProtosDataMessageContactAvatar : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasIsProfile_:1;
BOOL hasAvatar_:1;
BOOL isProfile_:1;
OWSSignalServiceProtosAttachmentPointer* avatar;
}
- (BOOL) hasAvatar;
- (BOOL) hasIsProfile;
@property (readonly, strong) OWSSignalServiceProtosAttachmentPointer* avatar;
- (BOOL) isProfile;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builder;
+ (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builder;
+ (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builderWithPrototype:(OWSSignalServiceProtosDataMessageContactAvatar*) prototype;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) toBuilder;
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromData:(NSData*) data;
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromInputStream:(NSInputStream*) input;
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface OWSSignalServiceProtosDataMessageContactAvatarBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosDataMessageContactAvatar* resultAvatar;
}
- (OWSSignalServiceProtosDataMessageContactAvatar*) defaultInstance;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clear;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clone;
- (OWSSignalServiceProtosDataMessageContactAvatar*) build;
- (OWSSignalServiceProtosDataMessageContactAvatar*) buildPartial;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeFrom:(OWSSignalServiceProtosDataMessageContactAvatar*) other;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasAvatar;
- (OWSSignalServiceProtosAttachmentPointer*) avatar;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) setAvatar:(OWSSignalServiceProtosAttachmentPointer*) value;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) setAvatarBuilder:(OWSSignalServiceProtosAttachmentPointerBuilder*) builderForValue;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeAvatar:(OWSSignalServiceProtosAttachmentPointer*) value;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clearAvatar;
- (BOOL) hasIsProfile;
- (BOOL) isProfile;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) setIsProfile:(BOOL) value;
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clearIsProfile;
@end
@interface OWSSignalServiceProtosDataMessageContactBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosDataMessageContact* resultContact;
@ -1517,11 +1596,16 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (OWSSignalServiceProtosDataMessageContactBuilder *)clearAddress;
- (BOOL) hasAvatar;
- (OWSSignalServiceProtosAttachmentPointer*) avatar;
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatar:(OWSSignalServiceProtosAttachmentPointer*) value;
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatarBuilder:(OWSSignalServiceProtosAttachmentPointerBuilder*) builderForValue;
- (OWSSignalServiceProtosDataMessageContactBuilder*) mergeAvatar:(OWSSignalServiceProtosAttachmentPointer*) value;
- (OWSSignalServiceProtosDataMessageContactAvatar*) avatar;
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatar:(OWSSignalServiceProtosDataMessageContactAvatar*) value;
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatarBuilder:(OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builderForValue;
- (OWSSignalServiceProtosDataMessageContactBuilder*) mergeAvatar:(OWSSignalServiceProtosDataMessageContactAvatar*) value;
- (OWSSignalServiceProtosDataMessageContactBuilder*) clearAvatar;
- (BOOL) hasOrganization;
- (NSString*) organization;
- (OWSSignalServiceProtosDataMessageContactBuilder*) setOrganization:(NSString*) value;
- (OWSSignalServiceProtosDataMessageContactBuilder*) clearOrganization;
@end
@interface OWSSignalServiceProtosDataMessageBuilder : PBGeneratedMessageBuilder {

View file

@ -4049,7 +4049,8 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageQuoteQuotedAttachmentFlag
@property (strong) NSMutableArray<OWSSignalServiceProtosDataMessageContactPhone*> * numberArray;
@property (strong) NSMutableArray<OWSSignalServiceProtosDataMessageContactEmail*> * emailArray;
@property (strong) NSMutableArray<OWSSignalServiceProtosDataMessageContactPostalAddress*> * addressArray;
@property (strong) OWSSignalServiceProtosAttachmentPointer* avatar;
@property (strong) OWSSignalServiceProtosDataMessageContactAvatar* avatar;
@property (strong) NSString* organization;
@end
@implementation OWSSignalServiceProtosDataMessageContact
@ -4074,10 +4075,18 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageQuoteQuotedAttachmentFlag
hasAvatar_ = !!_value_;
}
@synthesize avatar;
- (BOOL) hasOrganization {
return !!hasOrganization_;
}
- (void) setHasOrganization:(BOOL) _value_ {
hasOrganization_ = !!_value_;
}
@synthesize organization;
- (instancetype) init {
if ((self = [super init])) {
self.name = [OWSSignalServiceProtosDataMessageContactName defaultInstance];
self.avatar = [OWSSignalServiceProtosAttachmentPointer defaultInstance];
self.avatar = [OWSSignalServiceProtosDataMessageContactAvatar defaultInstance];
self.organization = @"";
}
return self;
}
@ -4130,6 +4139,9 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
if (self.hasAvatar) {
[output writeMessage:6 value:self.avatar];
}
if (self.hasOrganization) {
[output writeString:7 value:self.organization];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32) serializedSize {
@ -4154,6 +4166,9 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
if (self.hasAvatar) {
size_ += computeMessageSize(6, self.avatar);
}
if (self.hasOrganization) {
size_ += computeStringSize(7, self.organization);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
@ -4219,6 +4234,9 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
withIndent:[NSString stringWithFormat:@"%@ ", indent]];
[output appendFormat:@"%@}\n", indent];
}
if (self.hasOrganization) {
[output appendFormat:@"%@%@: %@\n", indent, @"organization", self.organization];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void) storeInDictionary:(NSMutableDictionary *)dictionary {
@ -4247,6 +4265,9 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
[self.avatar storeInDictionary:messageDictionary];
[dictionary setObject:[NSDictionary dictionaryWithDictionary:messageDictionary] forKey:@"avatar"];
}
if (self.hasOrganization) {
[dictionary setObject: self.organization forKey: @"organization"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL) isEqual:(id)other {
@ -4265,6 +4286,8 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
[self.addressArray isEqualToArray:otherMessage.addressArray] &&
self.hasAvatar == otherMessage.hasAvatar &&
(!self.hasAvatar || [self.avatar isEqual:otherMessage.avatar]) &&
self.hasOrganization == otherMessage.hasOrganization &&
(!self.hasOrganization || [self.organization isEqual:otherMessage.organization]) &&
(self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger) hash {
@ -4284,6 +4307,9 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
if (self.hasAvatar) {
hashCode = hashCode * 31 + [self.avatar hash];
}
if (self.hasOrganization) {
hashCode = hashCode * 31 + [self.organization hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@ -4295,6 +4321,7 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
@property (strong) NSString* prefix;
@property (strong) NSString* suffix;
@property (strong) NSString* middleName;
@property (strong) NSString* displayName;
@end
@implementation OWSSignalServiceProtosDataMessageContactName
@ -4334,6 +4361,13 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
hasMiddleName_ = !!_value_;
}
@synthesize middleName;
- (BOOL) hasDisplayName {
return !!hasDisplayName_;
}
- (void) setHasDisplayName:(BOOL) _value_ {
hasDisplayName_ = !!_value_;
}
@synthesize displayName;
- (instancetype) init {
if ((self = [super init])) {
self.givenName = @"";
@ -4341,6 +4375,7 @@ static OWSSignalServiceProtosDataMessageContact* defaultOWSSignalServiceProtosDa
self.prefix = @"";
self.suffix = @"";
self.middleName = @"";
self.displayName = @"";
}
return self;
}
@ -4375,6 +4410,9 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
if (self.hasMiddleName) {
[output writeString:5 value:self.middleName];
}
if (self.hasDisplayName) {
[output writeString:6 value:self.displayName];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32) serializedSize {
@ -4399,6 +4437,9 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
if (self.hasMiddleName) {
size_ += computeStringSize(5, self.middleName);
}
if (self.hasDisplayName) {
size_ += computeStringSize(6, self.displayName);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
@ -4449,6 +4490,9 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
if (self.hasMiddleName) {
[output appendFormat:@"%@%@: %@\n", indent, @"middleName", self.middleName];
}
if (self.hasDisplayName) {
[output appendFormat:@"%@%@: %@\n", indent, @"displayName", self.displayName];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void) storeInDictionary:(NSMutableDictionary *)dictionary {
@ -4467,6 +4511,9 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
if (self.hasMiddleName) {
[dictionary setObject: self.middleName forKey: @"middleName"];
}
if (self.hasDisplayName) {
[dictionary setObject: self.displayName forKey: @"displayName"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL) isEqual:(id)other {
@ -4488,6 +4535,8 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
(!self.hasSuffix || [self.suffix isEqual:otherMessage.suffix]) &&
self.hasMiddleName == otherMessage.hasMiddleName &&
(!self.hasMiddleName || [self.middleName isEqual:otherMessage.middleName]) &&
self.hasDisplayName == otherMessage.hasDisplayName &&
(!self.hasDisplayName || [self.displayName isEqual:otherMessage.displayName]) &&
(self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger) hash {
@ -4507,6 +4556,9 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
if (self.hasMiddleName) {
hashCode = hashCode * 31 + [self.middleName hash];
}
if (self.hasDisplayName) {
hashCode = hashCode * 31 + [self.displayName hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@ -4565,6 +4617,9 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
if (other.hasMiddleName) {
[self setMiddleName:other.middleName];
}
if (other.hasDisplayName) {
[self setDisplayName:other.displayName];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
@ -4606,6 +4661,10 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
[self setMiddleName:[input readString]];
break;
}
case 50: {
[self setDisplayName:[input readString]];
break;
}
}
}
}
@ -4689,6 +4748,22 @@ static OWSSignalServiceProtosDataMessageContactName* defaultOWSSignalServiceProt
resultName.middleName = @"";
return self;
}
- (BOOL) hasDisplayName {
return resultName.hasDisplayName;
}
- (NSString*) displayName {
return resultName.displayName;
}
- (OWSSignalServiceProtosDataMessageContactNameBuilder*) setDisplayName:(NSString*) value {
resultName.hasDisplayName = YES;
resultName.displayName = value;
return self;
}
- (OWSSignalServiceProtosDataMessageContactNameBuilder*) clearDisplayName {
resultName.hasDisplayName = NO;
resultName.displayName = @"";
return self;
}
@end
@interface OWSSignalServiceProtosDataMessageContactPhone ()
@ -5987,6 +6062,290 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageContactPostalAddressType(
}
@end
@interface OWSSignalServiceProtosDataMessageContactAvatar ()
@property (strong) OWSSignalServiceProtosAttachmentPointer* avatar;
@property BOOL isProfile;
@end
@implementation OWSSignalServiceProtosDataMessageContactAvatar
- (BOOL) hasAvatar {
return !!hasAvatar_;
}
- (void) setHasAvatar:(BOOL) _value_ {
hasAvatar_ = !!_value_;
}
@synthesize avatar;
- (BOOL) hasIsProfile {
return !!hasIsProfile_;
}
- (void) setHasIsProfile:(BOOL) _value_ {
hasIsProfile_ = !!_value_;
}
- (BOOL) isProfile {
return !!isProfile_;
}
- (void) setIsProfile:(BOOL) _value_ {
isProfile_ = !!_value_;
}
- (instancetype) init {
if ((self = [super init])) {
self.avatar = [OWSSignalServiceProtosAttachmentPointer defaultInstance];
self.isProfile = NO;
}
return self;
}
static OWSSignalServiceProtosDataMessageContactAvatar* defaultOWSSignalServiceProtosDataMessageContactAvatarInstance = nil;
+ (void) initialize {
if (self == [OWSSignalServiceProtosDataMessageContactAvatar class]) {
defaultOWSSignalServiceProtosDataMessageContactAvatarInstance = [[OWSSignalServiceProtosDataMessageContactAvatar alloc] init];
}
}
+ (instancetype) defaultInstance {
return defaultOWSSignalServiceProtosDataMessageContactAvatarInstance;
}
- (instancetype) defaultInstance {
return defaultOWSSignalServiceProtosDataMessageContactAvatarInstance;
}
- (BOOL) isInitialized {
return YES;
}
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output {
if (self.hasAvatar) {
[output writeMessage:1 value:self.avatar];
}
if (self.hasIsProfile) {
[output writeBool:2 value:self.isProfile];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32) serializedSize {
__block SInt32 size_ = memoizedSerializedSize;
if (size_ != -1) {
return size_;
}
size_ = 0;
if (self.hasAvatar) {
size_ += computeMessageSize(1, self.avatar);
}
if (self.hasIsProfile) {
size_ += computeBoolSize(2, self.isProfile);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
}
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromData:(NSData*) data {
return (OWSSignalServiceProtosDataMessageContactAvatar*)[[[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFromData:data] build];
}
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSSignalServiceProtosDataMessageContactAvatar*)[[[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFromData:data extensionRegistry:extensionRegistry] build];
}
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromInputStream:(NSInputStream*) input {
return (OWSSignalServiceProtosDataMessageContactAvatar*)[[[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFromInputStream:input] build];
}
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSSignalServiceProtosDataMessageContactAvatar*)[[[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build];
}
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromCodedInputStream:(PBCodedInputStream*) input {
return (OWSSignalServiceProtosDataMessageContactAvatar*)[[[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFromCodedInputStream:input] build];
}
+ (OWSSignalServiceProtosDataMessageContactAvatar*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSSignalServiceProtosDataMessageContactAvatar*)[[[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build];
}
+ (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builder {
return [[OWSSignalServiceProtosDataMessageContactAvatarBuilder alloc] init];
}
+ (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builderWithPrototype:(OWSSignalServiceProtosDataMessageContactAvatar*) prototype {
return [[OWSSignalServiceProtosDataMessageContactAvatar builder] mergeFrom:prototype];
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builder {
return [OWSSignalServiceProtosDataMessageContactAvatar builder];
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) toBuilder {
return [OWSSignalServiceProtosDataMessageContactAvatar builderWithPrototype:self];
}
- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent {
if (self.hasAvatar) {
[output appendFormat:@"%@%@ {\n", indent, @"avatar"];
[self.avatar writeDescriptionTo:output
withIndent:[NSString stringWithFormat:@"%@ ", indent]];
[output appendFormat:@"%@}\n", indent];
}
if (self.hasIsProfile) {
[output appendFormat:@"%@%@: %@\n", indent, @"isProfile", [NSNumber numberWithBool:self.isProfile]];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void) storeInDictionary:(NSMutableDictionary *)dictionary {
if (self.hasAvatar) {
NSMutableDictionary *messageDictionary = [NSMutableDictionary dictionary];
[self.avatar storeInDictionary:messageDictionary];
[dictionary setObject:[NSDictionary dictionaryWithDictionary:messageDictionary] forKey:@"avatar"];
}
if (self.hasIsProfile) {
[dictionary setObject: [NSNumber numberWithBool:self.isProfile] forKey: @"isProfile"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL) isEqual:(id)other {
if (other == self) {
return YES;
}
if (![other isKindOfClass:[OWSSignalServiceProtosDataMessageContactAvatar class]]) {
return NO;
}
OWSSignalServiceProtosDataMessageContactAvatar *otherMessage = other;
return
self.hasAvatar == otherMessage.hasAvatar &&
(!self.hasAvatar || [self.avatar isEqual:otherMessage.avatar]) &&
self.hasIsProfile == otherMessage.hasIsProfile &&
(!self.hasIsProfile || self.isProfile == otherMessage.isProfile) &&
(self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger) hash {
__block NSUInteger hashCode = 7;
if (self.hasAvatar) {
hashCode = hashCode * 31 + [self.avatar hash];
}
if (self.hasIsProfile) {
hashCode = hashCode * 31 + [[NSNumber numberWithBool:self.isProfile] hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@end
@interface OWSSignalServiceProtosDataMessageContactAvatarBuilder()
@property (strong) OWSSignalServiceProtosDataMessageContactAvatar* resultAvatar;
@end
@implementation OWSSignalServiceProtosDataMessageContactAvatarBuilder
@synthesize resultAvatar;
- (instancetype) init {
if ((self = [super init])) {
self.resultAvatar = [[OWSSignalServiceProtosDataMessageContactAvatar alloc] init];
}
return self;
}
- (PBGeneratedMessage*) internalGetResult {
return resultAvatar;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clear {
self.resultAvatar = [[OWSSignalServiceProtosDataMessageContactAvatar alloc] init];
return self;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clone {
return [OWSSignalServiceProtosDataMessageContactAvatar builderWithPrototype:resultAvatar];
}
- (OWSSignalServiceProtosDataMessageContactAvatar*) defaultInstance {
return [OWSSignalServiceProtosDataMessageContactAvatar defaultInstance];
}
- (OWSSignalServiceProtosDataMessageContactAvatar*) build {
[self checkInitialized];
return [self buildPartial];
}
- (OWSSignalServiceProtosDataMessageContactAvatar*) buildPartial {
OWSSignalServiceProtosDataMessageContactAvatar* returnMe = resultAvatar;
self.resultAvatar = nil;
return returnMe;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeFrom:(OWSSignalServiceProtosDataMessageContactAvatar*) other {
if (other == [OWSSignalServiceProtosDataMessageContactAvatar defaultInstance]) {
return self;
}
if (other.hasAvatar) {
[self mergeAvatar:other.avatar];
}
if (other.hasIsProfile) {
[self setIsProfile:other.isProfile];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input {
return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]];
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields];
while (YES) {
SInt32 tag = [input readTag];
switch (tag) {
case 0:
[self setUnknownFields:[unknownFields build]];
return self;
default: {
if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) {
[self setUnknownFields:[unknownFields build]];
return self;
}
break;
}
case 10: {
OWSSignalServiceProtosAttachmentPointerBuilder* subBuilder = [OWSSignalServiceProtosAttachmentPointer builder];
if (self.hasAvatar) {
[subBuilder mergeFrom:self.avatar];
}
[input readMessage:subBuilder extensionRegistry:extensionRegistry];
[self setAvatar:[subBuilder buildPartial]];
break;
}
case 16: {
[self setIsProfile:[input readBool]];
break;
}
}
}
}
- (BOOL) hasAvatar {
return resultAvatar.hasAvatar;
}
- (OWSSignalServiceProtosAttachmentPointer*) avatar {
return resultAvatar.avatar;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) setAvatar:(OWSSignalServiceProtosAttachmentPointer*) value {
resultAvatar.hasAvatar = YES;
resultAvatar.avatar = value;
return self;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) setAvatarBuilder:(OWSSignalServiceProtosAttachmentPointerBuilder*) builderForValue {
return [self setAvatar:[builderForValue build]];
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) mergeAvatar:(OWSSignalServiceProtosAttachmentPointer*) value {
if (resultAvatar.hasAvatar &&
resultAvatar.avatar != [OWSSignalServiceProtosAttachmentPointer defaultInstance]) {
resultAvatar.avatar =
[[[OWSSignalServiceProtosAttachmentPointer builderWithPrototype:resultAvatar.avatar] mergeFrom:value] buildPartial];
} else {
resultAvatar.avatar = value;
}
resultAvatar.hasAvatar = YES;
return self;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clearAvatar {
resultAvatar.hasAvatar = NO;
resultAvatar.avatar = [OWSSignalServiceProtosAttachmentPointer defaultInstance];
return self;
}
- (BOOL) hasIsProfile {
return resultAvatar.hasIsProfile;
}
- (BOOL) isProfile {
return resultAvatar.isProfile;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) setIsProfile:(BOOL) value {
resultAvatar.hasIsProfile = YES;
resultAvatar.isProfile = value;
return self;
}
- (OWSSignalServiceProtosDataMessageContactAvatarBuilder*) clearIsProfile {
resultAvatar.hasIsProfile = NO;
resultAvatar.isProfile = NO;
return self;
}
@end
@interface OWSSignalServiceProtosDataMessageContactBuilder()
@property (strong) OWSSignalServiceProtosDataMessageContact* resultContact;
@end
@ -6052,6 +6411,9 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageContactPostalAddressType(
if (other.hasAvatar) {
[self mergeAvatar:other.avatar];
}
if (other.hasOrganization) {
[self setOrganization:other.organization];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
@ -6101,7 +6463,7 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageContactPostalAddressType(
break;
}
case 50: {
OWSSignalServiceProtosAttachmentPointerBuilder* subBuilder = [OWSSignalServiceProtosAttachmentPointer builder];
OWSSignalServiceProtosDataMessageContactAvatarBuilder* subBuilder = [OWSSignalServiceProtosDataMessageContactAvatar builder];
if (self.hasAvatar) {
[subBuilder mergeFrom:self.avatar];
}
@ -6109,6 +6471,10 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageContactPostalAddressType(
[self setAvatar:[subBuilder buildPartial]];
break;
}
case 58: {
[self setOrganization:[input readString]];
break;
}
}
}
}
@ -6208,22 +6574,22 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageContactPostalAddressType(
- (BOOL) hasAvatar {
return resultContact.hasAvatar;
}
- (OWSSignalServiceProtosAttachmentPointer*) avatar {
- (OWSSignalServiceProtosDataMessageContactAvatar*) avatar {
return resultContact.avatar;
}
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatar:(OWSSignalServiceProtosAttachmentPointer*) value {
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatar:(OWSSignalServiceProtosDataMessageContactAvatar*) value {
resultContact.hasAvatar = YES;
resultContact.avatar = value;
return self;
}
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatarBuilder:(OWSSignalServiceProtosAttachmentPointerBuilder*) builderForValue {
- (OWSSignalServiceProtosDataMessageContactBuilder*) setAvatarBuilder:(OWSSignalServiceProtosDataMessageContactAvatarBuilder*) builderForValue {
return [self setAvatar:[builderForValue build]];
}
- (OWSSignalServiceProtosDataMessageContactBuilder*) mergeAvatar:(OWSSignalServiceProtosAttachmentPointer*) value {
- (OWSSignalServiceProtosDataMessageContactBuilder*) mergeAvatar:(OWSSignalServiceProtosDataMessageContactAvatar*) value {
if (resultContact.hasAvatar &&
resultContact.avatar != [OWSSignalServiceProtosAttachmentPointer defaultInstance]) {
resultContact.avatar != [OWSSignalServiceProtosDataMessageContactAvatar defaultInstance]) {
resultContact.avatar =
[[[OWSSignalServiceProtosAttachmentPointer builderWithPrototype:resultContact.avatar] mergeFrom:value] buildPartial];
[[[OWSSignalServiceProtosDataMessageContactAvatar builderWithPrototype:resultContact.avatar] mergeFrom:value] buildPartial];
} else {
resultContact.avatar = value;
}
@ -6232,7 +6598,23 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageContactPostalAddressType(
}
- (OWSSignalServiceProtosDataMessageContactBuilder*) clearAvatar {
resultContact.hasAvatar = NO;
resultContact.avatar = [OWSSignalServiceProtosAttachmentPointer defaultInstance];
resultContact.avatar = [OWSSignalServiceProtosDataMessageContactAvatar defaultInstance];
return self;
}
- (BOOL) hasOrganization {
return resultContact.hasOrganization;
}
- (NSString*) organization {
return resultContact.organization;
}
- (OWSSignalServiceProtosDataMessageContactBuilder*) setOrganization:(NSString*) value {
resultContact.hasOrganization = YES;
resultContact.organization = value;
return self;
}
- (OWSSignalServiceProtosDataMessageContactBuilder*) clearOrganization {
resultContact.hasOrganization = NO;
resultContact.organization = @"";
return self;
}
@end