Fix a race condition when refreshing My Profile before initial load is complete

This commit is contained in:
Shadowfacts 2022-03-28 22:58:34 -04:00
parent 781c37fbae
commit f31c909517
2 changed files with 19 additions and 7 deletions

View File

@ -40,6 +40,11 @@ class ProfileStatusesViewController: DiffableTimelineLikeTableViewController<Pro
super.viewDidLoad() super.viewDidLoad()
tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: .main), forCellReuseIdentifier: "statusCell") tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: .main), forCellReuseIdentifier: "statusCell")
// setup the initial snapshot with the sections in the right order, so we don't have to worry about order later
var snapshot = Snapshot()
snapshot.appendSections([.pinned, .statuses])
dataSource.apply(snapshot, animatingDifferences: false)
} }
func updateUI(account: AccountMO) { func updateUI(account: AccountMO) {
@ -72,6 +77,10 @@ class ProfileStatusesViewController: DiffableTimelineLikeTableViewController<Pro
} }
getStatuses { (response) in getStatuses { (response) in
guard self.state == .loadingInitial else {
return
}
switch response { switch response {
case let .failure(error): case let .failure(error):
completion(.failure(.client(error))) completion(.failure(.client(error)))
@ -83,7 +92,6 @@ class ProfileStatusesViewController: DiffableTimelineLikeTableViewController<Pro
self.mastodonController.persistentContainer.addAll(statuses: statuses) { self.mastodonController.persistentContainer.addAll(statuses: statuses) {
DispatchQueue.main.async { DispatchQueue.main.async {
var snapshot = self.dataSource.snapshot() var snapshot = self.dataSource.snapshot()
snapshot.appendSections([.statuses])
snapshot.appendItems(statuses.map { Item(id: $0.id, state: .unknown) }, toSection: .statuses) snapshot.appendItems(statuses.map { Item(id: $0.id, state: .unknown) }, toSection: .statuses)
if self.kind == .statuses { if self.kind == .statuses {
self.loadPinnedStatuses(snapshot: { snapshot }, completion: completion) self.loadPinnedStatuses(snapshot: { snapshot }, completion: completion)
@ -110,10 +118,7 @@ class ProfileStatusesViewController: DiffableTimelineLikeTableViewController<Pro
self.mastodonController.persistentContainer.addAll(statuses: statuses) { self.mastodonController.persistentContainer.addAll(statuses: statuses) {
DispatchQueue.main.async { DispatchQueue.main.async {
var snapshot = snapshot() var snapshot = snapshot()
if snapshot.indexOfSection(.pinned) != nil { snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .pinned))
snapshot.deleteSections([.pinned])
}
snapshot.insertSections([.pinned], beforeSection: .statuses)
snapshot.appendItems(statuses.map { Item(id: $0.id, state: .unknown) }, toSection: .pinned) snapshot.appendItems(statuses.map { Item(id: $0.id, state: .unknown) }, toSection: .pinned)
completion(.success(snapshot)) completion(.success(snapshot))
} }
@ -209,7 +214,9 @@ class ProfileStatusesViewController: DiffableTimelineLikeTableViewController<Pro
override func refresh() { override func refresh() {
super.refresh() super.refresh()
if kind == .statuses { // only refresh pinned if the super call actually succeded (put the state into .loadingNewer)
if state == .loadingNewer,
kind == .statuses {
loadPinnedStatuses(snapshot: dataSource.snapshot) { (result) in loadPinnedStatuses(snapshot: dataSource.snapshot) { (result) in
switch result { switch result {
case .failure(_): case .failure(_):

View File

@ -195,7 +195,12 @@ class DiffableTimelineLikeTableViewController<Section: Hashable & CaseIterable,
// MARK: - RefreshableViewController // MARK: - RefreshableViewController
func refresh() { func refresh() {
guard state != .loadingNewer else { return } // if we're unloaded, there's nothing "newer" to load
// if we're performing some other operation, we don't want to step on its toes
guard state == .loaded else {
self.refreshControl?.endRefreshing()
return
}
state = .loadingNewer state = .loadingNewer