From b2c8ad2d298c4655f4b589808ebc25cb75c28c76 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 31 Aug 2017 15:13:00 -0400 Subject: [PATCH] Restore scroll state after resetting the conversation view's mapping. // FREEBIE --- .../ConversationView/MessagesViewController.m | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 5a50a253d..1b7806e1c 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -4436,7 +4436,30 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { _shouldObserveDBModifications = shouldObserveDBModifications; if (self.shouldObserveDBModifications) { + // We need to call resetMappings when we _resume_ observing DB modifications, + // since we've been ignore DB modifications so the mappings can be wrong. + // + // resetMappings can however have the side effect of increasing the mapping's + // "window" size. If that happens, we need to restore the scroll state. + + // Snapshot the scroll state by measuring the "distance from top of view to + // bottom of content"; if the mapping's "window" size grows, it will grow + // _upward_. + CGFloat viewTopToContentBottom = self.collectionView.contentSize.height - self.collectionView.contentOffset.y; + + NSUInteger oldCellCount = [self.messageMappings numberOfItemsInGroup:self.thread.uniqueId]; [self resetMappings]; + NSUInteger newCellCount = [self.messageMappings numberOfItemsInGroup:self.thread.uniqueId]; + + // Detect changes in the mapping's "window" size. + if (oldCellCount != newCellCount) { + // There's no way to imperatively force the collection view to layout its + // content, but we can safely use `collectionViewContentSize` to determine + // the new content size. + CGSize newContentSize = [self.collectionView.collectionViewLayout collectionViewContentSize]; + CGPoint newContentOffset = CGPointMake(0, MAX(0, newContentSize.height - viewTopToContentBottom)); + [self.collectionView setContentOffset:newContentOffset animated:NO]; + } } }