Add paginated panel loading

This commit is contained in:
Georg Bauer
2026-07-31 15:02:21 +02:00
parent 228879da15
commit 33f9eb809c
11 changed files with 1104 additions and 290 deletions

View File

@@ -29,6 +29,12 @@ extension UIViewController {
class RefreshingTableViewController: UITableViewController {
private let spinner = UIActivityIndicatorView(style: .medium)
var loadingTask: Task<Void, Never>?
private lazy var moreButton = UIButton(
configuration: .plain(),
primaryAction: UIAction { [weak self] _ in self?.requestMoreContent() }
)
private var hasMoreContent = false
private var loadingMore = false
init() {
super.init(style: .plain)
@@ -46,6 +52,8 @@ class RefreshingTableViewController: UITableViewController {
func loadContent(refreshing: Bool) {}
func loadMoreContent() {}
func beginLoading(refreshing: Bool) {
if !refreshing { beginNavigationLoading(spinner) }
}
@@ -55,6 +63,58 @@ class RefreshingTableViewController: UITableViewController {
refreshControl?.endRefreshing()
}
func resetPagination() {
hasMoreContent = false
loadingMore = false
tableView.tableFooterView = nil
}
func finishPagination(hasMore: Bool) {
hasMoreContent = hasMore
loadingMore = false
var configuration = moreButton.configuration
configuration?.title = "Pull up or tap to load more"
configuration?.showsActivityIndicator = false
moreButton.configuration = configuration
moreButton.accessibilityLabel = "Load more results"
tableView.tableFooterView = hasMore ? paginationFooter() : nil
}
func failPagination() {
loadingMore = false
finishPagination(hasMore: hasMoreContent)
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard scrollView.isDragging, hasMoreContent, !loadingMore else { return }
let bottom = max(
-scrollView.adjustedContentInset.top,
scrollView.contentSize.height
+ scrollView.adjustedContentInset.bottom
- scrollView.bounds.height
)
if scrollView.contentOffset.y > bottom + 60 { requestMoreContent() }
}
private func requestMoreContent() {
guard hasMoreContent, !loadingMore else { return }
loadingMore = true
var configuration = moreButton.configuration
configuration?.title = "Loading more…"
configuration?.showsActivityIndicator = true
moreButton.configuration = configuration
moreButton.accessibilityLabel = "Loading more results"
loadMoreContent()
}
private func paginationFooter() -> UIView {
let footer = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 56))
moreButton.frame = footer.bounds
moreButton.autoresizingMask = [.flexibleWidth, .flexibleHeight]
footer.addSubview(moreButton)
return footer
}
@objc private func refreshRequested() {
loadContent(refreshing: true)
}