Create & access groups more carefully.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 87c5a6c5fb
commit 380ed0f82b

@ -1495,15 +1495,26 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
}]]; }]];
} }
[subtitleText if (self.userLeftGroup) {
appendAttributedString:[[NSAttributedString alloc] [subtitleText
initWithString:NSLocalizedString(@"MESSAGES_VIEW_TITLE_SUBTITLE", appendAttributedString:[[NSAttributedString alloc]
@"The subtitle for the messages view title indicates that the " initWithString:NSLocalizedString(@"GROUP_YOU_LEFT", @"")
@"title can be tapped to access settings for this conversation.") attributes:@{
attributes:@{ NSFontAttributeName : [UIFont ows_regularFontWithSize:9.f],
NSFontAttributeName : [UIFont ows_regularFontWithSize:9.f], NSForegroundColorAttributeName : [UIColor colorWithWhite:0.9f alpha:1.f],
NSForegroundColorAttributeName : [UIColor colorWithWhite:0.9f alpha:1.f], }]];
}]]; } else {
[subtitleText appendAttributedString:
[[NSAttributedString alloc]
initWithString:NSLocalizedString(@"MESSAGES_VIEW_TITLE_SUBTITLE",
@"The subtitle for the messages view title indicates that the "
@"title can be tapped to access settings for this conversation.")
attributes:@{
NSFontAttributeName : [UIFont ows_regularFontWithSize:9.f],
NSForegroundColorAttributeName : [UIColor colorWithWhite:0.9f alpha:1.f],
}]];
}
self.navigationBarSubtitleLabel.attributedText = subtitleText; self.navigationBarSubtitleLabel.attributedText = subtitleText;
[self.navigationBarSubtitleLabel sizeToFit]; [self.navigationBarSubtitleLabel sizeToFit];
} }
@ -3649,7 +3660,13 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
TSGroupThread *gThread = (TSGroupThread *)self.thread; TSGroupThread *gThread = (TSGroupThread *)self.thread;
if (gThread.groupModel) { if (gThread.groupModel) {
self.thread = [TSGroupThread threadWithGroupModel:gThread.groupModel transaction:transaction]; TSGroupThread *_Nullable updatedThread =
[TSGroupThread threadWithGroupId:gThread.groupModel.groupId transaction:transaction];
if (updatedThread) {
self.thread = updatedThread;
} else {
OWSFail(@"%@ Could not reload thread.", self.tag);
}
} }
}]; }];
[self setNavigationTitle]; [self setNavigationTitle];

@ -18,11 +18,11 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel + (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel
transaction:(YapDatabaseReadWriteTransaction *)transaction; transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (instancetype)getOrCreateThreadWithGroupIdData:(NSData *)groupId; + (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId;
+ (instancetype)getOrCreateThreadWithGroupIdData:(NSData *)groupId + (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId
transaction:(YapDatabaseReadWriteTransaction *)transaction; transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (instancetype)threadWithGroupModel:(TSGroupModel *)groupModel transaction:(YapDatabaseReadTransaction *)transaction; + (nullable instancetype)threadWithGroupId:(NSData *)groupId transaction:(YapDatabaseReadTransaction *)transaction;
+ (NSString *)threadIdFromGroupId:(NSData *)groupId; + (NSString *)threadIdFromGroupId:(NSData *)groupId;

@ -36,11 +36,19 @@ NS_ASSUME_NONNULL_BEGIN
return self; return self;
} }
- (instancetype)initWithGroupIdData:(NSData *)groupId - (instancetype)initWithGroupId:(NSData *)groupId
{ {
OWSAssert(groupId.length > 0); OWSAssert(groupId.length > 0);
TSGroupModel *groupModel = [[TSGroupModel alloc] initWithTitle:nil memberIds:nil image:nil groupId:groupId]; NSString *localNumber = [TSAccountManager localNumber];
OWSAssert(localNumber.length > 0);
TSGroupModel *groupModel = [[TSGroupModel alloc] initWithTitle:nil
memberIds:[@[
localNumber,
] mutableCopy]
image:nil
groupId:groupId];
self = [self initWithGroupModel:groupModel]; self = [self initWithGroupModel:groupModel];
if (!self) { if (!self) {
@ -50,35 +58,34 @@ NS_ASSUME_NONNULL_BEGIN
return self; return self;
} }
+ (instancetype)threadWithGroupModel:(TSGroupModel *)groupModel transaction:(YapDatabaseReadTransaction *)transaction + (nullable instancetype)threadWithGroupId:(NSData *)groupId transaction:(YapDatabaseReadTransaction *)transaction
{ {
OWSAssert(groupModel); OWSAssert(groupId.length > 0);
OWSAssert(groupModel.groupId.length > 0);
return [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupModel.groupId] transaction:transaction]; return [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupId] transaction:transaction];
} }
+ (instancetype)getOrCreateThreadWithGroupIdData:(NSData *)groupId + (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
OWSAssert(groupId.length > 0); OWSAssert(groupId.length > 0);
OWSAssert(transaction); OWSAssert(transaction);
TSGroupThread *thread = [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupId] transaction:transaction]; TSGroupThread *thread = [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupId] transaction:transaction];
if (!thread) { if (!thread) {
thread = [[self alloc] initWithGroupIdData:groupId]; thread = [[self alloc] initWithGroupId:groupId];
[thread saveWithTransaction:transaction]; [thread saveWithTransaction:transaction];
} }
return thread; return thread;
} }
+ (instancetype)getOrCreateThreadWithGroupIdData:(NSData *)groupId + (instancetype)getOrCreateThreadWithGroupId:(NSData *)groupId
{ {
OWSAssert(groupId.length > 0); OWSAssert(groupId.length > 0);
__block TSGroupThread *thread; __block TSGroupThread *thread;
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithGroupIdData:groupId transaction:transaction]; thread = [self getOrCreateThreadWithGroupId:groupId transaction:transaction];
}]; }];
return thread; return thread;
} }

@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
- (TSThread *)threadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction - (TSThread *)threadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
if (self.dataMessage.hasGroup) { if (self.dataMessage.hasGroup) {
return [TSGroupThread getOrCreateThreadWithGroupIdData:self.dataMessage.group.id transaction:transaction]; return [TSGroupThread getOrCreateThreadWithGroupId:self.dataMessage.group.id transaction:transaction];
} else { } else {
return [TSContactThread getOrCreateThreadWithContactId:self.recipientId transaction:transaction]; return [TSContactThread getOrCreateThreadWithContactId:self.recipientId transaction:transaction];
} }

@ -307,40 +307,22 @@ NS_ASSUME_NONNULL_BEGIN
} }
if (dataMessage.hasGroup) { if (dataMessage.hasGroup) {
TSGroupModel *emptyModelToFillOutId = TSGroupThread *_Nullable gThread =
[[TSGroupModel alloc] initWithTitle:nil memberIds:nil image:nil groupId:dataMessage.group.id]; [TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
TSGroupThread *gThread = [TSGroupThread threadWithGroupModel:emptyModelToFillOutId transaction:transaction];
BOOL unknownGroup = NO; BOOL unknownGroup = NO;
if (gThread == nil && dataMessage.group.type != OWSSignalServiceProtosGroupContextTypeUpdate) { if (gThread == nil && dataMessage.group.type != OWSSignalServiceProtosGroupContextTypeUpdate) {
unknownGroup = YES; unknownGroup = YES;
} }
if (unknownGroup) { if (unknownGroup) {
if (dataMessage.group.type == OWSSignalServiceProtosGroupContextTypeRequestInfo) { if (dataMessage.group.type == OWSSignalServiceProtosGroupContextTypeRequestInfo) {
DDLogInfo( DDLogInfo(@"%@ Ignoring group info request for unknown group from: %@", self.tag, envelope.source);
@"%@ Ignoring group info request for group I don't know about from: %@", self.tag, envelope.source); return;
} else if (dataMessage.group.type == OWSSignalServiceProtosGroupContextTypeQuit) {
DDLogInfo(@"%@ Ignoring group quit for unknown group from: %@", self.tag, envelope.source);
return; return;
} }
// FIXME: https://github.com/WhisperSystems/Signal-iOS/issues/1340 [self sendGroupInfoRequest:dataMessage.group.id envelope:envelope transaction:transaction];
DDLogInfo(@"%@ Received message from group that I left or don't know about from: %@",
self.tag,
envelopeAddress(envelope));
NSString *recipientId = envelope.source;
TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
NSData *groupId = dataMessage.group.id;
OWSAssert(groupId);
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread groupId:groupId];
[self.messageSender sendMessage:syncGroupsRequestMessage
success:^{
DDLogWarn(@"%@ Successfully sent Request Group Info message.", self.tag);
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send Request Group Info message with error: %@", self.tag, error);
}];
return; return;
} }
} }
@ -355,6 +337,7 @@ NS_ASSUME_NONNULL_BEGIN
[self handleReceivedMediaWithEnvelope:envelope dataMessage:dataMessage transaction:transaction]; [self handleReceivedMediaWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
} else { } else {
[self handleReceivedTextMessageWithEnvelope:envelope dataMessage:dataMessage transaction:transaction]; [self handleReceivedTextMessageWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
if ([self isDataMessageGroupAvatarUpdate:dataMessage]) { if ([self isDataMessageGroupAvatarUpdate:dataMessage]) {
DDLogVerbose(@"%@ Data message had group avatar attachment", self.tag); DDLogVerbose(@"%@ Data message had group avatar attachment", self.tag);
[self handleReceivedGroupAvatarUpdateWithEnvelope:envelope dataMessage:dataMessage transaction:transaction]; [self handleReceivedGroupAvatarUpdateWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
@ -362,6 +345,36 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (void)sendGroupInfoRequest:(NSData *)groupId
envelope:(OWSSignalServiceProtosEnvelope *)envelope
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(groupId.length > 0);
OWSAssert(envelope);
OWSAssert(transaction);
if (groupId.length < 1) {
return;
}
// FIXME: https://github.com/WhisperSystems/Signal-iOS/issues/1340
DDLogInfo(@"%@ Sending group info request: %@", self.tag, envelopeAddress(envelope));
NSString *recipientId = envelope.source;
TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread groupId:groupId];
[self.messageSender sendMessage:syncGroupsRequestMessage
success:^{
DDLogWarn(@"%@ Successfully sent Request Group Info message.", self.tag);
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send Request Group Info message with error: %@", self.tag, error);
}];
}
- (id<ProfileManagerProtocol>)profileManager - (id<ProfileManagerProtocol>)profileManager
{ {
return [TextSecureKitEnv sharedEnv].profileManager; return [TextSecureKitEnv sharedEnv].profileManager;
@ -445,8 +458,13 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(dataMessage); OWSAssert(dataMessage);
OWSAssert(transaction); OWSAssert(transaction);
TSGroupThread *groupThread = TSGroupThread *_Nullable groupThread =
[TSGroupThread getOrCreateThreadWithGroupIdData:dataMessage.group.id transaction:transaction]; [TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
if (!groupThread) {
[self sendGroupInfoRequest:dataMessage.group.id envelope:envelope transaction:transaction];
return;
}
OWSAssert(groupThread); OWSAssert(groupThread);
OWSAttachmentsProcessor *attachmentsProcessor = OWSAttachmentsProcessor *attachmentsProcessor =
[[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:@[ dataMessage.group.avatar ] [[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:@[ dataMessage.group.avatar ]
@ -482,8 +500,12 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(dataMessage); OWSAssert(dataMessage);
OWSAssert(transaction); OWSAssert(transaction);
TSThread *thread = [self threadForEnvelope:envelope dataMessage:dataMessage transaction:transaction]; TSThread *_Nullable thread = [self threadForEnvelope:envelope dataMessage:dataMessage transaction:transaction];
OWSAssert(thread); if (!thread) {
OWSFail(@"%@ ignoring media message for unknown group.", self.tag);
return;
}
OWSAttachmentsProcessor *attachmentsProcessor = OWSAttachmentsProcessor *attachmentsProcessor =
[[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:dataMessage.attachments [[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:dataMessage.attachments
timestamp:envelope.timestamp timestamp:envelope.timestamp
@ -559,10 +581,16 @@ NS_ASSUME_NONNULL_BEGIN
if ([self isDataMessageGroupAvatarUpdate:syncMessage.sent.message]) { if ([self isDataMessageGroupAvatarUpdate:syncMessage.sent.message]) {
[recordJob runWithAttachmentHandler:^(TSAttachmentStream *attachmentStream) { [recordJob runWithAttachmentHandler:^(TSAttachmentStream *attachmentStream) {
TSGroupThread *groupThread = [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[TSGroupThread getOrCreateThreadWithGroupIdData:syncMessage.sent.message.group.id TSGroupThread *_Nullable groupThread =
transaction:transaction]; [TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
[groupThread updateAvatarWithAttachmentStream:attachmentStream]; if (!groupThread) {
[self sendGroupInfoRequest:dataMessage.group.id envelope:envelope transaction:transaction];
return;
}
[groupThread updateAvatarWithAttachmentStream:attachmentStream transaction:transaction];
}];
} }
transaction:transaction]; transaction:transaction];
} else { } else {
@ -664,7 +692,11 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(dataMessage); OWSAssert(dataMessage);
OWSAssert(transaction); OWSAssert(transaction);
TSThread *thread = [self threadForEnvelope:envelope dataMessage:dataMessage transaction:transaction]; TSThread *_Nullable thread = [self threadForEnvelope:envelope dataMessage:dataMessage transaction:transaction];
if (!thread) {
OWSFail(@"%@ ignoring expiring messages update for unknown group.", self.tag);
return;
}
OWSDisappearingMessagesConfiguration *disappearingMessagesConfiguration; OWSDisappearingMessagesConfiguration *disappearingMessagesConfiguration;
if (dataMessage.hasExpireTimer && dataMessage.expireTimer > 0) { if (dataMessage.hasExpireTimer && dataMessage.expireTimer > 0) {
@ -776,9 +808,7 @@ NS_ASSUME_NONNULL_BEGIN
DDLogWarn(@"%@ Received 'Request Group Info' message for group: %@ from: %@", self.tag, groupId, envelope.source); DDLogWarn(@"%@ Received 'Request Group Info' message for group: %@ from: %@", self.tag, groupId, envelope.source);
TSGroupModel *emptyModelToFillOutId = TSGroupThread *_Nullable gThread = [TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
[[TSGroupModel alloc] initWithTitle:nil memberIds:nil image:nil groupId:dataMessage.group.id];
TSGroupThread *gThread = [TSGroupThread threadWithGroupModel:emptyModelToFillOutId transaction:transaction];
if (!gThread) { if (!gThread) {
DDLogWarn(@"%@ Unknown group: %@", self.tag, groupId); DDLogWarn(@"%@ Unknown group: %@", self.tag, groupId);
return; return;
@ -828,101 +858,131 @@ NS_ASSUME_NONNULL_BEGIN
return nil; return nil;
} }
if (groupId) { if (groupId.length > 0) {
NSMutableArray *uniqueMemberIds = [[[NSSet setWithArray:dataMessage.group.members] allObjects] mutableCopy]; NSMutableSet *newMemberIds = [NSMutableSet setWithArray:dataMessage.group.members];
TSGroupModel *model = [[TSGroupModel alloc] initWithTitle:dataMessage.group.name
memberIds:uniqueMemberIds // Group messages create the group if it doesn't already exist.
image:nil //
groupId:dataMessage.group.id]; // We distinguish between the old group state (if any) and the new group state.
TSGroupThread *gThread = [TSGroupThread getOrCreateThreadWithGroupModel:model transaction:transaction]; TSGroupThread *_Nullable oldGroupThread = [TSGroupThread threadWithGroupId:groupId transaction:transaction];
if (oldGroupThread) {
// Don't trust other clients; ensure all known group members leave the group
// _unless_ it is a "quit" message in which case we should explicitly remove
// just the quiting member below.
[newMemberIds addObjectsFromArray:oldGroupThread.groupModel.groupMemberIds];
}
switch (dataMessage.group.type) { switch (dataMessage.group.type) {
case OWSSignalServiceProtosGroupContextTypeUpdate: { case OWSSignalServiceProtosGroupContextTypeUpdate: {
NSString *updateGroupInfo = // Ensures that the thread exists but doesn't update it.
[gThread.groupModel getInfoStringAboutUpdateTo:model contactsManager:self.contactsManager]; TSGroupThread *newGroupThread =
gThread.groupModel = model; [TSGroupThread getOrCreateThreadWithGroupId:groupId transaction:transaction];
[gThread saveWithTransaction:transaction];
TSGroupModel *newGroupModel = [[TSGroupModel alloc] initWithTitle:dataMessage.group.name
memberIds:[newMemberIds.allObjects mutableCopy]
image:nil
groupId:dataMessage.group.id];
NSString *updateGroupInfo = [newGroupThread.groupModel getInfoStringAboutUpdateTo:newGroupModel
contactsManager:self.contactsManager];
newGroupThread.groupModel = newGroupModel;
[newGroupThread saveWithTransaction:transaction];
[[[TSInfoMessage alloc] initWithTimestamp:timestamp [[[TSInfoMessage alloc] initWithTimestamp:timestamp
inThread:gThread inThread:newGroupThread
messageType:TSInfoMessageTypeGroupUpdate messageType:TSInfoMessageTypeGroupUpdate
customMessage:updateGroupInfo] saveWithTransaction:transaction]; customMessage:updateGroupInfo] saveWithTransaction:transaction];
thread = newGroupThread;
break; break;
} }
case OWSSignalServiceProtosGroupContextTypeQuit: { case OWSSignalServiceProtosGroupContextTypeQuit: {
NSString *nameString = [self.contactsManager displayNameForPhoneIdentifier:envelope.source]; if (!oldGroupThread) {
DDLogInfo(@"%@ ignoring quit group message from unknown group.", self.tag);
return nil;
}
[newMemberIds removeObject:envelope.source];
oldGroupThread.groupModel.groupMemberIds = [newMemberIds.allObjects mutableCopy];
[oldGroupThread saveWithTransaction:transaction];
NSString *nameString = [self.contactsManager displayNameForPhoneIdentifier:envelope.source];
NSString *updateGroupInfo = NSString *updateGroupInfo =
[NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""), nameString]; [NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""), nameString];
NSMutableArray *newGroupMembers = [NSMutableArray arrayWithArray:gThread.groupModel.groupMemberIds];
[newGroupMembers removeObject:envelope.source];
gThread.groupModel.groupMemberIds = newGroupMembers;
[gThread saveWithTransaction:transaction];
[[[TSInfoMessage alloc] initWithTimestamp:timestamp [[[TSInfoMessage alloc] initWithTimestamp:timestamp
inThread:gThread inThread:oldGroupThread
messageType:TSInfoMessageTypeGroupUpdate messageType:TSInfoMessageTypeGroupUpdate
customMessage:updateGroupInfo] saveWithTransaction:transaction]; customMessage:updateGroupInfo] saveWithTransaction:transaction];
thread = oldGroupThread;
break; break;
} }
case OWSSignalServiceProtosGroupContextTypeDeliver: { case OWSSignalServiceProtosGroupContextTypeDeliver: {
if (!oldGroupThread) {
DDLogInfo(@"%@ ignoring quit group message from unknown group.", self.tag);
[self sendGroupInfoRequest:groupId envelope:envelope transaction:transaction];
return nil;
}
if (body.length == 0 && attachmentIds.count < 1) { if (body.length == 0 && attachmentIds.count < 1) {
DDLogWarn(@"%@ ignoring empty incoming message from: %@ for group: %@ with timestamp: %lu", DDLogWarn(@"%@ ignoring empty incoming message from: %@ for group: %@ with timestamp: %lu",
self.tag, self.tag,
envelopeAddress(envelope), envelopeAddress(envelope),
groupId, groupId,
(unsigned long)timestamp); (unsigned long)timestamp);
} else { return nil;
DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu",
self.tag,
envelopeAddress(envelope),
groupId,
(unsigned long)timestamp);
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
inThread:gThread
authorId:envelope.source
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer];
[incomingMessage saveWithTransaction:transaction];
} }
DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu",
self.tag,
envelopeAddress(envelope),
groupId,
(unsigned long)timestamp);
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
inThread:oldGroupThread
authorId:envelope.source
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer];
[incomingMessage saveWithTransaction:transaction];
thread = oldGroupThread;
break; break;
} }
default: { default: {
DDLogWarn(@"%@ Ignoring unknown group message type: %d", self.tag, (int)dataMessage.group.type); DDLogWarn(@"%@ Ignoring unknown group message type: %d", self.tag, (int)dataMessage.group.type);
return nil;
} }
} }
thread = gThread;
} else { } else {
if (body.length == 0 && attachmentIds.count < 1) { if (body.length == 0 && attachmentIds.count < 1) {
DDLogWarn(@"%@ ignoring empty incoming message from: %@ with timestamp: %lu", DDLogWarn(@"%@ ignoring empty incoming message from: %@ with timestamp: %lu",
self.tag, self.tag,
envelopeAddress(envelope), envelopeAddress(envelope),
(unsigned long)timestamp); (unsigned long)timestamp);
} else { return nil;
DDLogDebug(@"%@ incoming message from: %@ with timestamp: %lu",
self.tag,
envelopeAddress(envelope),
(unsigned long)timestamp);
TSContactThread *cThread = [TSContactThread getOrCreateThreadWithContactId:envelope.source
transaction:transaction
relay:envelope.relay];
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
inThread:cThread
authorId:[cThread contactIdentifier]
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer];
[incomingMessage saveWithTransaction:transaction];
thread = cThread;
} }
DDLogDebug(@"%@ incoming message from: %@ with timestamp: %lu",
self.tag,
envelopeAddress(envelope),
(unsigned long)timestamp);
TSContactThread *cThread = [TSContactThread getOrCreateThreadWithContactId:envelope.source
transaction:transaction
relay:envelope.relay];
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
inThread:cThread
authorId:[cThread contactIdentifier]
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer];
[incomingMessage saveWithTransaction:transaction];
thread = cThread;
} }
OWSAssert(thread);
OWSAssert(incomingMessage);
if (thread && incomingMessage) { if (thread && incomingMessage) {
// Any messages sent from the current user - from this device or another - should be // Any messages sent from the current user - from this device or another - should be
// automatically marked as read. // automatically marked as read.
@ -949,9 +1009,7 @@ NS_ASSUME_NONNULL_BEGIN
DDLogDebug(@"%@ incoming extra text message: %@", self.tag, incomingMessage.debugDescription); DDLogDebug(@"%@ incoming extra text message: %@", self.tag, incomingMessage.debugDescription);
[textMessage saveWithTransaction:transaction]; [textMessage saveWithTransaction:transaction];
} }
}
if (thread && incomingMessage) {
// In case we already have a read receipt for this new message (this happens sometimes). // In case we already have a read receipt for this new message (this happens sometimes).
[OWSReadReceiptManager.sharedManager applyEarlyReadReceiptsForIncomingMessage:incomingMessage [OWSReadReceiptManager.sharedManager applyEarlyReadReceiptsForIncomingMessage:incomingMessage
transaction:transaction]; transaction:transaction];
@ -981,18 +1039,25 @@ NS_ASSUME_NONNULL_BEGIN
/** /**
* @returns * @returns
* Group or Contact thread for message, creating a new one if necessary. * Group or Contact thread for message, creating a new contact thread if necessary,
* but never creating a new group thread.
*/ */
- (TSThread *)threadForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope - (nullable TSThread *)threadForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
dataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage dataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
OWSAssert(envelope); OWSAssert(envelope);
OWSAssert(dataMessage); OWSAssert(dataMessage);
OWSAssert(transaction); OWSAssert(transaction);
if (dataMessage.hasGroup) { if (dataMessage.hasGroup) {
return [TSGroupThread getOrCreateThreadWithGroupIdData:dataMessage.group.id transaction:transaction]; NSData *groupId = dataMessage.group.id;
OWSAssert(groupId.length > 0);
TSGroupThread *_Nullable groupThread = [TSGroupThread threadWithGroupId:groupId transaction:transaction];
// This method should only be called from a code path that has already verified
// that this is a "known" group.
OWSAssert(groupThread);
return groupThread;
} else { } else {
return [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction]; return [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
} }

Loading…
Cancel
Save