diff --git a/Tusker/Screens/Conversation/ConversationCollectionViewController.swift b/Tusker/Screens/Conversation/ConversationCollectionViewController.swift index 5bd35b1f..57915d12 100644 --- a/Tusker/Screens/Conversation/ConversationCollectionViewController.swift +++ b/Tusker/Screens/Conversation/ConversationCollectionViewController.swift @@ -94,6 +94,9 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont let expandThreadCell = UICollectionView.CellRegistration { cell, indexPath, item in cell.updateUI(childThreads: item.0, inline: item.1) } + let loadingCell = UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in + cell.indicator.startAnimating() + } return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in switch itemIdentifier { case let .status(id: id, state: state, prevLink: prevLink, nextLink: nextLink): @@ -104,17 +107,31 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont } case .expandThread(childThreads: let childThreads, inline: let inline): return collectionView.dequeueConfiguredReusableCell(using: expandThreadCell, for: indexPath, item: (childThreads, inline)) + case .loadingIndicator: + return collectionView.dequeueConfiguredReusableCell(using: loadingCell, for: indexPath, item: ()) } } } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + clearSelectionOnAppear(animated: animated) + } + func addMainStatus(_ status: StatusMO) { loadViewIfNeeded() var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.statuses]) + + if status.inReplyToID != nil { + snapshot.appendItems([.loadingIndicator], toSection: .statuses) + } + let mainStatusItem = Item.status(id: mainStatusID, state: mainStatusState, prevLink: status.inReplyToID != nil, nextLink: false) snapshot.appendItems([mainStatusItem], toSection: .statuses) + dataSource.apply(snapshot, animatingDifferences: false) } @@ -125,6 +142,7 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont await mastodonController.persistentContainer.addAll(statuses: parentStatuses + context.descendants) var snapshot = dataSource.snapshot() + snapshot.deleteItems([.loadingIndicator]) let mainStatusItem = Item.status(id: mainStatusID, state: mainStatusState, prevLink: mainStatus.inReplyToID != nil, nextLink: false) let parentItems = parentIDs.enumerated().map { index, id in Item.status(id: id, state: .unknown, prevLink: index > 0, nextLink: true) @@ -299,6 +317,7 @@ extension ConversationCollectionViewController { enum Item: Hashable { case status(id: String, state: CollapseState, prevLink: Bool, nextLink: Bool) case expandThread(childThreads: [ConversationNode], inline: Bool) + case loadingIndicator static func ==(lhs: Item, rhs: Item) -> Bool { switch (lhs, rhs) { @@ -306,6 +325,8 @@ extension ConversationCollectionViewController { return a == b && aPrev == bPrev && aNext == bNext case let (.expandThread(childThreads: a, inline: aInline), .expandThread(childThreads: b, inline: bInline)): return a.count == b.count && zip(a, b).allSatisfy { $0.status.id == $1.status.id } && aInline == bInline + case (.loadingIndicator, .loadingIndicator): + return true default: return false } @@ -324,6 +345,8 @@ extension ConversationCollectionViewController { hasher.combine(thread.status.id) } hasher.combine(inline) + case .loadingIndicator: + hasher.combine(2) } } } @@ -331,11 +354,13 @@ extension ConversationCollectionViewController { extension ConversationCollectionViewController: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { - if case .status(id: let id, _, _, _) = dataSource.itemIdentifier(for: indexPath), - id == mainStatusID { - return false - } else { + switch dataSource.itemIdentifier(for: indexPath) { + case .status(id: let id, state: _, prevLink: _, nextLink: _): + return id != mainStatusID + case .expandThread(childThreads: _, inline: _): return true + default: + return false } } @@ -343,6 +368,8 @@ extension ConversationCollectionViewController: UICollectionViewDelegate { switch dataSource.itemIdentifier(for: indexPath) { case nil: break + case .loadingIndicator: + break case .status(id: let id, state: let state, _, _): selected(status: id, state: state.copy()) case .expandThread(childThreads: let childThreads, inline: _):