Fix paging

This commit is contained in:
nielsandriesse 2021-02-10 11:55:50 +11:00
parent 1924e01edc
commit 217e4dad38
2 changed files with 25 additions and 17 deletions

View file

@ -19,22 +19,23 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
var contextMenuWindow: ContextMenuWindow? var contextMenuWindow: ContextMenuWindow?
var contextMenuVC: ContextMenuVC? var contextMenuVC: ContextMenuVC?
// Scrolling & paging // Scrolling & paging
private var isUserScrolling = false { didSet { autoLoadMoreIfNeeded() } } private var isUserScrolling = false
private var hasPerformedInitialScroll = false private var hasPerformedInitialScroll = false
private var isLoadingMore = false private var isLoadingMore = false
private var contentOffsetYBeforeUpdate: CGFloat? private var scrollDistanceToBottomBeforeUpdate: CGFloat?
private var contentHeightBeforeUpdate: CGFloat?
private var dbConnection: YapDatabaseConnection { OWSPrimaryStorage.shared().uiDatabaseConnection } private var dbConnection: YapDatabaseConnection { OWSPrimaryStorage.shared().uiDatabaseConnection }
var viewItems: [ConversationViewItem] { viewModel.viewState.viewItems } var viewItems: [ConversationViewItem] { viewModel.viewState.viewItems }
func conversationStyle() -> ConversationStyle { return ConversationStyle(thread: thread) } func conversationStyle() -> ConversationStyle { return ConversationStyle(thread: thread) }
override var inputAccessoryView: UIView? { snInputView } override var inputAccessoryView: UIView? { snInputView }
override var canBecomeFirstResponder: Bool { true } override var canBecomeFirstResponder: Bool { true }
private var tableViewUnobscuredHeight: CGFloat {
let bottomInset = messagesTableView.adjustedContentInset.bottom + ConversationVC.bottomInset
return messagesTableView.bounds.height - bottomInset
}
private var lastPageTop: CGFloat { private var lastPageTop: CGFloat {
let bottomInset = -messagesTableView.adjustedContentInset.bottom - ConversationVC.bottomInset
let tableViewUnobscuredHeight = messagesTableView.bounds.height + bottomInset
return messagesTableView.contentSize.height - tableViewUnobscuredHeight return messagesTableView.contentSize.height - tableViewUnobscuredHeight
} }
@ -250,14 +251,14 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
} }
func conversationViewModelWillLoadMoreItems() { func conversationViewModelWillLoadMoreItems() {
contentHeightBeforeUpdate = messagesTableView.contentSize.height view.layoutIfNeeded()
contentOffsetYBeforeUpdate = messagesTableView.contentOffset.y scrollDistanceToBottomBeforeUpdate = messagesTableView.contentSize.height - messagesTableView.contentOffset.y
} }
func conversationViewModelDidLoadMoreItems() { func conversationViewModelDidLoadMoreItems() {
guard let contentHeightBeforeUpdate = contentHeightBeforeUpdate, let contentOffsetYBeforeUpdate = contentOffsetYBeforeUpdate else { return } guard let scrollDistanceToBottomBeforeUpdate = scrollDistanceToBottomBeforeUpdate else { return }
view.layoutIfNeeded() view.layoutIfNeeded()
messagesTableView.contentOffset.y = (messagesTableView.contentSize.height - contentHeightBeforeUpdate + contentOffsetYBeforeUpdate) messagesTableView.contentOffset.y = messagesTableView.contentSize.height - scrollDistanceToBottomBeforeUpdate
isLoadingMore = false isLoadingMore = false
} }
@ -274,6 +275,14 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
} }
// MARK: General // MARK: General
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func getMediaCache() -> NSCache<NSString, AnyObject> { func getMediaCache() -> NSCache<NSString, AnyObject> {
return mediaCache return mediaCache
} }
@ -291,9 +300,9 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
// Ensure the view is fully up to date before we try to scroll to the bottom, since // Ensure the view is fully up to date before we try to scroll to the bottom, since
// we use the table view's bounds to determine where the bottom is. // we use the table view's bounds to determine where the bottom is.
view.layoutIfNeeded() view.layoutIfNeeded()
let firstContentPageTop = -messagesTableView.adjustedContentInset.top let firstContentPageTop: CGFloat = 0
let destinationY = max(firstContentPageTop, lastPageTop) let contentOffsetY = max(firstContentPageTop, lastPageTop)
messagesTableView.setContentOffset(CGPoint(x: 0, y: destinationY), animated: isAnimated) messagesTableView.setContentOffset(CGPoint(x: 0, y: contentOffsetY), animated: isAnimated)
// TODO: Did scroll to bottom // TODO: Did scroll to bottom
} }
@ -315,7 +324,6 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
guard isMainAppAndActive && viewModel.canLoadMoreItems() && !isLoadingMore guard isMainAppAndActive && viewModel.canLoadMoreItems() && !isLoadingMore
&& messagesTableView.contentOffset.y < ConversationVC.loadMoreThreshold else { return } && messagesTableView.contentOffset.y < ConversationVC.loadMoreThreshold else { return }
isLoadingMore = true isLoadingMore = true
print("[Test] LOAD MORE")
viewModel.loadAnotherPageOfMessages() viewModel.loadAnotherPageOfMessages()
} }

View file

@ -166,12 +166,12 @@ NS_ASSUME_NONNULL_BEGIN
// Always load up to n messages when user arrives. // Always load up to n messages when user arrives.
// //
// The smaller this number is, the faster the conversation can display. // The smaller this number is, the faster the conversation can display.
// To test, shrink you accessability font as much as possible, then count how many 1-line system info messages (our // To test, shrink you accessibility font as much as possible, then count how many 1-line system info messages (our
// shortest cells) can fit on screen at a time on an iPhoneX // shortest cells) can fit on screen at a time on an iPhoneX
// //
// PERF: we could do less messages on shorter (older, slower) devices // PERF: we could do less messages on shorter (older, slower) devices
// PERF: we could cache the cell height, since some messages will be much taller. // PERF: we could cache the cell height, since some messages will be much taller.
static const int kYapDatabasePageSize = 18; static const int kYapDatabasePageSize = 64;
// Never show more than n messages in conversation view when user arrives. // Never show more than n messages in conversation view when user arrives.
static const int kConversationInitialMaxRangeSize = 300; static const int kConversationInitialMaxRangeSize = 300;