// // LoadMoreConfigurableTableViewContainer.swift // Mastodon // // Created by sxiaojian on 2021/2/3. // import UIKit import GameplayKit /// The tableView container driven by state machines with "LoadMore" logic protocol LoadMoreConfigurableTableViewContainer: UIViewController { associatedtype BottomLoaderTableViewCell: UITableViewCell associatedtype LoadingState: GKState var loadMoreConfigurableTableView: UITableView { get } var loadMoreConfigurableStateMachine: GKStateMachine { get } func handleScrollViewDidScroll(_ scrollView: UIScrollView) } extension LoadMoreConfigurableTableViewContainer { func handleScrollViewDidScroll(_ scrollView: UIScrollView) { guard scrollView === loadMoreConfigurableTableView else { return } // check if current scroll position is the bottom of table let contentOffsetY = loadMoreConfigurableTableView.contentOffset.y let bottomVisiblePageContentOffsetY = loadMoreConfigurableTableView.contentSize.height - (1.5 * loadMoreConfigurableTableView.visibleSize.height) guard contentOffsetY > bottomVisiblePageContentOffsetY else { return } let cells = loadMoreConfigurableTableView.visibleCells.compactMap { $0 as? BottomLoaderTableViewCell } guard let loaderTableViewCell = cells.first else { return } if let tabBar = tabBarController?.tabBar, let window = view.window { let loaderTableViewCellFrameInWindow = loadMoreConfigurableTableView.convert(loaderTableViewCell.frame, to: nil) let windowHeight = window.frame.height let loaderAppear = (loaderTableViewCellFrameInWindow.origin.y + 0.8 * loaderTableViewCell.frame.height) < (windowHeight - tabBar.frame.height) if loaderAppear { loadMoreConfigurableStateMachine.enter(LoadingState.self) } else { // do nothing } } else { loadMoreConfigurableStateMachine.enter(LoadingState.self) } } }