Avoid stale mapping in conversation view.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-06-19 13:56:23 -04:00
parent 8d4f30d19e
commit d4a6a35ee3
3 changed files with 75 additions and 27 deletions

View File

@ -332,6 +332,8 @@ typedef enum : NSUInteger {
_composeOnOpen = keyboardOnViewAppearing;
_callOnOpen = callOnViewAppearing;
[self.uiDatabaseConnection beginLongLivedReadTransaction];
// We need to create the "unread indicator" before we mark
// all messages as read.
[self ensureDynamicInteractions];
@ -564,9 +566,12 @@ typedef enum : NSUInteger {
// We need to `beginLongLivedReadTransaction` before we update our
// mapping in order to jump to the most recent commit.
[self.uiDatabaseConnection beginLongLivedReadTransaction];
self.messageMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[ self.thread.uniqueId ]
view:TSMessageDatabaseViewExtensionName];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction];
}];
[self updateMessageMappingRangeOptions];
[self toggleObservers:YES];
@ -2218,6 +2223,10 @@ typedef enum : NSUInteger {
// while updating the range and the dynamic interactions.
[[NSNotificationCenter defaultCenter] removeObserver:self name:YapDatabaseModifiedNotification object:nil];
// We need to `beginLongLivedReadTransaction` before we update our
// mapping in order to jump to the most recent commit.
[self.uiDatabaseConnection beginLongLivedReadTransaction];
// We need to update the dynamic interactions after loading earlier messages,
// since the unseen indicator may need to move or change.
[self ensureDynamicInteractions];
@ -2566,7 +2575,7 @@ typedef enum : NSUInteger {
DDLogInfo(@"%@ Blocking an unknown user.", self.tag);
[self.blockingManager addBlockedPhoneNumber:errorMessage.contactId];
// Delete the block offer.
[self.storageManager.dbConnection
[self.editingDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[errorMessage removeWithTransaction:transaction];
}];
@ -2693,7 +2702,8 @@ typedef enum : NSUInteger {
[ThreadUtil ensureDynamicInteractionsForThread:self.thread
contactsManager:self.contactsManager
blockingManager:self.blockingManager
dbConnection:self.editingDatabaseConnection
readDBConnection:self.uiDatabaseConnection
writeDBConnection:self.editingDatabaseConnection
hideUnreadMessagesIndicator:self.hasClearedUnreadMessagesIndicator
firstUnseenInteractionTimestamp:self.dynamicInteractions.firstUnseenInteractionTimestamp
maxRangeSize:maxRangeSize];
@ -3206,8 +3216,8 @@ typedef enum : NSUInteger {
[self setNavigationTitle];
}
if (!
[[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName] hasChangesForNotifications:notifications]) {
if (![[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName] hasChangesForGroup:self.thread.uniqueId
inNotifications:notifications]) {
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction];
}];
@ -3223,12 +3233,24 @@ typedef enum : NSUInteger {
NSArray *messageRowChanges = nil;
NSArray *sectionChanges = nil;
[[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName] getSectionChanges:&sectionChanges
rowChanges:&messageRowChanges
forNotifications:notifications
withMappings:self.messageMappings];
[[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName]
getSectionChanges:&sectionChanges
rowChanges:&messageRowChanges
forNotifications:notifications
withMappings:self.messageMappings];
if ([sectionChanges count] == 0 && [messageRowChanges count] == 0) {
// YapDatabase will ignore insertions within the message mapping's
// range that are not within the current mapping's contents. We
// may need to extend the mapping's contents to reflect the current
// range.
[self updateMessageMappingRangeOptions];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction];
}];
[self resetContentAndLayout];
if ([sectionChanges count] == 0 & [messageRowChanges count] == 0) {
return;
}

View File

@ -83,7 +83,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (ThreadDynamicInteractions *)ensureDynamicInteractionsForThread:(TSThread *)thread
contactsManager:(OWSContactsManager *)contactsManager
blockingManager:(OWSBlockingManager *)blockingManager
dbConnection:(YapDatabaseConnection *)dbConnection
readDBConnection:(YapDatabaseConnection *)readDBConnection
writeDBConnection:(YapDatabaseConnection *)writeDBConnection
hideUnreadMessagesIndicator:(BOOL)hideUnreadMessagesIndicator
firstUnseenInteractionTimestamp:(nullable NSNumber *)firstUnseenInteractionTimestamp
maxRangeSize:(int)maxRangeSize;

View File

@ -116,14 +116,16 @@ NS_ASSUME_NONNULL_BEGIN
+ (ThreadDynamicInteractions *)ensureDynamicInteractionsForThread:(TSThread *)thread
contactsManager:(OWSContactsManager *)contactsManager
blockingManager:(OWSBlockingManager *)blockingManager
dbConnection:(YapDatabaseConnection *)dbConnection
readDBConnection:(YapDatabaseConnection *)readDBConnection
writeDBConnection:(YapDatabaseConnection *)writeDBConnection
hideUnreadMessagesIndicator:(BOOL)hideUnreadMessagesIndicator
firstUnseenInteractionTimestamp:
(nullable NSNumber *)firstUnseenInteractionTimestampParameter
maxRangeSize:(int)maxRangeSize
{
OWSAssert(thread);
OWSAssert(dbConnection);
OWSAssert(readDBConnection);
OWSAssert(writeDBConnection);
OWSAssert(contactsManager);
OWSAssert(blockingManager);
OWSAssert(maxRangeSize > 0);
@ -133,15 +135,23 @@ NS_ASSUME_NONNULL_BEGIN
ThreadDynamicInteractions *result = [ThreadDynamicInteractions new];
[dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
const int kMaxBlockOfferOutgoingMessageCount = 10;
const int kMaxBlockOfferOutgoingMessageCount = 10;
__block OWSAddToContactsOfferMessage *existingAddToContactsOffer = nil;
__block OWSUnknownContactBlockOfferMessage *existingBlockOffer = nil;
__block TSUnreadIndicatorInteraction *existingUnreadIndicator = nil;
NSMutableArray<TSInvalidIdentityKeyErrorMessage *> *blockingSafetyNumberChanges = [NSMutableArray new];
NSMutableArray<TSInteraction *> *nonBlockingSafetyNumberChanges = [NSMutableArray new];
__block TSMessage *firstMessage = nil;
__block NSUInteger outgoingMessageCount;
__block NSUInteger threadMessageCount;
__block long visibleUnseenMessageCount = 0;
__block TSInteraction *interactionAfterUnreadIndicator = nil;
__block NSUInteger missingUnseenSafetyNumberChangeCount = 0;
[readDBConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
// Find any "dynamic" interactions and safety number changes.
__block OWSAddToContactsOfferMessage *existingAddToContactsOffer = nil;
__block OWSUnknownContactBlockOfferMessage *existingBlockOffer = nil;
__block TSUnreadIndicatorInteraction *existingUnreadIndicator = nil;
NSMutableArray<TSInvalidIdentityKeyErrorMessage *> *blockingSafetyNumberChanges = [NSMutableArray new];
NSMutableArray<TSInteraction *> *nonBlockingSafetyNumberChanges = [NSMutableArray new];
// We use different views for performance reasons.
[[TSDatabaseView threadSpecialMessagesDatabaseView:transaction]
enumerateRowsInGroup:thread.uniqueId
@ -186,7 +196,6 @@ NS_ASSUME_NONNULL_BEGIN
}
}
__block TSMessage *firstMessage = nil;
[[transaction ext:TSMessageDatabaseViewExtensionName]
enumerateRowsInGroup:thread.uniqueId
usingBlock:^(
@ -201,9 +210,9 @@ NS_ASSUME_NONNULL_BEGIN
}
}];
NSUInteger outgoingMessageCount =
outgoingMessageCount =
[[TSDatabaseView threadOutgoingMessageDatabaseView:transaction] numberOfItemsInGroup:thread.uniqueId];
NSUInteger threadMessageCount =
threadMessageCount =
[[transaction ext:TSMessageDatabaseViewExtensionName] numberOfItemsInGroup:thread.uniqueId];
// Enumerate in reverse to count the number of messages
@ -212,9 +221,6 @@ NS_ASSUME_NONNULL_BEGIN
// the messages view the position of the unread indicator,
// so that it can widen its "load window" to always show
// the unread indicator.
__block long visibleUnseenMessageCount = 0;
__block TSInteraction *interactionAfterUnreadIndicator = nil;
NSUInteger missingUnseenSafetyNumberChangeCount = 0;
if (result.firstUnseenInteractionTimestamp != nil) {
[[transaction ext:TSMessageDatabaseViewExtensionName]
enumerateRowsInGroup:thread.uniqueId
@ -288,7 +294,9 @@ NS_ASSUME_NONNULL_BEGIN
result.unreadIndicatorPosition = @(visibleUnseenMessageCount);
}
OWSAssert((result.firstUnseenInteractionTimestamp != nil) == (result.unreadIndicatorPosition != nil));
}];
[writeDBConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
BOOL shouldHaveBlockOffer = YES;
BOOL shouldHaveAddToContactsOffer = YES;
@ -347,7 +355,11 @@ NS_ASSUME_NONNULL_BEGIN
const int kUnreadIndicatorOfferOffset = -1;
if (existingBlockOffer && !shouldHaveBlockOffer) {
DDLogInfo(@"Removing block offer");
DDLogInfo(@"%@ Removing block offer: %@ (%llu)",
self.tag,
existingBlockOffer.uniqueId,
existingBlockOffer.timestampForSorting);
;
[existingBlockOffer removeWithTransaction:transaction];
} else if (!existingBlockOffer && shouldHaveBlockOffer) {
DDLogInfo(@"Creating block offer for unknown contact");
@ -363,10 +375,18 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread
contactId:recipientId];
[offerMessage saveWithTransaction:transaction];
DDLogInfo(@"%@ Creating block offer: %@ (%llu)",
self.tag,
offerMessage.uniqueId,
offerMessage.timestampForSorting);
}
if (existingAddToContactsOffer && !shouldHaveAddToContactsOffer) {
DDLogInfo(@"Removing 'add to contacts' offer");
DDLogInfo(@"%@ Removing 'add to contacts' offer: %@ (%llu)",
self.tag,
existingAddToContactsOffer.uniqueId,
existingAddToContactsOffer.timestampForSorting);
[existingAddToContactsOffer removeWithTransaction:transaction];
} else if (!existingAddToContactsOffer && shouldHaveAddToContactsOffer) {
@ -383,6 +403,11 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread
contactId:recipientId];
[offerMessage saveWithTransaction:transaction];
DDLogInfo(@"%@ Creating 'add to contacts' offer: %@ (%llu)",
self.tag,
offerMessage.uniqueId,
offerMessage.timestampForSorting);
}
BOOL shouldHaveUnreadIndicator