diff --git a/Tusker/Screens/Timeline/TimelineViewController.swift b/Tusker/Screens/Timeline/TimelineViewController.swift index 7d41b321..0ef4b009 100644 --- a/Tusker/Screens/Timeline/TimelineViewController.swift +++ b/Tusker/Screens/Timeline/TimelineViewController.swift @@ -62,6 +62,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro collectionView.delegate = self // collectionView.dragDelegate = self + registerTimelineLikeCells() dataSource = createDataSource() applyInitialSnapshot() @@ -93,27 +94,14 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro config.text = try! doc.text() cell.contentConfiguration = config } - collectionView.register(LoadingCollectionViewCell.self, forCellWithReuseIdentifier: "loadingIndicator") - collectionView.register(ConfirmLoadMoreCollectionViewCell.self, forCellWithReuseIdentifier: "confirmLoadMore") return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in switch itemIdentifier { case .status(_, _): return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: itemIdentifier) case .loadingIndicator: - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "loadingIndicator", for: indexPath) as! LoadingCollectionViewCell - cell.indicator.startAnimating() - return cell + return loadingIndicatorCell(for: indexPath) case .confirmLoadMore: - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "confirmLoadMore", for: indexPath) as! ConfirmLoadMoreCollectionViewCell - cell.confirmLoadMore = self.confirmLoadMore - Task { - if case .loadingOlder(_, _) = await controller.state { - cell.isLoading = true - } else { - cell.isLoading = false - } - } - return cell + return confirmLoadMoreCell(for: indexPath) } } } @@ -195,7 +183,7 @@ extension TimelineViewController { } } -// MARK: - TimelineLikeControllerDelegate +// MARK: TimelineLikeControllerDelegate extension TimelineViewController { typealias TimelineItem = String // status ID diff --git a/Tusker/Screens/Utilities/TimelineLikeCollectionViewController.swift b/Tusker/Screens/Utilities/TimelineLikeCollectionViewController.swift index ee1e5383..f75a78c6 100644 --- a/Tusker/Screens/Utilities/TimelineLikeCollectionViewController.swift +++ b/Tusker/Screens/Utilities/TimelineLikeCollectionViewController.swift @@ -42,6 +42,7 @@ protocol TimelineLikeCollectionViewError: Error, Equatable { static var allCaughtUp: Self { get } } +// MARK: TimelineLikeControllerDelegate extension TimelineLikeCollectionViewController { func canLoadOlder() async -> Bool { if Preferences.shared.disableInfiniteScrolling { @@ -185,3 +186,29 @@ extension TimelineLikeCollectionViewController { await dataSource.apply(snapshot, animatingDifferences: false) } } + +extension TimelineLikeCollectionViewController { + func registerTimelineLikeCells() { + collectionView.register(LoadingCollectionViewCell.self, forCellWithReuseIdentifier: "loadingIndicator") + collectionView.register(ConfirmLoadMoreCollectionViewCell.self, forCellWithReuseIdentifier: "confirmLoadMore") + } + + func loadingIndicatorCell(for indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "loadingIndicator", for: indexPath) as! LoadingCollectionViewCell + cell.indicator.startAnimating() + return cell + } + + func confirmLoadMoreCell(for indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "confirmLoadMore", for: indexPath) as! ConfirmLoadMoreCollectionViewCell + cell.confirmLoadMore = self.confirmLoadMore + Task { + if case .loadingOlder(_, _) = await controller.state { + cell.isLoading = true + } else { + cell.isLoading = false + } + } + return cell + } +} diff --git a/Tusker/TimelineLikeController.swift b/Tusker/TimelineLikeController.swift index 1bd558c2..9f53e1ed 100644 --- a/Tusker/TimelineLikeController.swift +++ b/Tusker/TimelineLikeController.swift @@ -86,11 +86,7 @@ actor TimelineLikeController { return } let token = LoadAttemptToken() - // TODO: does the waiting state need to include the token? - // TODO: does this even need to be a separate state? maybe we should just await the delegate's permission, since it can suspend until user input. then the prompt could appear, and the user could scroll back to the top and still be able to refresh -// state = .waitingForLoadOlderPermission guard await delegate.canLoadOlder() else { -// state = .idle return } state = .loadingOlder(token, hasAddedLoadingIndicator: false) @@ -124,7 +120,6 @@ actor TimelineLikeController { case idle case loadingInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool) case loadingNewer(LoadAttemptToken) -// case waitingForLoadOlderPermission case loadingOlder(LoadAttemptToken, hasAddedLoadingIndicator: Bool) var debugDescription: String { @@ -137,8 +132,6 @@ actor TimelineLikeController { return "loadingInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))" case .loadingNewer(let token): return "loadingNewer(\(ObjectIdentifier(token)))" -// case .waitingForLoadOlderPermission: -// return "waitingForLoadOlderPermission" case .loadingOlder(let token, let hasAddedLoadingIndicator): return "loadingOlder(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))" } @@ -155,7 +148,7 @@ actor TimelineLikeController { } case .idle: switch to { - case .loadingNewer(_)/*, .waitingForLoadOlderPermission*/, .loadingOlder(_, _): + case .loadingNewer(_), .loadingOlder(_, _): return true default: return false @@ -166,13 +159,6 @@ actor TimelineLikeController { return to == .idle case .loadingOlder(let token, let hasAddedLoadingIndicator): return to == .idle || (!hasAddedLoadingIndicator && to == .loadingOlder(token, hasAddedLoadingIndicator: true)) -// case .waitingForLoadOlderPermission: -// switch to { -// case .idle, .loadingOlder(_, _): -// return true -// default: -// return false -// } } }