Track 'persisted' viewItems separately

pull/1/head
Michael Kirk 7 years ago
parent e3610d4360
commit 087e320036

@ -702,7 +702,7 @@ typedef enum : NSUInteger {
- (NSArray<id<ConversationViewItem>> *)viewItems - (NSArray<id<ConversationViewItem>> *)viewItems
{ {
return self.conversationViewModel.viewItems; return self.conversationViewModel.allViewItems;
} }
- (ThreadDynamicInteractions *)dynamicInteractions - (ThreadDynamicInteractions *)dynamicInteractions

@ -80,7 +80,7 @@ typedef NS_ENUM(NSUInteger, ConversationUpdateItemType) {
@interface ConversationViewModel : NSObject @interface ConversationViewModel : NSObject
@property (nonatomic, readonly) NSArray<id<ConversationViewItem>> *viewItems; @property (nonatomic, readonly) NSArray<id<ConversationViewItem>> *allViewItems;
@property (nonatomic, nullable) NSString *focusMessageIdOnOpen; @property (nonatomic, nullable) NSString *focusMessageIdOnOpen;
@property (nonatomic, readonly, nullable) ThreadDynamicInteractions *dynamicInteractions; @property (nonatomic, readonly, nullable) ThreadDynamicInteractions *dynamicInteractions;

@ -154,7 +154,7 @@ static const int kYapDatabaseRangeMinLength = 0;
// * If we do the third step, we must call resetContentAndLayout afterward. // * If we do the third step, we must call resetContentAndLayout afterward.
@property (nonatomic) YapDatabaseViewMappings *messageMappings; @property (nonatomic) YapDatabaseViewMappings *messageMappings;
@property (nonatomic) NSArray<id<ConversationViewItem>> *viewItems; @property (nonatomic) NSArray<id<ConversationViewItem>> *allViewItems;
@property (nonatomic) NSMutableDictionary<NSString *, id<ConversationViewItem>> *viewItemCache; @property (nonatomic) NSMutableDictionary<NSString *, id<ConversationViewItem>> *viewItemCache;
@property (nonatomic) NSUInteger lastRangeLength; @property (nonatomic) NSUInteger lastRangeLength;
@ -165,6 +165,7 @@ static const int kYapDatabaseRangeMinLength = 0;
@property (nonatomic, nullable) ConversationProfileState *conversationProfileState; @property (nonatomic, nullable) ConversationProfileState *conversationProfileState;
@property (nonatomic) BOOL hasTooManyOutgoingMessagesToBlockCached; @property (nonatomic) BOOL hasTooManyOutgoingMessagesToBlockCached;
@property (nonatomic) NSArray<id<ConversationViewItem>> *persistedViewItems;
@end @end
@ -489,7 +490,7 @@ static const int kYapDatabaseRangeMinLength = 0;
- (nullable id<ConversationViewItem>)viewItemForUnreadMessagesIndicator - (nullable id<ConversationViewItem>)viewItemForUnreadMessagesIndicator
{ {
for (id<ConversationViewItem> viewItem in self.viewItems) { for (id<ConversationViewItem> viewItem in self.allViewItems) {
if (viewItem.unreadIndicator) { if (viewItem.unreadIndicator) {
return viewItem; return viewItem;
} }
@ -596,7 +597,7 @@ static const int kYapDatabaseRangeMinLength = 0;
} }
NSMutableArray<NSString *> *oldItemIdList = [NSMutableArray new]; NSMutableArray<NSString *> *oldItemIdList = [NSMutableArray new];
for (id<ConversationViewItem> viewItem in self.viewItems) { for (id<ConversationViewItem> viewItem in self.allViewItems) {
[oldItemIdList addObject:viewItem.itemId]; [oldItemIdList addObject:viewItem.itemId];
} }
@ -659,7 +660,7 @@ static const int kYapDatabaseRangeMinLength = 0;
return; return;
} }
OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.viewItems.count); OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.allViewItems.count);
[self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:updatedItemSet]; [self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:updatedItemSet];
} }
@ -673,7 +674,7 @@ static const int kYapDatabaseRangeMinLength = 0;
OWSLogVerbose(@""); OWSLogVerbose(@"");
NSMutableArray<NSString *> *oldItemIdList = [NSMutableArray new]; NSMutableArray<NSString *> *oldItemIdList = [NSMutableArray new];
for (id<ConversationViewItem> viewItem in self.viewItems) { for (id<ConversationViewItem> viewItem in self.allViewItems) {
[oldItemIdList addObject:viewItem.itemId]; [oldItemIdList addObject:viewItem.itemId];
} }
@ -685,7 +686,7 @@ static const int kYapDatabaseRangeMinLength = 0;
return; return;
} }
OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.viewItems.count); OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.allViewItems.count);
[self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:[NSSet set]]; [self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:[NSSet set]];
} }
@ -710,7 +711,7 @@ static const int kYapDatabaseRangeMinLength = 0;
NSMutableArray<NSString *> *newItemIdList = [NSMutableArray new]; NSMutableArray<NSString *> *newItemIdList = [NSMutableArray new];
NSMutableDictionary<NSString *, id<ConversationViewItem>> *newViewItemMap = [NSMutableDictionary new]; NSMutableDictionary<NSString *, id<ConversationViewItem>> *newViewItemMap = [NSMutableDictionary new];
for (id<ConversationViewItem> viewItem in self.viewItems) { for (id<ConversationViewItem> viewItem in self.allViewItems) {
[newItemIdList addObject:viewItem.itemId]; [newItemIdList addObject:viewItem.itemId];
newViewItemMap[viewItem.itemId] = viewItem; newViewItemMap[viewItem.itemId] = viewItem;
} }
@ -1150,6 +1151,32 @@ static const int kYapDatabaseRangeMinLength = 0;
return offersMessage; return offersMessage;
} }
- (id<ConversationViewItem>)addViewItemWithInteraction:(TSInteraction *)interaction
conversationStyle:(ConversationStyle *)conversationStyle
isGroupThread:(BOOL)isGroupThread
transaction:(YapDatabaseReadTransaction *)transaction
viewItemCache:
(NSMutableDictionary<NSString *, id<ConversationViewItem>> *)viewItemCache
toViewItems:(NSMutableArray<id<ConversationViewItem>> *)viewItems
{
OWSAssertDebug(interaction.uniqueId.length > 0);
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[interaction.uniqueId];
if (!viewItem) {
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:interaction
isGroupThread:isGroupThread
transaction:transaction
conversationStyle:conversationStyle];
}
[viewItems addObject:viewItem];
OWSAssertDebug(
!viewItemCache[interaction.uniqueId] || [interaction isKindOfClass:[OWSTypingIndicatorInteraction class]]);
viewItemCache[interaction.uniqueId] = viewItem;
return viewItem;
}
// This is a key method. It builds or rebuilds the list of // This is a key method. It builds or rebuilds the list of
// cell view models. // cell view models.
// //
@ -1166,20 +1193,14 @@ static const int kYapDatabaseRangeMinLength = 0;
[self ensureConversationProfileState]; [self ensureConversationProfileState];
__block BOOL hasError = NO; __block BOOL hasError = NO;
id<ConversationViewItem> (^tryToAddViewItem)(TSInteraction *, YapDatabaseReadTransaction *) = ^(TSInteraction *interaction, YapDatabaseReadTransaction *transaction) { id<ConversationViewItem> (^tryToAddViewItem)(TSInteraction *, YapDatabaseReadTransaction *)
OWSAssertDebug(interaction.uniqueId.length > 0); = ^(TSInteraction *interaction, YapDatabaseReadTransaction *transaction) {
return [self addViewItemWithInteraction:interaction
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[interaction.uniqueId]; conversationStyle:conversationStyle
if (!viewItem) {
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:interaction
isGroupThread:isGroupThread isGroupThread:isGroupThread
transaction:transaction transaction:transaction
conversationStyle:conversationStyle]; viewItemCache:viewItemCache
} toViewItems:viewItems];
[viewItems addObject:viewItem];
OWSAssertDebug(!viewItemCache[interaction.uniqueId]);
viewItemCache[interaction.uniqueId] = viewItem;
return viewItem;
}; };
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
@ -1242,17 +1263,6 @@ static const int kYapDatabaseRangeMinLength = 0;
return [left.interaction compareForSorting:right.interaction]; return [left.interaction compareForSorting:right.interaction];
}]; }];
if (self.typingIndicatorsSender) {
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
id<ConversationViewItem> _Nullable lastViewItem = viewItems.lastObject;
uint64_t typingIndicatorTimestamp = (lastViewItem ? lastViewItem.interaction.timestamp + 1 : 1);
TSInteraction *interaction =
[[OWSTypingIndicatorInteraction alloc] initWithThread:self.thread
timestamp:typingIndicatorTimestamp
recipientId:self.typingIndicatorsSender];
tryToAddViewItem(interaction, transaction);
}];
}
// Flag to ensure that we only increment once per launch. // Flag to ensure that we only increment once per launch.
if (hasError) { if (hasError) {
OWSLogWarn(@"incrementing version of: %@", TSMessageDatabaseViewExtensionName); OWSLogWarn(@"incrementing version of: %@", TSMessageDatabaseViewExtensionName);
@ -1260,13 +1270,36 @@ static const int kYapDatabaseRangeMinLength = 0;
} }
self.viewItemCache = viewItemCache; self.viewItemCache = viewItemCache;
self.viewItems = [self prepareViewItemsForDisplay:viewItems]; self.persistedViewItems = [viewItems copy];
self.allViewItems = [self prepareViewItemsForDisplay:viewItems];
return !hasError; return !hasError;
} }
- (NSArray<id<ConversationViewItem>> *)prepareViewItemsForDisplay:(NSArray<id<ConversationViewItem>> *)viewItems - (NSArray<id<ConversationViewItem>> *)prepareViewItemsForDisplay:(NSArray<id<ConversationViewItem>> *)viewItemsArg
{ {
NSArray<id<ConversationViewItem>> *viewItems = viewItemsArg;
if (self.typingIndicatorsSender) {
NSMutableArray<id<ConversationViewItem>> *mutableViewItems = [viewItems mutableCopy];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
id<ConversationViewItem> _Nullable lastViewItem = viewItems.lastObject;
uint64_t typingIndicatorTimestamp = (lastViewItem ? lastViewItem.interaction.timestamp + 1 : 1);
TSInteraction *interaction =
[[OWSTypingIndicatorInteraction alloc] initWithThread:self.thread
timestamp:typingIndicatorTimestamp
recipientId:self.typingIndicatorsSender];
[self addViewItemWithInteraction:interaction
conversationStyle:self.delegate.conversationStyle
isGroupThread:self.thread.isGroupThread
transaction:transaction
viewItemCache:self.viewItemCache
toViewItems:mutableViewItems];
}];
viewItems = [mutableViewItems copy];
}
// Update the "break" properties (shouldShowDate and unreadIndicator) of the view items. // Update the "break" properties (shouldShowDate and unreadIndicator) of the view items.
BOOL shouldShowDateOnNextViewItem = YES; BOOL shouldShowDateOnNextViewItem = YES;
uint64_t previousViewItemTimestamp = 0; uint64_t previousViewItemTimestamp = 0;
@ -1509,14 +1542,15 @@ static const int kYapDatabaseRangeMinLength = 0;
conversationStyle:self.delegate.conversationStyle]; conversationStyle:self.delegate.conversationStyle];
}]; }];
ConversationUpdateItem *updateItem = [[ConversationUpdateItem alloc] initWithUpdateItemType:ConversationUpdateItemType_Insert ConversationUpdateItem *updateItem =
[[ConversationUpdateItem alloc] initWithUpdateItemType:ConversationUpdateItemType_Insert
oldIndex:0 oldIndex:0
newIndex:self.viewItems.count newIndex:self.persistedViewItems.count
viewItem:viewItem]; viewItem:viewItem];
NSMutableArray<id <ConversationViewItem>> *viewItems = [self.viewItems mutableCopy]; NSMutableArray<id<ConversationViewItem>> *viewItems = [self.persistedViewItems mutableCopy];
[viewItems addObject:viewItem]; [viewItems addObject:viewItem];
self.viewItems = [self prepareViewItemsForDisplay:viewItems]; self.allViewItems = [self prepareViewItemsForDisplay:viewItems];
ConversationUpdate *conversationUpdate = [[ConversationUpdate alloc] initWithConversationUpdateType:ConversationUpdateType_Diff ConversationUpdate *conversationUpdate = [[ConversationUpdate alloc] initWithConversationUpdateType:ConversationUpdateType_Diff
updateItems:@[updateItem] updateItems:@[updateItem]
shouldAnimateUpdates:NO]; shouldAnimateUpdates:NO];
@ -1666,7 +1700,7 @@ static const int kYapDatabaseRangeMinLength = 0;
OWSFailDebug(@"Could not locate view item for quoted reply."); OWSFailDebug(@"Could not locate view item for quoted reply.");
return nil; return nil;
} }
NSUInteger viewItemIndex = [self.viewItems indexOfObject:viewItem]; NSUInteger viewItemIndex = [self.allViewItems indexOfObject:viewItem];
if (viewItemIndex == NSNotFound) { if (viewItemIndex == NSNotFound) {
OWSFailDebug(@"Could not locate view item index for quoted reply."); OWSFailDebug(@"Could not locate view item index for quoted reply.");
return nil; return nil;
@ -1718,7 +1752,7 @@ static const int kYapDatabaseRangeMinLength = 0;
// Update the view items if necessary. // Update the view items if necessary.
// We don't have to do this if they haven't been configured yet. // We don't have to do this if they haven't been configured yet.
if (didChange && self.viewItems != nil) { if (didChange && self.allViewItems != nil) {
[self updateForTransientItems]; [self updateForTransientItems];
} }
} }

Loading…
Cancel
Save