Create disappearing message update info messages before messages they affect

Since we're no longer sorting by timestamp we have to ensure we save the update
info message before we save any affected message, e.g. in the case of implicit
updates.
This commit is contained in:
Michael Kirk 2018-09-20 11:19:12 -06:00
parent eef1368ad3
commit 550e7ba63b
5 changed files with 56 additions and 79 deletions

View File

@ -129,12 +129,13 @@ NS_ASSUME_NONNULL_BEGIN
}
}
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:outgoingMessage.expiresInSeconds
thread:transcript.thread
createdByRemoteRecipientId:nil
createdInExistingGroup:NO
transaction:transaction];
if (transcript.isExpirationTimerUpdate) {
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:outgoingMessage
contactsManager:self.contactsManager
transaction:transaction];
// early return to avoid saving an empty incoming message.
OWSAssertDebug(transcript.body.length == 0);
OWSAssertDebug(outgoingMessage.attachmentIds.count == 0);
@ -149,9 +150,6 @@ NS_ASSUME_NONNULL_BEGIN
[outgoingMessage saveWithTransaction:transaction];
[outgoingMessage updateWithWasSentFromLinkedDeviceWithTransaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:outgoingMessage
contactsManager:self.contactsManager
transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:outgoingMessage
expirationStartedAt:transcript.expirationStartedAt
transaction:transaction];

View File

@ -76,7 +76,7 @@ NS_ASSUME_NONNULL_BEGIN
return [NSString stringWithFormat:infoFormat, self.createdByRemoteName];
}
} else {
// Changed by local request
// Changed by localNumber on this device or via synced transcript
if (self.configurationIsEnabled && self.configurationDurationSeconds > 0) {
NSString *infoFormat = NSLocalizedString(@"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION",
@"Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context.");

View File

@ -21,42 +21,23 @@ NS_ASSUME_NONNULL_BEGIN
expirationStartedAt:(uint64_t)expirationStartedAt
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction;
/**
* Synchronize our disappearing messages settings with that of the given message. Useful so we can
* become eventually consistent with remote senders.
*
* @param message
* Can be an expiring or non expiring message. We match the expiration timer of the message, including disabling
* expiring messages if the message is not an expiring message.
*
* @param contactsManager
* Provides the contact name responsible for any configuration changes in an info message.
*/
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
contactsManager:(id<ContactsManagerProtocol>)contactsManager
transaction:(YapDatabaseReadWriteTransaction *)transaction;
/**
* Synchronize our disappearing messages settings with that of the given message. Useful so we can
* become eventually consistent with remote senders.
*
* @param duration
* Can be 0, indicating a non-expiring message, or greater, indicating an expiring message. We match the expiration
* timer of the message, including disabling expiring messages if the message is not an expiring message.
* timer of the message, including disabling expiring messages if the message is not an expiring message.
*
* @param timestampForSorting
* timestampForSorting of the message before which we want to appear.
* @param remoteRecipientId
* nil for outgoing messages, otherwise the recipientId of the sender
*
* @param remoteContactName
* nil for outgoing messages, otherwise the name of the sender
* @param createdInExistingGroup
* YES when being added to a group which already has DM enabled, otherwise NO
*/
// MJK FIXME - we can't rely on timestampForSorting
- (void)becomeConsistentWithDisappearingDuration:(uint32_t)duration
thread:(TSThread *)thread
appearBeforeSenderTimestamp:(uint64_t)timestampForSorting
createdByRemoteContactName:(nullable NSString *)remoteContactName
createdByRemoteRecipientId:(nullable NSString *)remoteRecipientId
createdInExistingGroup:(BOOL)createdInExistingGroup
transaction:(YapDatabaseReadWriteTransaction *)transaction;

View File

@ -13,6 +13,7 @@
#import "OWSDisappearingMessagesConfiguration.h"
#import "OWSDisappearingMessagesFinder.h"
#import "OWSPrimaryStorage.h"
#import "SSKEnvironment.h"
#import "TSIncomingMessage.h"
#import "TSMessage.h"
#import "TSThread.h"
@ -110,6 +111,15 @@ void AssertIsOnDisappearingMessagesQueue()
return queue;
}
#pragma mark - Dependencies
- (id<ContactsManagerProtocol>)contactsManager
{
return SSKEnvironment.shared.contactsManager;
}
#pragma mark -
- (NSUInteger)deleteExpiredMessages
{
AssertIsOnDisappearingMessagesQueue();
@ -193,40 +203,25 @@ void AssertIsOnDisappearingMessagesQueue()
}];
}
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
contactsManager:(id<ContactsManagerProtocol>)contactsManager
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
TSThread *thread = [message threadWithTransaction:transaction];
NSString *remoteContactName = nil;
if ([message isKindOfClass:[TSIncomingMessage class]]) {
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)message;
remoteContactName = [contactsManager displayNameForPhoneIdentifier:incomingMessage.messageAuthorId];
}
// MJK - we can't rely on timestampForSorting
[self becomeConsistentWithDisappearingDuration:message.expiresInSeconds
thread:thread
appearBeforeSenderTimestamp:message.timestampForSorting
createdByRemoteContactName:remoteContactName
createdInExistingGroup:NO
transaction:transaction];
}
#pragma mark - Apply Remote Configuration
// MJK - we can't rely on timestampForSorting
- (void)becomeConsistentWithDisappearingDuration:(uint32_t)duration
thread:(TSThread *)thread
appearBeforeSenderTimestamp:(uint64_t)timestampForSorting
createdByRemoteContactName:(nullable NSString *)remoteContactName
createdByRemoteRecipientId:(nullable NSString *)remoteRecipientId
createdInExistingGroup:(BOOL)createdInExistingGroup
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(thread);
OWSAssertDebug(timestampForSorting > 0);
OWSAssertDebug(transaction);
OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
NSString *_Nullable remoteContactName = nil;
if (remoteRecipientId) {
remoteContactName = [self.contactsManager displayNameForPhoneIdentifier:remoteRecipientId];
}
// Become eventually consistent in the case that the remote changed their settings at the same time.
// Also in case remote doesn't support expiring messages
OWSDisappearingMessagesConfiguration *disappearingMessagesConfiguration =
@ -248,10 +243,9 @@ void AssertIsOnDisappearingMessagesQueue()
[disappearingMessagesConfiguration saveWithTransaction:transaction];
// We want the info message to appear _before_ the message.
// MJK FIXME - we have to affect ordering by creation sequence, not sender timestamp
// MJK TODO - should be safe to remove this senderTimestamp
OWSDisappearingConfigurationUpdateInfoMessage *infoMessage =
[[OWSDisappearingConfigurationUpdateInfoMessage alloc] initWithSenderTimestamp:timestampForSorting - 1
[[OWSDisappearingConfigurationUpdateInfoMessage alloc] initWithSenderTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
configuration:disappearingMessagesConfiguration
createdByRemoteName:remoteContactName
@ -262,6 +256,8 @@ void AssertIsOnDisappearingMessagesQueue()
backgroundTask = nil;
}
#pragma mark -
- (void)startIfNecessary
{
dispatch_async(dispatch_get_main_queue(), ^{

View File

@ -1146,8 +1146,6 @@ NS_ASSUME_NONNULL_BEGIN
TSGroupThread *newGroupThread =
[TSGroupThread getOrCreateThreadWithGroupId:groupId transaction:transaction];
uint64_t now = [NSDate ows_millisecondTimeStamp];
TSGroupModel *newGroupModel = [[TSGroupModel alloc] initWithTitle:dataMessage.group.name
memberIds:newMemberIds.allObjects
image:oldGroupThread.groupModel.groupImage
@ -1157,23 +1155,19 @@ NS_ASSUME_NONNULL_BEGIN
newGroupThread.groupModel = newGroupModel;
[newGroupThread saveWithTransaction:transaction];
// MJK FIXME - seems like we're relying on senderTimestamp
TSInfoMessage *infoMessage = [[TSInfoMessage alloc] initWithSenderTimestamp:now
inThread:newGroupThread
messageType:TSInfoMessageTypeGroupUpdate
customMessage:updateGroupInfo];
[infoMessage saveWithTransaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:newGroupThread
createdByRemoteRecipientId:nil
createdInExistingGroup:NO
transaction:transaction];
if (dataMessage.hasExpireTimer && dataMessage.expireTimer > 0) {
// MJK - we can't rely on senderTimestamp
[[OWSDisappearingMessagesJob sharedJob]
becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:newGroupThread
appearBeforeSenderTimestamp:now
createdByRemoteContactName:nil
createdInExistingGroup:YES
transaction:transaction];
}
// MJK TODO - should be safe to remove senderTimestamp
TSInfoMessage *infoMessage =
[[TSInfoMessage alloc] initWithSenderTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:newGroupThread
messageType:TSInfoMessageTypeGroupUpdate
customMessage:updateGroupInfo];
[infoMessage saveWithTransaction:transaction];
return nil;
}
@ -1210,6 +1204,12 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:oldGroupThread
createdByRemoteRecipientId:envelope.source
createdInExistingGroup:YES
transaction:transaction];
TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage
thread:oldGroupThread
transaction:transaction];
@ -1255,6 +1255,12 @@ NS_ASSUME_NONNULL_BEGIN
TSContactThread *thread =
[TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:thread
createdByRemoteRecipientId:envelope.source
createdInExistingGroup:NO
transaction:transaction];
TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage
thread:thread
transaction:transaction];
@ -1369,10 +1375,6 @@ NS_ASSUME_NONNULL_BEGIN
[OWSReadReceiptManager.sharedManager applyEarlyReadReceiptsForIncomingMessage:incomingMessage
transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:incomingMessage
contactsManager:self.contactsManager
transaction:transaction];
// Update thread preview in inbox
[thread touchWithTransaction:transaction];