diff --git a/Tusker/Screens/Explore/TrendsViewController.swift b/Tusker/Screens/Explore/TrendsViewController.swift index 711d82c9..6116763e 100644 --- a/Tusker/Screens/Explore/TrendsViewController.swift +++ b/Tusker/Screens/Explore/TrendsViewController.swift @@ -42,6 +42,12 @@ class TrendsViewController: UIViewController, CollectionViewController { let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in let sectionIdentifier = self.dataSource.snapshot().sectionIdentifiers[sectionIndex] switch sectionIdentifier { + case .loadingIndicator: + var listConfig = UICollectionLayoutListConfiguration(appearance: .grouped) + listConfig.backgroundColor = .appGroupedBackground + listConfig.showsSeparators = false + return .list(using: listConfig, layoutEnvironment: environment) + case .trendingHashtags: var listConfig = UICollectionLayoutListConfiguration(appearance: .grouped) listConfig.headerMode = .supplementary @@ -107,6 +113,9 @@ class TrendsViewController: UIViewController, CollectionViewController { headerView.contentConfiguration = config } + let loadingCell = UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in + cell.indicator.startAnimating() + } let trendingHashtagCell = UICollectionView.CellRegistration { (cell, indexPath, hashtag) in cell.updateUI(hashtag: hashtag) } @@ -125,7 +134,7 @@ class TrendsViewController: UIViewController, CollectionViewController { let moreCell = UICollectionView.SupplementaryRegistration(elementKind: UICollectionView.elementKindSectionFooter) { [unowned self] supplementaryView, elementKind, indexPath in supplementaryView.delegate = self switch self.dataSource.sectionIdentifier(for: indexPath.section) { - case nil, .trendingStatuses: + case nil, .loadingIndicator, .trendingStatuses: fatalError() case .trendingHashtags: supplementaryView.updateUI(.hashtags) @@ -138,6 +147,9 @@ class TrendsViewController: UIViewController, CollectionViewController { let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in switch item { + case .loadingIndicator: + return collectionView.dequeueConfiguredReusableCell(using: loadingCell, for: indexPath, item: ()) + case let .tag(hashtag): return collectionView.dequeueConfiguredReusableCell(using: trendingHashtagCell, for: indexPath, item: hashtag) @@ -189,6 +201,11 @@ class TrendsViewController: UIViewController, CollectionViewController { } var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections([.loadingIndicator]) + snapshot.appendItems([.loadingIndicator]) + await apply(snapshot: snapshot) + + snapshot = NSDiffableDataSourceSnapshot() let hashtagsReq = Client.getTrendingHashtags(limit: 5) let hashtags = try? await mastodonController.run(hashtagsReq).0 @@ -271,13 +288,16 @@ class TrendsViewController: UIViewController, CollectionViewController { extension TrendsViewController { enum Section { + case loadingIndicator case trendingHashtags case trendingLinks case profileSuggestions case trendingStatuses - var title: String { + var title: String? { switch self { + case .loadingIndicator: + return nil case .trendingHashtags: return "Trending Hashtags" case .trendingLinks: @@ -290,6 +310,7 @@ extension TrendsViewController { } } enum Item: Equatable, Hashable { + case loadingIndicator case status(String, CollapseState) case tag(Hashtag) case link(Card) @@ -297,6 +318,8 @@ extension TrendsViewController { static func == (lhs: Item, rhs: Item) -> Bool { switch (lhs, rhs) { + case (.loadingIndicator, .loadingIndicator): + return true case let (.status(a, _), .status(b, _)): return a == b case let (.tag(a), .tag(b)): @@ -312,6 +335,8 @@ extension TrendsViewController { func hash(into hasher: inout Hasher) { switch self { + case .loadingIndicator: + hasher.combine("loadingIndicator") case let .status(id, _): hasher.combine("status") hasher.combine(id) @@ -326,15 +351,31 @@ extension TrendsViewController { hasher.combine(id) } } + + var shouldSelect: Bool { + switch self { + case .loadingIndicator: + return false + default: + return true + } + } } } extension TrendsViewController: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + return dataSource.itemIdentifier(for: indexPath)?.shouldSelect ?? false + } + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let item = dataSource.itemIdentifier(for: indexPath) else { return } switch item { + case .loadingIndicator: + return + case let .tag(hashtag): show(HashtagTimelineViewController(for: hashtag, mastodonController: mastodonController), sender: nil) @@ -358,6 +399,9 @@ extension TrendsViewController: UICollectionViewDelegate { } switch item { + case .loadingIndicator: + return nil + case let .tag(hashtag): return UIContextMenuConfiguration(identifier: nil) { HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController) @@ -443,6 +487,9 @@ extension TrendsViewController: UICollectionViewDragDelegate { return [] } switch item { + case .loadingIndicator: + return [] + case let .tag(hashtag): guard let url = URL(hashtag.url) else { return []