Extract more things to TimelineLikeCollectionViewController

This commit is contained in:
Shadowfacts 2022-10-01 15:08:51 -04:00
parent a682c8f5cc
commit 253fb8d27d
3 changed files with 32 additions and 31 deletions

View File

@ -62,6 +62,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
collectionView.delegate = self collectionView.delegate = self
// collectionView.dragDelegate = self // collectionView.dragDelegate = self
registerTimelineLikeCells()
dataSource = createDataSource() dataSource = createDataSource()
applyInitialSnapshot() applyInitialSnapshot()
@ -93,27 +94,14 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
config.text = try! doc.text() config.text = try! doc.text()
cell.contentConfiguration = config 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 return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in
switch itemIdentifier { switch itemIdentifier {
case .status(_, _): case .status(_, _):
return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: itemIdentifier) return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: itemIdentifier)
case .loadingIndicator: case .loadingIndicator:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "loadingIndicator", for: indexPath) as! LoadingCollectionViewCell return loadingIndicatorCell(for: indexPath)
cell.indicator.startAnimating()
return cell
case .confirmLoadMore: case .confirmLoadMore:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "confirmLoadMore", for: indexPath) as! ConfirmLoadMoreCollectionViewCell return confirmLoadMoreCell(for: indexPath)
cell.confirmLoadMore = self.confirmLoadMore
Task {
if case .loadingOlder(_, _) = await controller.state {
cell.isLoading = true
} else {
cell.isLoading = false
}
}
return cell
} }
} }
} }
@ -195,7 +183,7 @@ extension TimelineViewController {
} }
} }
// MARK: - TimelineLikeControllerDelegate // MARK: TimelineLikeControllerDelegate
extension TimelineViewController { extension TimelineViewController {
typealias TimelineItem = String // status ID typealias TimelineItem = String // status ID

View File

@ -42,6 +42,7 @@ protocol TimelineLikeCollectionViewError: Error, Equatable {
static var allCaughtUp: Self { get } static var allCaughtUp: Self { get }
} }
// MARK: TimelineLikeControllerDelegate
extension TimelineLikeCollectionViewController { extension TimelineLikeCollectionViewController {
func canLoadOlder() async -> Bool { func canLoadOlder() async -> Bool {
if Preferences.shared.disableInfiniteScrolling { if Preferences.shared.disableInfiniteScrolling {
@ -185,3 +186,29 @@ extension TimelineLikeCollectionViewController {
await dataSource.apply(snapshot, animatingDifferences: false) 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
}
}

View File

@ -86,11 +86,7 @@ actor TimelineLikeController<Item> {
return return
} }
let token = LoadAttemptToken() 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 { guard await delegate.canLoadOlder() else {
// state = .idle
return return
} }
state = .loadingOlder(token, hasAddedLoadingIndicator: false) state = .loadingOlder(token, hasAddedLoadingIndicator: false)
@ -124,7 +120,6 @@ actor TimelineLikeController<Item> {
case idle case idle
case loadingInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool) case loadingInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
case loadingNewer(LoadAttemptToken) case loadingNewer(LoadAttemptToken)
// case waitingForLoadOlderPermission
case loadingOlder(LoadAttemptToken, hasAddedLoadingIndicator: Bool) case loadingOlder(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
var debugDescription: String { var debugDescription: String {
@ -137,8 +132,6 @@ actor TimelineLikeController<Item> {
return "loadingInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))" return "loadingInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))"
case .loadingNewer(let token): case .loadingNewer(let token):
return "loadingNewer(\(ObjectIdentifier(token)))" return "loadingNewer(\(ObjectIdentifier(token)))"
// case .waitingForLoadOlderPermission:
// return "waitingForLoadOlderPermission"
case .loadingOlder(let token, let hasAddedLoadingIndicator): case .loadingOlder(let token, let hasAddedLoadingIndicator):
return "loadingOlder(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))" return "loadingOlder(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))"
} }
@ -155,7 +148,7 @@ actor TimelineLikeController<Item> {
} }
case .idle: case .idle:
switch to { switch to {
case .loadingNewer(_)/*, .waitingForLoadOlderPermission*/, .loadingOlder(_, _): case .loadingNewer(_), .loadingOlder(_, _):
return true return true
default: default:
return false return false
@ -166,13 +159,6 @@ actor TimelineLikeController<Item> {
return to == .idle return to == .idle
case .loadingOlder(let token, let hasAddedLoadingIndicator): case .loadingOlder(let token, let hasAddedLoadingIndicator):
return to == .idle || (!hasAddedLoadingIndicator && to == .loadingOlder(token, hasAddedLoadingIndicator: true)) return to == .idle || (!hasAddedLoadingIndicator && to == .loadingOlder(token, hasAddedLoadingIndicator: true))
// case .waitingForLoadOlderPermission:
// switch to {
// case .idle, .loadingOlder(_, _):
// return true
// default:
// return false
// }
} }
} }