Fix a timeline jump triggered by pagination during an interactive scroll. (#2870)

This commit is contained in:
Doug
2024-05-21 09:19:25 +01:00
committed by GitHub
parent 711e36602e
commit 8027e665ad
@@ -59,8 +59,7 @@ class TimelineTableViewController: UIViewController {
var timelineStyle: TimelineStyle var timelineStyle: TimelineStyle
var timelineItemsDictionary = OrderedDictionary<String, RoomTimelineItemViewState>() { var timelineItemsDictionary = OrderedDictionary<String, RoomTimelineItemViewState>() {
didSet { didSet {
if !isLive, isDraggingScrollView { guard canApplySnapshot else {
// Forward pagination doesn't play well with the user scrolling, so we wait for it to stop.
hasPendingItems = true hasPendingItems = true
return return
} }
@@ -75,13 +74,34 @@ class TimelineTableViewController: UIViewController {
} }
} }
/// Whether or not it is safe to update the data source with the latest items.
private var canApplySnapshot: Bool {
if isLive {
// Backward pagination jumps if items are inserted whilst actively dragging.
!isDraggingScrollView
} else {
// Forward pagination breaks inertial scrolling when fixing the offset.
!scrollViewIsScrolling
}
}
/// There are pending items in `timelineItemsDictionary` that haven't been applied to the data source. /// There are pending items in `timelineItemsDictionary` that haven't been applied to the data source.
private var hasPendingItems = false private var hasPendingItems = false
/// The user is dragging the scroll view (or it is still decelerating after a drag). /// The scroll view is scrolling either directly with a drag or indirectly with inertia.
private var scrollViewIsScrolling = false {
didSet {
if !scrollViewIsScrolling, hasPendingItems, !isLive {
hasPendingItems = false
applySnapshot()
}
}
}
/// The scroll view is being dragged by the user (doesn't include scrolling with inertia)
private var isDraggingScrollView = false { private var isDraggingScrollView = false {
didSet { didSet {
if !isDraggingScrollView, hasPendingItems { if !isDraggingScrollView, hasPendingItems, isLive {
hasPendingItems = false hasPendingItems = false
applySnapshot() applySnapshot()
} }
@@ -415,18 +435,21 @@ extension TimelineTableViewController: UITableViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isDraggingScrollView = true isDraggingScrollView = true
scrollViewIsScrolling = true
} }
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
sendLastVisibleItemReadReceipt() sendLastVisibleItemReadReceipt()
if !decelerate {
isDraggingScrollView = false isDraggingScrollView = false
if !decelerate {
scrollViewIsScrolling = false
} }
} }
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
sendLastVisibleItemReadReceipt() sendLastVisibleItemReadReceipt()
isDraggingScrollView = false scrollViewIsScrolling = false
} }
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {