/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import IGListKit import UIKit final class LoadMoreViewController: UIViewController, ListAdapterDataSource, UIScrollViewDelegate { lazy var adapter: ListAdapter = { return ListAdapter(updater: ListAdapterUpdater(), viewController: self) }() let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) lazy var items: [Int] = { // Load more on iPad in order for the content size to be bigger than its screen. UIDevice.current.userInterfaceIdiom == .pad ? Array(0...30) : Array(0...15) }() var loading = false let spinToken = "spinner" override func viewDidLoad() { super.viewDidLoad() collectionView.alwaysBounceVertical = true view.addSubview(collectionView) adapter.collectionView = collectionView adapter.dataSource = self adapter.scrollViewDelegate = self } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() collectionView.frame = view.bounds collectionView.collectionViewLayout.invalidateLayout() } // MARK: ListAdapterDataSource func objects(for listAdapter: ListAdapter) -> [ListDiffable] { var objects = items as [ListDiffable] if loading { objects.append(spinToken as ListDiffable) } return objects } func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController { if let obj = object as? String, obj == spinToken { return spinnerSectionController() } else { return LabelSectionController() } } func emptyView(for listAdapter: ListAdapter) -> UIView? { return nil } // MARK: UIScrollViewDelegate func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { let distance = scrollView.contentSize.height - (targetContentOffset.pointee.y + scrollView.bounds.height) if !loading && distance < 200 { loading = true adapter.performUpdates(animated: true, completion: nil) DispatchQueue.global(qos: .default).async { // fake background loading task sleep(2) DispatchQueue.main.async { self.loading = false let itemCount = self.items.count self.items.append(contentsOf: Array(itemCount..