Merge branch 'charlesmchen/messageViewTweaks'

pull/1/head
Matthew Chen 8 years ago
commit c630a1ecc0

@ -56,6 +56,10 @@ NS_ASSUME_NONNULL_BEGIN
_referenceSystemMessageCell = [OWSSystemMessageCell new]; _referenceSystemMessageCell = [OWSSystemMessageCell new];
_referenceUnreadIndicatorCell = [OWSUnreadIndicatorCell new]; _referenceUnreadIndicatorCell = [OWSUnreadIndicatorCell new];
_referenceContactOffersCell = [OWSContactOffersCell new]; _referenceContactOffersCell = [OWSContactOffersCell new];
// Calculating message size is relatively expensive, so unbound the size of the cache.
self.cache.countLimit = 0;
self.cache.totalCostLimit = 0;
} }
return self; return self;
} }
@ -74,6 +78,21 @@ NS_ASSUME_NONNULL_BEGIN
- (CGSize)messageBubbleSizeForMessageData:(id<JSQMessageData>)messageData - (CGSize)messageBubbleSizeForMessageData:(id<JSQMessageData>)messageData
atIndexPath:(NSIndexPath *)indexPath atIndexPath:(NSIndexPath *)indexPath
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout withLayout:(JSQMessagesCollectionViewFlowLayout *)layout
{
id cacheKey = [self cacheKeyForMessageData:messageData];
NSValue *cachedSize = [self.cache objectForKey:cacheKey];
if (cachedSize != nil) {
return [cachedSize CGSizeValue];
}
CGSize result = [self calculateMessageBubbleSizeForMessageData:messageData atIndexPath:indexPath withLayout:layout];
[self.cache setObject:[NSValue valueWithCGSize:result] forKey:cacheKey];
return result;
}
- (CGSize)calculateMessageBubbleSizeForMessageData:(id<JSQMessageData>)messageData
atIndexPath:(NSIndexPath *)indexPath
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout
{ {
if ([messageData isKindOfClass:[TSMessageAdapter class]]) { if ([messageData isKindOfClass:[TSMessageAdapter class]]) {
TSMessageAdapter *message = (TSMessageAdapter *)messageData; TSMessageAdapter *message = (TSMessageAdapter *)messageData;
@ -82,21 +101,18 @@ NS_ASSUME_NONNULL_BEGIN
case TSCallAdapter: case TSCallAdapter:
case TSInfoMessageAdapter: case TSInfoMessageAdapter:
case TSErrorMessageAdapter: { case TSErrorMessageAdapter: {
id cacheKey = [self cacheKeyForMessageData:messageData];
TSInteraction *interaction = ((TSMessageAdapter *)messageData).interaction; TSInteraction *interaction = ((TSMessageAdapter *)messageData).interaction;
return [self sizeForSystemMessage:interaction cacheKey:cacheKey layout:layout]; return [self sizeForSystemMessage:interaction layout:layout];
} }
case TSUnreadIndicatorAdapter: { case TSUnreadIndicatorAdapter: {
id cacheKey = [self cacheKeyForMessageData:messageData];
TSUnreadIndicatorInteraction *interaction TSUnreadIndicatorInteraction *interaction
= (TSUnreadIndicatorInteraction *)((TSMessageAdapter *)messageData).interaction; = (TSUnreadIndicatorInteraction *)((TSMessageAdapter *)messageData).interaction;
return [self sizeForUnreadIndicator:interaction cacheKey:cacheKey layout:layout]; return [self sizeForUnreadIndicator:interaction layout:layout];
} }
case OWSContactOffersAdapter: { case OWSContactOffersAdapter: {
id cacheKey = [self cacheKeyForMessageData:messageData];
OWSContactOffersInteraction *interaction OWSContactOffersInteraction *interaction
= (OWSContactOffersInteraction *)((TSMessageAdapter *)messageData).interaction; = (OWSContactOffersInteraction *)((TSMessageAdapter *)messageData).interaction;
return [self sizeForContactOffers:interaction cacheKey:cacheKey layout:layout]; return [self sizeForContactOffers:interaction layout:layout];
} }
case TSIncomingMessageAdapter: case TSIncomingMessageAdapter:
case TSOutgoingMessageAdapter: case TSOutgoingMessageAdapter:
@ -106,9 +122,8 @@ NS_ASSUME_NONNULL_BEGIN
break; break;
} }
} else if ([messageData isKindOfClass:[OWSCall class]]) { } else if ([messageData isKindOfClass:[OWSCall class]]) {
id cacheKey = [self cacheKeyForMessageData:messageData];
TSInteraction *interaction = ((OWSCall *)messageData).interaction; TSInteraction *interaction = ((OWSCall *)messageData).interaction;
return [self sizeForSystemMessage:interaction cacheKey:cacheKey layout:layout]; return [self sizeForSystemMessage:interaction layout:layout];
} else { } else {
OWSFail(@"Can't size unknown message data type: %@", [messageData class]); OWSFail(@"Can't size unknown message data type: %@", [messageData class]);
} }
@ -126,64 +141,31 @@ NS_ASSUME_NONNULL_BEGIN
} }
- (CGSize)sizeForSystemMessage:(TSInteraction *)interaction - (CGSize)sizeForSystemMessage:(TSInteraction *)interaction
cacheKey:(id)cacheKey
layout:(JSQMessagesCollectionViewFlowLayout *)layout layout:(JSQMessagesCollectionViewFlowLayout *)layout
{ {
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);
OWSAssert(interaction); OWSAssert(interaction);
OWSAssert(cacheKey);
NSValue *cachedSize = [self.cache objectForKey:cacheKey]; return [self.referenceSystemMessageCell bubbleSizeForInteraction:interaction
if (cachedSize != nil) { collectionViewWidth:layout.collectionView.width];
return [cachedSize CGSizeValue];
}
CGSize result = [self.referenceSystemMessageCell bubbleSizeForInteraction:interaction
collectionViewWidth:layout.collectionView.width];
[self.cache setObject:[NSValue valueWithCGSize:result] forKey:cacheKey];
return result;
} }
- (CGSize)sizeForUnreadIndicator:(TSUnreadIndicatorInteraction *)interaction - (CGSize)sizeForUnreadIndicator:(TSUnreadIndicatorInteraction *)interaction
cacheKey:(id)cacheKey
layout:(JSQMessagesCollectionViewFlowLayout *)layout layout:(JSQMessagesCollectionViewFlowLayout *)layout
{ {
OWSAssert(interaction); OWSAssert(interaction);
OWSAssert(cacheKey);
NSValue *cachedSize = [self.cache objectForKey:cacheKey]; return [self.referenceUnreadIndicatorCell bubbleSizeForInteraction:interaction
if (cachedSize != nil) { collectionViewWidth:layout.collectionView.width];
return [cachedSize CGSizeValue];
}
CGSize result = [self.referenceUnreadIndicatorCell bubbleSizeForInteraction:interaction
collectionViewWidth:layout.collectionView.width];
[self.cache setObject:[NSValue valueWithCGSize:result] forKey:cacheKey];
return result;
} }
- (CGSize)sizeForContactOffers:(OWSContactOffersInteraction *)interaction - (CGSize)sizeForContactOffers:(OWSContactOffersInteraction *)interaction
cacheKey:(id)cacheKey
layout:(JSQMessagesCollectionViewFlowLayout *)layout layout:(JSQMessagesCollectionViewFlowLayout *)layout
{ {
OWSAssert(interaction); OWSAssert(interaction);
OWSAssert(cacheKey);
NSValue *cachedSize = [self.cache objectForKey:cacheKey];
if (cachedSize != nil) {
return [cachedSize CGSizeValue];
}
CGSize result = [self.referenceContactOffersCell bubbleSizeForInteraction:interaction return [self.referenceContactOffersCell bubbleSizeForInteraction:interaction
collectionViewWidth:layout.collectionView.width]; collectionViewWidth:layout.collectionView.width];
[self.cache setObject:[NSValue valueWithCGSize:result] forKey:cacheKey];
return result;
} }
/** /**
@ -254,6 +236,18 @@ NS_ASSUME_NONNULL_BEGIN
return @([messageData messageHash]); return @([messageData messageHash]);
} }
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -228,7 +228,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
@property (nonatomic) NSCache *messageAdapterCache; @property (nonatomic) NSCache *messageAdapterCache;
@property (nonatomic) BOOL userHasScrolled; @property (nonatomic) BOOL userHasScrolled;
@property (nonatomic) NSDate *lastMessageSentDate; @property (nonatomic) NSDate *lastMessageSentDate;
@property (nonatomic) NSTimer *scrollLaterTimer;
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper; @property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
@property (nonatomic, nullable) ThreadDynamicInteractions *dynamicInteractions; @property (nonatomic, nullable) ThreadDynamicInteractions *dynamicInteractions;
@ -640,14 +639,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
[self.view layoutSubviews]; [self.view layoutSubviews];
[self scrollToDefaultPosition]; [self scrollToDefaultPosition];
[self.scrollLaterTimer invalidate];
// We want to scroll to the bottom _after_ the layout has been updated.
self.scrollLaterTimer = [NSTimer weakScheduledTimerWithTimeInterval:0.001f
target:self
selector:@selector(scrollToDefaultPosition)
userInfo:nil
repeats:NO];
} }
- (NSIndexPath *_Nullable)indexPathOfUnreadMessagesIndicator - (NSIndexPath *_Nullable)indexPathOfUnreadMessagesIndicator
@ -684,9 +675,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
- (void)scrollToDefaultPosition - (void)scrollToDefaultPosition
{ {
[self.scrollLaterTimer invalidate];
self.scrollLaterTimer = nil;
if (self.isUserScrolling) { if (self.isUserScrolling) {
return; return;
} }
@ -709,9 +697,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
- (void)scrollToUnreadIndicatorAnimated - (void)scrollToUnreadIndicatorAnimated
{ {
[self.scrollLaterTimer invalidate];
self.scrollLaterTimer = nil;
if (self.isUserScrolling) { if (self.isUserScrolling) {
return; return;
} }
@ -2392,17 +2377,11 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
self.collectionView.contentOffset = CGPointMake(0, self.collectionView.contentSize.height - scrollDistanceToBottom); self.collectionView.contentOffset = CGPointMake(0, self.collectionView.contentSize.height - scrollDistanceToBottom);
[self.scrollLaterTimer invalidate];
// Dont auto-scroll afterloading more messagesunless we havemore unseen messages. // Dont auto-scroll afterloading more messagesunless we havemore unseen messages.
// //
// Otherwise, tapping on "load more messages" autoscrolls you downward which is completely wrong. // Otherwise, tapping on "load more messages" autoscrolls you downward which is completely wrong.
if (hasEarlierUnseenMessages) { if (hasEarlierUnseenMessages) {
// We want to scroll to the bottom _after_ the layout has been updated. [self scrollToUnreadIndicatorAnimated];
self.scrollLaterTimer = [NSTimer weakScheduledTimerWithTimeInterval:0.001f
target:self
selector:@selector(scrollToUnreadIndicatorAnimated)
userInfo:nil
repeats:NO];
} }
[self updateLoadEarlierVisible]; [self updateLoadEarlierVisible];
@ -3539,8 +3518,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
[self updateLastVisibleTimestamp]; [self updateLastVisibleTimestamp];
if (scrollToBottom) { if (scrollToBottom) {
[self.scrollLaterTimer invalidate];
self.scrollLaterTimer = nil;
[self scrollToBottomAnimated:shouldAnimateScrollToBottom]; [self scrollToBottomAnimated:shouldAnimateScrollToBottom];
} }
}]; }];
@ -4176,13 +4153,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
BOOL wasAtBottom = [self isScrolledToBottom]; BOOL wasAtBottom = [self isScrolledToBottom];
if (wasAtBottom) { if (wasAtBottom) {
[self.scrollLaterTimer invalidate]; [self scrollToBottomImmediately];
// We want to scroll to the bottom _after_ the layout has been updated.
self.scrollLaterTimer = [NSTimer weakScheduledTimerWithTimeInterval:0.001f
target:self
selector:@selector(scrollToBottomImmediately)
userInfo:nil
repeats:NO];
} }
[self ensureScrollDownButton]; [self ensureScrollDownButton];
@ -4197,8 +4168,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
- (void)scrollToBottomAnimated:(BOOL)animated - (void)scrollToBottomAnimated:(BOOL)animated
{ {
[self.scrollLaterTimer invalidate];
self.scrollLaterTimer = nil;
if (self.isUserScrolling) { if (self.isUserScrolling) {
return; return;

Loading…
Cancel
Save