Sync Groups with Desktop

// FREEBIE
pull/1/head
Michael Kirk 9 years ago
parent 36d3691c74
commit 69da0b3c25

@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
[sentBuilder setDestination:self.message.recipientIdentifier]; [sentBuilder setDestination:self.message.recipientIdentifier];
[sentBuilder setMessage:[self.message buildDataMessage]]; [sentBuilder setMessage:[self.message buildDataMessage]];
[syncMessageBuilder setSent:[sentBuilder build]]; [syncMessageBuilder setSentBuilder:sentBuilder];
return [syncMessageBuilder build]; return [syncMessageBuilder build];
} }

@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage - (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{ {
NSAssert(NO, @"buildSyncMessage must be overridden in suclass"); NSAssert(NO, @"buildSyncMessage must be overridden in subclass");
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new]; OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
return [syncMessageBuilder build]; return [syncMessageBuilder build];
@ -28,7 +28,6 @@ NS_ASSUME_NONNULL_BEGIN
return [[contentBuilder build] data]; return [[contentBuilder build] data];
} }
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -31,36 +31,18 @@ NS_ASSUME_NONNULL_BEGIN
return self; return self;
} }
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
// no-op
// There's no need to save this message, since it's not displayed to the user.
// Furthermore if we did save it, we probably don't want to save the conctactsManager property.
}
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage - (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{ {
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new]; OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
OWSSignalServiceProtosSyncMessageContactsBuilder *contactsBuilder =
[OWSSignalServiceProtosSyncMessageContactsBuilder new];
[syncMessageBuilder setContactsBuilder:contactsBuilder];
if (self.attachmentIds.count != 1) { if (self.attachmentIds.count != 1) {
DDLogError(@"expected sync contact message to have exactly one attachment, but found %lu", DDLogError(@"expected sync contact message to have exactly one attachment, but found %lu",
(unsigned long)self.attachmentIds.count); (unsigned long)self.attachmentIds.count);
} }
TSAttachment *attachment = [TSAttachmentStream fetchObjectWithUniqueID:self.attachmentIds[0]]; [contactsBuilder setBlobBuilder:[self attachmentBuilderForAttachmentId:self.attachmentIds[0]]];
OWSSignalServiceProtosAttachmentPointerBuilder *attachmentBuilder =
[OWSSignalServiceProtosAttachmentPointerBuilder new];
[attachmentBuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentBuilder setContentType:attachment.contentType];
[attachmentBuilder setKey:attachment.encryptionKey];
OWSSignalServiceProtosSyncMessageContactsBuilder *contactsBuilder =
[OWSSignalServiceProtosSyncMessageContactsBuilder new];
[contactsBuilder setBlobBuilder:attachmentBuilder];
[syncMessageBuilder setContacts:[contactsBuilder build]];
return [syncMessageBuilder build]; return [syncMessageBuilder build];
} }
@ -88,9 +70,8 @@ NS_ASSUME_NONNULL_BEGIN
[avatarBuilder setContentType:@"image/png"]; [avatarBuilder setContentType:@"image/png"];
avatarPng = UIImagePNGRepresentation(contact.image); avatarPng = UIImagePNGRepresentation(contact.image);
// TODO check datasize and safely cast to int
[avatarBuilder setLength:(uint32_t)avatarPng.length]; [avatarBuilder setLength:(uint32_t)avatarPng.length];
[contactBuilder setAvatar:[avatarBuilder build]]; [contactBuilder setAvatarBuilder:avatarBuilder];
} }
NSData *contactData = [[contactBuilder build] data]; NSData *contactData = [[contactBuilder build] data];

@ -1,5 +1,7 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved. // Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSOutgoingSyncMessage.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface OWSSyncGroupsMessage : OWSOutgoingSyncMessage @interface OWSSyncGroupsMessage : OWSOutgoingSyncMessage

@ -1,12 +1,21 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved. // Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSSyncGroupsMessage.h" #import "OWSSyncGroupsMessage.h"
#import "NSDate+millisecondTimeStamp.h"
#import "OWSSignalServiceProtos.pb.h" #import "OWSSignalServiceProtos.pb.h"
#import "TSAttachment.h"
#import "TSGroupModel.h"
#import "TSGroupThread.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@implementation OWSSyncGroupsMessage @implementation OWSSyncGroupsMessage
- (instancetype)init
{
return [super initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:nil messageBody:nil attachmentIds:@[]];
}
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction - (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
// no-op // no-op
@ -18,25 +27,15 @@ NS_ASSUME_NONNULL_BEGIN
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage - (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{ {
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new]; OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
OWSSignalServiceProtosSyncMessageGroupsBuilder *groupsBuilder =
[OWSSignalServiceProtosSyncMessageGroupsBuilder new];
[syncMessageBuilder setGroupsBuilder:groupsBuilder];
if (self.attachmentIds.count != 1) { if (self.attachmentIds.count != 1) {
DDLogError(@"expected sync contact message to have exactly one attachment, but found %lu", DDLogError(@"expected sync groups message to have exactly one attachment, but found %lu",
(unsigned long)self.attachmentIds.count); (unsigned long)self.attachmentIds.count);
} }
TSAttachment *attachment = [TSAttachmentStream fetchObjectWithUniqueID:self.attachmentIds[0]]; [groupsBuilder setBlobBuilder:[self attachmentBuilderForAttachmentId:self.attachmentIds[0]]];
OWSSignalServiceProtosAttachmentPointerBuilder *attachmentBuilder =
[OWSSignalServiceProtosAttachmentPointerBuilder new];
[attachmentBuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentBuilder setContentType:attachment.contentType];
[attachmentBuilder setKey:attachment.encryptionKey];
OWSSignalServiceProtosSyncMessageContactsBuilder *contactsBuilder =
[OWSSignalServiceProtosSyncMessageContactsBuilder new];
[contactsBuilder setBlobBuilder:attachmentBuilder];
[syncMessageBuilder setContacts:[contactsBuilder build]];
return [syncMessageBuilder build]; return [syncMessageBuilder build];
} }
@ -50,35 +49,39 @@ NS_ASSUME_NONNULL_BEGIN
[fileOutputStream open]; [fileOutputStream open];
PBCodedOutputStream *outputStream = [PBCodedOutputStream streamWithOutputStream:fileOutputStream]; PBCodedOutputStream *outputStream = [PBCodedOutputStream streamWithOutputStream:fileOutputStream];
DDLogInfo(@"Writing contacts data to %@", fileURL); DDLogInfo(@"Writing groups data to %@", fileURL);
for (Contact *contact in self.contactsManager.signalContacts) { [TSGroupThread enumerateCollectionObjectsUsingBlock:^(id obj, BOOL *stop) {
OWSSignalServiceProtosContactDetailsBuilder *contactBuilder = [OWSSignalServiceProtosContactDetailsBuilder new]; if (![obj isKindOfClass:[TSGroupThread class]]) {
DDLogError(@"Unexpected class in group collection: %@", obj);
[contactBuilder setName:contact.fullName]; return;
[contactBuilder setNumber:contact.textSecureIdentifiers.firstObject]; }
TSGroupModel *group = ((TSGroupThread *)obj).groupModel;
OWSSignalServiceProtosGroupDetailsBuilder *groupBuilder = [OWSSignalServiceProtosGroupDetailsBuilder new];
[groupBuilder setId:group.groupId];
[groupBuilder setName:group.groupName];
[groupBuilder setMembersArray:group.groupMemberIds];
NSData *avatarPng; NSData *avatarPng;
if (contact.image) { if (group.groupImage) {
OWSSignalServiceProtosContactDetailsAvatarBuilder *avatarBuilder = OWSSignalServiceProtosGroupDetailsAvatarBuilder *avatarBuilder =
[OWSSignalServiceProtosContactDetailsAvatarBuilder new]; [OWSSignalServiceProtosGroupDetailsAvatarBuilder new];
[avatarBuilder setContentType:@"image/png"]; [avatarBuilder setContentType:@"image/png"];
avatarPng = UIImagePNGRepresentation(contact.image); avatarPng = UIImagePNGRepresentation(group.groupImage);
// TODO check datasize and safely cast to int
[avatarBuilder setLength:(uint32_t)avatarPng.length]; [avatarBuilder setLength:(uint32_t)avatarPng.length];
[contactBuilder setAvatar:[avatarBuilder build]]; [groupBuilder setAvatarBuilder:avatarBuilder];
} }
NSData *contactData = [[contactBuilder build] data]; NSData *groupData = [[groupBuilder build] data];
uint32_t groupDataLength = (uint32_t)groupData.length;
[outputStream writeRawVarint32:groupDataLength];
[outputStream writeRawData:groupData];
uint32_t contactDataLength = (uint32_t)contactData.length; if (avatarPng) {
[outputStream writeRawVarint32:contactDataLength];
[outputStream writeRawData:contactData];
if (contact.image) {
[outputStream writeRawData:avatarPng]; [outputStream writeRawData:avatarPng];
} }
} }];
[outputStream flush]; [outputStream flush];
[fileOutputStream close]; [fileOutputStream close];

@ -5,7 +5,7 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class OWSSignalServiceProtosDataMessage; @class OWSSignalServiceProtosAttachmentPointerBuilder;
@interface TSOutgoingMessage : TSMessage @interface TSOutgoingMessage : TSMessage
@ -36,6 +36,15 @@ typedef NS_ENUM(NSInteger, TSOutgoingMessageState) {
*/ */
- (BOOL)shouldSyncTranscript; - (BOOL)shouldSyncTranscript;
/**
* @param attachmentStream
* Containing the meta data used when populating the attachment proto
*
* @return
* An attachment builder suitable for including in various container protobuf builders
*/
- (OWSSignalServiceProtosAttachmentPointerBuilder *)attachmentBuilderForAttachmentId:(NSString *)attachmentId;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSSignalServiceProtosDataMessageBuilder *builder = [OWSSignalServiceProtosDataMessageBuilder new]; OWSSignalServiceProtosDataMessageBuilder *builder = [OWSSignalServiceProtosDataMessageBuilder new];
[builder setBody:self.body]; [builder setBody:self.body];
BOOL processAttachments = YES; BOOL attachmentWasGroupAvatar = NO;
if ([thread isKindOfClass:[TSGroupThread class]]) { if ([thread isKindOfClass:[TSGroupThread class]]) {
TSGroupThread *gThread = (TSGroupThread *)thread; TSGroupThread *gThread = (TSGroupThread *)thread;
OWSSignalServiceProtosGroupContextBuilder *groupBuilder = [OWSSignalServiceProtosGroupContextBuilder new]; OWSSignalServiceProtosGroupContextBuilder *groupBuilder = [OWSSignalServiceProtosGroupContextBuilder new];
@ -56,19 +56,11 @@ NS_ASSUME_NONNULL_BEGIN
break; break;
case TSGroupMessageUpdate: case TSGroupMessageUpdate:
case TSGroupMessageNew: { case TSGroupMessageNew: {
if (gThread.groupModel.groupImage != nil && [self.attachmentIds count] == 1) { if (gThread.groupModel.groupImage != nil && self.attachmentIds.count == 1) {
id dbObject = [TSAttachmentStream fetchObjectWithUniqueID:self.attachmentIds[0]]; attachmentWasGroupAvatar = YES;
if ([dbObject isKindOfClass:[TSAttachmentStream class]]) { [groupBuilder setAvatarBuilder:[self attachmentBuilderForAttachmentId:self.attachmentIds[0]]];
TSAttachmentStream *attachment = (TSAttachmentStream *)dbObject;
OWSSignalServiceProtosAttachmentPointerBuilder *attachmentbuilder =
[OWSSignalServiceProtosAttachmentPointerBuilder new];
[attachmentbuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentbuilder setContentType:attachment.contentType];
[attachmentbuilder setKey:attachment.encryptionKey];
[groupBuilder setAvatar:[attachmentbuilder build]];
processAttachments = NO;
}
} }
[groupBuilder setMembersArray:gThread.groupModel.groupMemberIds]; [groupBuilder setMembersArray:gThread.groupModel.groupMemberIds];
[groupBuilder setName:gThread.groupModel.groupName]; [groupBuilder setName:gThread.groupModel.groupName];
[groupBuilder setType:OWSSignalServiceProtosGroupContextTypeUpdate]; [groupBuilder setType:OWSSignalServiceProtosGroupContextTypeUpdate];
@ -81,22 +73,12 @@ NS_ASSUME_NONNULL_BEGIN
[groupBuilder setId:gThread.groupModel.groupId]; [groupBuilder setId:gThread.groupModel.groupId];
[builder setGroup:groupBuilder.build]; [builder setGroup:groupBuilder.build];
} }
if (processAttachments) { if (!attachmentWasGroupAvatar) {
NSMutableArray *attachments = [NSMutableArray new]; NSMutableArray *attachments = [NSMutableArray new];
for (NSString *attachmentId in self.attachmentIds) { for (NSString *attachmentId in self.attachmentIds) {
id dbObject = [TSAttachmentStream fetchObjectWithUniqueID:attachmentId]; OWSSignalServiceProtosAttachmentPointerBuilder *attachmentBuilder =
[self attachmentBuilderForAttachmentId:attachmentId];
if ([dbObject isKindOfClass:[TSAttachmentStream class]]) { [attachments addObject:[attachmentBuilder build]];
TSAttachmentStream *attachment = (TSAttachmentStream *)dbObject;
OWSSignalServiceProtosAttachmentPointerBuilder *attachmentbuilder =
[OWSSignalServiceProtosAttachmentPointerBuilder new];
[attachmentbuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentbuilder setContentType:attachment.contentType];
[attachmentbuilder setKey:attachment.encryptionKey];
[attachments addObject:[attachmentbuilder build]];
}
} }
[builder setAttachmentsArray:attachments]; [builder setAttachmentsArray:attachments];
} }
@ -113,6 +95,23 @@ NS_ASSUME_NONNULL_BEGIN
return !self.hasSyncedTranscript; return !self.hasSyncedTranscript;
} }
- (OWSSignalServiceProtosAttachmentPointerBuilder *)attachmentBuilderForAttachmentId:(NSString *)attachmentId
{
TSAttachment *attachment = [TSAttachmentStream fetchObjectWithUniqueID:attachmentId];
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
DDLogError(@"Unexpected type for attachment builder: %@", attachment);
return nil;
}
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment;
OWSSignalServiceProtosAttachmentPointerBuilder *builder = [OWSSignalServiceProtosAttachmentPointerBuilder new];
[builder setId:[attachmentStream.identifier unsignedLongLongValue]];
[builder setContentType:attachmentStream.contentType];
[builder setKey:attachmentStream.encryptionKey];
return builder;
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

Loading…
Cancel
Save