forked from shadowfacts/Tusker
Fix crash when fetching recommended instances fails
This commit is contained in:
parent
1d79918a94
commit
85e1e131f6
|
@ -49,6 +49,11 @@ class InstanceSelectorTableViewController: UITableViewController {
|
|||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// disable transparent background when scrolled to top because it gets weird with animating table items in and out
|
||||
let appearance = UINavigationBarAppearance()
|
||||
appearance.configureWithDefaultBackground()
|
||||
navigationItem.scrollEdgeAppearance = appearance
|
||||
|
||||
tableView.register(UINib(nibName: "InstanceTableViewCell", bundle: .main), forCellReuseIdentifier: instanceCell)
|
||||
|
||||
|
@ -120,14 +125,18 @@ class InstanceSelectorTableViewController: UITableViewController {
|
|||
client.run(request) { (response) in
|
||||
var snapshot = self.dataSource.snapshot()
|
||||
if snapshot.indexOfSection(.selected) != nil {
|
||||
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .selected))
|
||||
snapshot.deleteSections([.selected])
|
||||
}
|
||||
|
||||
if case let .success(instance, _) = response {
|
||||
if !snapshot.sectionIdentifiers.contains(.selected) {
|
||||
if snapshot.indexOfSection(.recommendedInstances) != nil {
|
||||
snapshot.insertSections([.selected], beforeSection: .recommendedInstances)
|
||||
} else {
|
||||
snapshot.appendSections([.selected])
|
||||
}
|
||||
|
||||
snapshot.appendItems([.selected(url, instance)], toSection: .selected)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.dataSource.apply(snapshot)
|
||||
}
|
||||
|
@ -137,14 +146,47 @@ class InstanceSelectorTableViewController: UITableViewController {
|
|||
|
||||
private func loadRecommendedInstances() {
|
||||
InstanceSelector.getInstances(category: nil) { (response) in
|
||||
guard case let .success(instances, _) = response else { fatalError() }
|
||||
|
||||
self.recommendedInstances = instances
|
||||
self.filterRecommendedResults()
|
||||
DispatchQueue.main.async {
|
||||
switch response {
|
||||
case let .failure(error):
|
||||
self.showRecommendationsError(error)
|
||||
case let .success(instances, _):
|
||||
self.recommendedInstances = instances
|
||||
self.filterRecommendedResults()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func filterRecommendedResults() {
|
||||
private func showRecommendationsError(_ error: Client.Error) {
|
||||
let footer = UITableViewHeaderFooterView()
|
||||
footer.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.textColor = .secondaryLabel
|
||||
label.textAlignment = .center
|
||||
label.font = .boldSystemFont(ofSize: 17)
|
||||
label.numberOfLines = 0
|
||||
label.text = "Could not fetch suggested instances: \(error.localizedDescription)"
|
||||
|
||||
footer.contentView.addSubview(label)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
label.leadingAnchor.constraint(equalToSystemSpacingAfter: footer.contentView.leadingAnchor, multiplier: 1),
|
||||
footer.contentView.trailingAnchor.constraint(equalToSystemSpacingAfter: label.trailingAnchor, multiplier: 1),
|
||||
label.topAnchor.constraint(equalTo: footer.contentView.topAnchor, constant: 8),
|
||||
label.bottomAnchor.constraint(equalTo: footer.contentView.bottomAnchor, constant: 8),
|
||||
])
|
||||
|
||||
let fittingSize = CGSize(width: tableView.bounds.width - (tableView.safeAreaInsets.left + tableView.safeAreaInsets.right), height: 0)
|
||||
let size = footer.systemLayoutSizeFitting(fittingSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
|
||||
footer.frame = CGRect(origin: .zero, size: size)
|
||||
|
||||
tableView.tableFooterView = footer
|
||||
}
|
||||
|
||||
private func filterRecommendedResults() {
|
||||
let filteredInstances: [InstanceSelector.Instance]
|
||||
if let currentQuery = currentQuery, !currentQuery.isEmpty {
|
||||
filteredInstances = recommendedInstances.filter {
|
||||
|
@ -155,12 +197,20 @@ class InstanceSelectorTableViewController: UITableViewController {
|
|||
}
|
||||
|
||||
var snapshot = self.dataSource.snapshot()
|
||||
snapshot.deleteSections([.recommendedInstances])
|
||||
snapshot.appendSections([.recommendedInstances])
|
||||
snapshot.appendItems(filteredInstances.map { Item.recommended($0) }, toSection: .recommendedInstances)
|
||||
DispatchQueue.main.async {
|
||||
self.dataSource.apply(snapshot)
|
||||
if snapshot.indexOfSection(.recommendedInstances) != nil {
|
||||
let toRemove = snapshot.itemIdentifiers(inSection: .recommendedInstances).filter {
|
||||
if case .recommended(_) = $0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
snapshot.deleteItems(toRemove)
|
||||
} else {
|
||||
snapshot.appendSections([.recommendedInstances])
|
||||
}
|
||||
snapshot.appendItems(filteredInstances.map { Item.recommended($0) }, toSection: .recommendedInstances)
|
||||
self.dataSource.apply(snapshot)
|
||||
}
|
||||
|
||||
// MARK: - Table view delegate
|
||||
|
@ -194,29 +244,30 @@ extension InstanceSelectorTableViewController {
|
|||
case recommended(InstanceSelector.Instance)
|
||||
|
||||
static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
if case let .selected(url, instance) = lhs,
|
||||
case let .selected(otherUrl, other) = rhs {
|
||||
return url == otherUrl && instance.uri == other.uri
|
||||
} else if case let .recommended(instance) = lhs,
|
||||
case let .recommended(other) = rhs {
|
||||
return instance.domain == other.domain
|
||||
switch (lhs, rhs) {
|
||||
case let (.selected(urlA, instanceA), .selected(urlB, instanceB)):
|
||||
return urlA == urlB && instanceA.uri == instanceB.uri
|
||||
case let (.recommended(a), .recommended(b)):
|
||||
return a.domain == b.domain
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
switch self {
|
||||
case let .selected(url, instance):
|
||||
hasher.combine(Section.selected)
|
||||
hasher.combine(0)
|
||||
hasher.combine(url)
|
||||
hasher.combine(instance.uri)
|
||||
case let .recommended(instance):
|
||||
hasher.combine(Section.recommendedInstances)
|
||||
hasher.combine(1)
|
||||
hasher.combine(instance.domain)
|
||||
}
|
||||
}
|
||||
}
|
||||
class DataSource: UITableViewDiffableDataSource<Section, Item> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue