Stop stealing away the timeline List's internal UITableViewDelegate. Fix context menus not working.

This commit is contained in:
Stefan Ceriu
2022-04-08 14:05:21 +03:00
parent e20c699298
commit 6b42f7cc3d
@@ -132,8 +132,12 @@ private class TableViewObserver: NSObject, UITableViewDelegate {
} }
private let topDetectionOffset: CGFloat private let topDetectionOffset: CGFloat
private var contentOffsetObserverToken: NSKeyValueObservation?
private var isAtTop: Bool = false private var isAtTop: Bool = false
private var offsetDetails: ContentOffsetDetails? private var offsetDetails: ContentOffsetDetails?
private var draggingInitiated = false
private(set) var tableView: UITableView? private(set) var tableView: UITableView?
@@ -149,7 +153,13 @@ private class TableViewObserver: NSObject, UITableViewDelegate {
self.topDetectionOffset = topDetectionOffset self.topDetectionOffset = topDetectionOffset
super.init() super.init()
tableView.delegate = self // Don't attempt stealing the UITableView delegate away from the List.
// Doing so results in undefined behavior e.g. context menus not working
contentOffsetObserverToken = tableView.observe(\.contentOffset, options: .new, changeHandler: { [weak self] _, _ in
self?.handleScrollViewScroll()
})
tableView.panGestureRecognizer.addTarget(self, action: #selector(handlePanGesture(_:)))
} }
func saveCurrentOffset() { func saveCurrentOffset() {
@@ -223,28 +233,39 @@ private class TableViewObserver: NSObject, UITableViewDelegate {
tableView.scrollToRow(at: .init(row: currentItemCount - 1, section: 0), at: .bottom, animated: false) tableView.scrollToRow(at: .init(row: currentItemCount - 1, section: 0), at: .bottom, animated: false)
} }
// MARK: - UIScrollViewDelegate // MARK: - Private
func scrollViewDidScroll(_ scrollView: UIScrollView) { private func handleScrollViewScroll() {
let isTopVisible = isTopVisible guard let tableView = self.tableView else {
if isTopVisible && isAtTop != isTopVisible { return
scrollViewDidReachTop.send(())
} }
isAtTop = isTopVisible let isTopVisible = self.isTopVisible
} if self.isTopVisible && self.isAtTop != isTopVisible {
self.scrollViewDidReachTop.send(())
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }
scrollViewDidRest.send(())
} self.isAtTop = isTopVisible
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerating: Bool) { if !self.draggingInitiated && tableView.isDragging {
if decelerating == false { self.draggingInitiated = true
scrollViewDidRest.send(()) } else if self.draggingInitiated && !tableView.isDragging {
self.draggingInitiated = false
self.scrollViewDidRest.send(())
} }
} }
// MARK: - Private @objc private func handlePanGesture(_ sender: UIPanGestureRecognizer) {
guard let tableView = self.tableView,
sender.state == .ended,
draggingInitiated == true,
!tableView.isDecelerating else {
return
}
self.draggingInitiated = false
self.scrollViewDidRest.send(())
}
private var isBottomVisible: Bool { private var isBottomVisible: Bool {
guard let scrollView = tableView else { guard let scrollView = tableView else {