Avoid stale mapping in conversation view.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 8d4f30d19e
commit d4a6a35ee3

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

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

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

Loading…
Cancel
Save