Merge branch 'charlesmchen/refineViewModelDiffs'

pull/1/head
Matthew Chen 6 years ago
commit 9f04e7c5df

@ -340,6 +340,7 @@ private class MockConversationViewItem: NSObject, ConversationViewItem {
var hasBodyTextActionContent: Bool = false var hasBodyTextActionContent: Bool = false
var hasMediaActionContent: Bool = false var hasMediaActionContent: Bool = false
var mediaAlbumItems: [ConversationMediaAlbumItem]? var mediaAlbumItems: [ConversationMediaAlbumItem]?
var hasCachedLayoutState: Bool = false
override init() { override init() {
super.init() super.init()

@ -577,7 +577,6 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
case OWSMessageCellType_Unknown: case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: case OWSMessageCellType_OversizeTextMessage:
return NO;
case OWSMessageCellType_Audio: case OWSMessageCellType_Audio:
case OWSMessageCellType_GenericAttachment: case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment: case OWSMessageCellType_DownloadingAttachment:
@ -588,6 +587,21 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
} }
} }
- (BOOL)hasBodyMediaView {
switch (self.cellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
return NO;
case OWSMessageCellType_Audio:
case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment:
case OWSMessageCellType_ContactShare:
case OWSMessageCellType_MediaAlbum:
return YES;
}
}
- (BOOL)hasFullWidthMediaView - (BOOL)hasFullWidthMediaView
{ {
return (self.hasBodyMediaWithThumbnail || self.cellType == OWSMessageCellType_ContactShare return (self.hasBodyMediaWithThumbnail || self.cellType == OWSMessageCellType_ContactShare
@ -601,8 +615,14 @@ const UIDataDetectorTypes kOWSAllowedDataDetectorTypes
- (BOOL)hasBottomFooter - (BOOL)hasBottomFooter
{ {
BOOL shouldFooterOverlayMedia = (self.canFooterOverlayMedia && !self.hasBodyText); BOOL shouldFooterOverlayMedia = (self.canFooterOverlayMedia && self.hasBodyMediaView && !self.hasBodyText);
return !self.viewItem.shouldHideFooter && !shouldFooterOverlayMedia; if (self.viewItem.shouldHideFooter) {
return NO;
} else if (shouldFooterOverlayMedia) {
return NO;
} else {
return YES;
}
} }
- (BOOL)insertAnyTextViewsIntoStackView:(NSArray<UIView *> *)textViews - (BOOL)insertAnyTextViewsIntoStackView:(NSArray<UIView *> *)textViews

@ -91,6 +91,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
- (void)clearCachedLayoutState; - (void)clearCachedLayoutState;
@property (nonatomic, readonly) BOOL hasCachedLayoutState;
#pragma mark - Audio Playback #pragma mark - Audio Playback
@property (nonatomic, weak) OWSAudioMessageView *lastAudioMessageView; @property (nonatomic, weak) OWSAudioMessageView *lastAudioMessageView;

@ -286,6 +286,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
self.cachedCellSize = nil; self.cachedCellSize = nil;
} }
- (BOOL)hasCachedLayoutState {
return self.cachedCellSize != nil;
}
- (CGSize)cellSize - (CGSize)cellSize
{ {
OWSAssertIsOnMainThread(); OWSAssertIsOnMainThread();

@ -569,7 +569,6 @@ static const int kYapDatabaseRangeMinLength = 0;
// reloadViewItems. // reloadViewItems.
BOOL hasMalformedRowChange = NO; BOOL hasMalformedRowChange = NO;
NSMutableSet<NSString *> *updatedItemSet = [NSMutableSet new]; NSMutableSet<NSString *> *updatedItemSet = [NSMutableSet new];
NSMutableSet<NSString *> *updatedNeighborItemSet = [NSMutableSet new];
for (YapDatabaseViewRowChange *rowChange in rowChanges) { for (YapDatabaseViewRowChange *rowChange in rowChanges) {
switch (rowChange.type) { switch (rowChange.type) {
case YapDatabaseViewChangeUpdate: { case YapDatabaseViewChangeUpdate: {
@ -579,17 +578,10 @@ static const int kYapDatabaseRangeMinLength = 0;
if (viewItem) { if (viewItem) {
[self reloadInteractionForViewItem:viewItem]; [self reloadInteractionForViewItem:viewItem];
[updatedItemSet addObject:viewItem.itemId]; [updatedItemSet addObject:viewItem.itemId];
if (rowChange.changes == YapDatabaseViewChangedDependency) {
[updatedNeighborItemSet addObject:viewItem.itemId];
}
} else { } else {
OWSLogError(@"Update is missing view item"); OWSLogError(@"Update is missing view item");
hasMalformedRowChange = YES; hasMalformedRowChange = YES;
} }
} else if (rowChange.indexPath && rowChange.originalIndex < self.viewItems.count) {
// Do nothing, this is a pseudo-update generated due to
// setCellDrawingDependencyOffsets.
OWSAssertDebug(rowChange.changes == YapDatabaseViewChangedDependency);
} else { } else {
OWSFailDebug(@"Update is missing collection key"); OWSFailDebug(@"Update is missing collection key");
hasMalformedRowChange = YES; hasMalformedRowChange = YES;
@ -634,9 +626,7 @@ static const int kYapDatabaseRangeMinLength = 0;
OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.viewItems.count); OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.viewItems.count);
[self updateViewWithOldItemIdList:oldItemIdList [self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:updatedItemSet];
updatedItemSet:updatedItemSet
updatedNeighborItemSet:updatedNeighborItemSet];
} }
// A simpler version of the update logic we use when // A simpler version of the update logic we use when
@ -662,15 +652,13 @@ static const int kYapDatabaseRangeMinLength = 0;
OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.viewItems.count); OWSLogVerbose(@"self.viewItems.count: %zd -> %zd", oldItemIdList.count, self.viewItems.count);
[self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:[NSSet set] updatedNeighborItemSet:nil]; [self updateViewWithOldItemIdList:oldItemIdList updatedItemSet:[NSSet set]];
} }
- (void)updateViewWithOldItemIdList:(NSArray<NSString *> *)oldItemIdList - (void)updateViewWithOldItemIdList:(NSArray<NSString *> *)oldItemIdList
updatedItemSet:(NSSet<NSString *> *)updatedItemSet updatedItemSet:(NSSet<NSString *> *)updatedItemSetParam {
updatedNeighborItemSet:(nullable NSMutableSet<NSString *> *)updatedNeighborItemSet
{
OWSAssertDebug(oldItemIdList); OWSAssertDebug(oldItemIdList);
OWSAssertDebug(updatedItemSet); OWSAssertDebug(updatedItemSetParam);
if (!self.delegate.isObservingVMUpdates) { if (!self.delegate.isObservingVMUpdates) {
OWSLogVerbose(@"Skipping VM update."); OWSLogVerbose(@"Skipping VM update.");
@ -771,6 +759,44 @@ static const int kYapDatabaseRangeMinLength = 0;
return [self.delegate conversationViewModelDidUpdate:ConversationUpdate.reloadUpdate]; return [self.delegate conversationViewModelDidUpdate:ConversationUpdate.reloadUpdate];
} }
// In addition to "update" items from the database change notification,
// we may need to update other items. One example is neighbors of modified
// cells. Another is cells whose appearance has changed due to the passage
// of time. We detect "dirty" items by whether or not they have cached layout
// state, since that is cleared whenever we change the properties of the
// item that affect its appearance.
//
// This replaces the setCellDrawingDependencyOffsets/
// YapDatabaseViewChangedDependency logic offered by YDB mappings,
// which only reflects changes in the data store, not at the view
// level.
NSMutableSet<NSString *> *updatedItemSet = [updatedItemSetParam mutableCopy];
NSMutableSet<NSString *> *updatedNeighborItemSet = [NSMutableSet new];
for (NSString *itemId in newItemIdSet) {
if (![oldItemIdSet containsObject:itemId]) {
continue;
}
if ([insertedItemIdSet containsObject:itemId] || [updatedItemSet containsObject:itemId]) {
continue;
}
OWSAssertDebug(![deletedItemIdSet containsObject:itemId]);
NSUInteger newIndex = [newItemIdList indexOfObject:itemId];
if (newIndex == NSNotFound) {
OWSFailDebug(@"Can't find index of holdover view item.");
return [self.delegate conversationViewModelDidUpdate:ConversationUpdate.reloadUpdate];
}
id<ConversationViewItem> _Nullable viewItem = newViewItemMap[itemId];
if (!viewItem) {
OWSFailDebug(@"Can't find holdover view item.");
return [self.delegate conversationViewModelDidUpdate:ConversationUpdate.reloadUpdate];
}
if (!viewItem.hasCachedLayoutState) {
[updatedItemSet addObject:itemId];
[updatedNeighborItemSet addObject:itemId];
}
}
// 3. Updates. // 3. Updates.
// //
// NOTE: Order doesn't matter. // NOTE: Order doesn't matter.
@ -867,16 +893,6 @@ static const int kYapDatabaseRangeMinLength = 0;
[[YapDatabaseViewMappings alloc] initWithGroups:@[] view:TSMessageDatabaseViewExtensionName]; [[YapDatabaseViewMappings alloc] initWithGroups:@[] view:TSMessageDatabaseViewExtensionName];
} }
// Cells' appearance can depend on adjacent cells in both directions.
//
// TODO: We could do the same thing in our logic to generate "update items"
// in updateViewWithOldItemIdList.
[self.messageMappings setCellDrawingDependencyOffsets:[NSSet setWithArray:@[
@(-1),
@(+1),
]]
forGroup:self.thread.uniqueId];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction]; [self.messageMappings updateWithTransaction:transaction];
}]; }];

Loading…
Cancel
Save