forked from shadowfacts/Tusker
Add loading indicator to conversation screen
This commit is contained in:
parent
ccd1672e72
commit
63ed3b6e10
|
@ -94,6 +94,9 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
|
||||||
let expandThreadCell = UICollectionView.CellRegistration<ExpandThreadCollectionViewCell, ([ConversationNode], Bool)> { cell, indexPath, item in
|
let expandThreadCell = UICollectionView.CellRegistration<ExpandThreadCollectionViewCell, ([ConversationNode], Bool)> { cell, indexPath, item in
|
||||||
cell.updateUI(childThreads: item.0, inline: item.1)
|
cell.updateUI(childThreads: item.0, inline: item.1)
|
||||||
}
|
}
|
||||||
|
let loadingCell = UICollectionView.CellRegistration<LoadingCollectionViewCell, Void> { cell, indexPath, itemIdentifier in
|
||||||
|
cell.indicator.startAnimating()
|
||||||
|
}
|
||||||
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 let .status(id: id, state: state, prevLink: prevLink, nextLink: nextLink):
|
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):
|
case .expandThread(childThreads: let childThreads, inline: let inline):
|
||||||
return collectionView.dequeueConfiguredReusableCell(using: expandThreadCell, for: indexPath, item: (childThreads, 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) {
|
func addMainStatus(_ status: StatusMO) {
|
||||||
loadViewIfNeeded()
|
loadViewIfNeeded()
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
||||||
snapshot.appendSections([.statuses])
|
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)
|
let mainStatusItem = Item.status(id: mainStatusID, state: mainStatusState, prevLink: status.inReplyToID != nil, nextLink: false)
|
||||||
snapshot.appendItems([mainStatusItem], toSection: .statuses)
|
snapshot.appendItems([mainStatusItem], toSection: .statuses)
|
||||||
|
|
||||||
dataSource.apply(snapshot, animatingDifferences: false)
|
dataSource.apply(snapshot, animatingDifferences: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +142,7 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
|
||||||
await mastodonController.persistentContainer.addAll(statuses: parentStatuses + context.descendants)
|
await mastodonController.persistentContainer.addAll(statuses: parentStatuses + context.descendants)
|
||||||
|
|
||||||
var snapshot = dataSource.snapshot()
|
var snapshot = dataSource.snapshot()
|
||||||
|
snapshot.deleteItems([.loadingIndicator])
|
||||||
let mainStatusItem = Item.status(id: mainStatusID, state: mainStatusState, prevLink: mainStatus.inReplyToID != nil, nextLink: false)
|
let mainStatusItem = Item.status(id: mainStatusID, state: mainStatusState, prevLink: mainStatus.inReplyToID != nil, nextLink: false)
|
||||||
let parentItems = parentIDs.enumerated().map { index, id in
|
let parentItems = parentIDs.enumerated().map { index, id in
|
||||||
Item.status(id: id, state: .unknown, prevLink: index > 0, nextLink: true)
|
Item.status(id: id, state: .unknown, prevLink: index > 0, nextLink: true)
|
||||||
|
@ -299,6 +317,7 @@ extension ConversationCollectionViewController {
|
||||||
enum Item: Hashable {
|
enum Item: Hashable {
|
||||||
case status(id: String, state: CollapseState, prevLink: Bool, nextLink: Bool)
|
case status(id: String, state: CollapseState, prevLink: Bool, nextLink: Bool)
|
||||||
case expandThread(childThreads: [ConversationNode], inline: Bool)
|
case expandThread(childThreads: [ConversationNode], inline: Bool)
|
||||||
|
case loadingIndicator
|
||||||
|
|
||||||
static func ==(lhs: Item, rhs: Item) -> Bool {
|
static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
|
@ -306,6 +325,8 @@ extension ConversationCollectionViewController {
|
||||||
return a == b && aPrev == bPrev && aNext == bNext
|
return a == b && aPrev == bPrev && aNext == bNext
|
||||||
case let (.expandThread(childThreads: a, inline: aInline), .expandThread(childThreads: b, inline: bInline)):
|
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
|
return a.count == b.count && zip(a, b).allSatisfy { $0.status.id == $1.status.id } && aInline == bInline
|
||||||
|
case (.loadingIndicator, .loadingIndicator):
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -324,6 +345,8 @@ extension ConversationCollectionViewController {
|
||||||
hasher.combine(thread.status.id)
|
hasher.combine(thread.status.id)
|
||||||
}
|
}
|
||||||
hasher.combine(inline)
|
hasher.combine(inline)
|
||||||
|
case .loadingIndicator:
|
||||||
|
hasher.combine(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,11 +354,13 @@ extension ConversationCollectionViewController {
|
||||||
|
|
||||||
extension ConversationCollectionViewController: UICollectionViewDelegate {
|
extension ConversationCollectionViewController: UICollectionViewDelegate {
|
||||||
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||||
if case .status(id: let id, _, _, _) = dataSource.itemIdentifier(for: indexPath),
|
switch dataSource.itemIdentifier(for: indexPath) {
|
||||||
id == mainStatusID {
|
case .status(id: let id, state: _, prevLink: _, nextLink: _):
|
||||||
return false
|
return id != mainStatusID
|
||||||
} else {
|
case .expandThread(childThreads: _, inline: _):
|
||||||
return true
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,6 +368,8 @@ extension ConversationCollectionViewController: UICollectionViewDelegate {
|
||||||
switch dataSource.itemIdentifier(for: indexPath) {
|
switch dataSource.itemIdentifier(for: indexPath) {
|
||||||
case nil:
|
case nil:
|
||||||
break
|
break
|
||||||
|
case .loadingIndicator:
|
||||||
|
break
|
||||||
case .status(id: let id, state: let state, _, _):
|
case .status(id: let id, state: let state, _, _):
|
||||||
selected(status: id, state: state.copy())
|
selected(status: id, state: state.copy())
|
||||||
case .expandThread(childThreads: let childThreads, inline: _):
|
case .expandThread(childThreads: let childThreads, inline: _):
|
||||||
|
|
Loading…
Reference in New Issue