Fix signing into API-restricted instances

Closes #556
This commit is contained in:
Shadowfacts 2024-12-28 23:43:50 -05:00
parent 238f246d64
commit cb535196e2
3 changed files with 53 additions and 33 deletions

View File

@ -11,9 +11,15 @@ import Foundation
public struct NodeInfo: Decodable, Sendable, Equatable {
public let version: String
public let software: Software
public let metadata: Metadata
public struct Software: Decodable, Sendable, Equatable {
public let name: String
public let version: String
}
public struct Metadata: Decodable, Sendable, Equatable {
public let nodeName: String
public let nodeDescription: String
}
}

View File

@ -75,13 +75,14 @@ class InstanceSelectorTableViewController: UITableViewController {
dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
switch item {
case let .selected(_, instance):
case let .selected(_, info):
let cell = tableView.dequeueReusableCell(withIdentifier: instanceCell, for: indexPath) as! InstanceTableViewCell
cell.updateUI(instance: instance)
cell.updateUI(info: info)
return cell
case let .recommended(instance):
let cell = tableView.dequeueReusableCell(withIdentifier: instanceCell, for: indexPath) as! InstanceTableViewCell
cell.updateUI(instance: instance)
let info = Info(host: instance.domain, description: instance.description, thumbnail: instance.proxiedThumbnailURL, adult: instance.category == "adult")
cell.updateUI(info: info)
return cell
}
})
@ -164,22 +165,20 @@ class InstanceSelectorTableViewController: UITableViewController {
return
}
let client = Client(baseURL: url, session: .appDefault)
let request = Client.getInstanceV1()
client.run(request) { (response) in
checkSpecificInstance(url: url) { (info) in
var snapshot = self.dataSource.snapshot()
if snapshot.indexOfSection(.selected) != nil {
snapshot.deleteSections([.selected])
}
if case let .success(instance, _) = response {
if let info {
if snapshot.indexOfSection(.recommendedInstances) != nil {
snapshot.insertSections([.selected], beforeSection: .recommendedInstances)
} else {
snapshot.appendSections([.selected])
}
snapshot.appendItems([.selected(url, instance)], toSection: .selected)
snapshot.appendItems([.selected(url, info)], toSection: .selected)
DispatchQueue.main.async {
self.dataSource.apply(snapshot) {
@ -194,6 +193,29 @@ class InstanceSelectorTableViewController: UITableViewController {
}
}
private func checkSpecificInstance(url: URL, completionHandler: @escaping (Info?) -> Void) {
let client = Client(baseURL: url, session: .appDefault)
let request = Client.getInstanceV1()
client.run(request) { response in
switch response {
case .success(let instance, _):
let host = url.host ?? URLComponents(string: instance.uri)?.host ?? instance.uri
let info = Info(host: host, description: instance.shortDescription ?? instance.description, thumbnail: instance.thumbnail, adult: false)
completionHandler(info)
case .failure(_):
Task {
do {
let nodeInfo = try await client.nodeInfo()
let info = Info(host: url.host!, description: nodeInfo.metadata.nodeDescription, thumbnail: nil, adult: false)
completionHandler(info)
} catch {
completionHandler(nil)
}
}
}
}
}
private func loadRecommendedInstances() {
InstanceSelector.getInstances(category: nil) { (response) in
DispatchQueue.main.async {
@ -312,13 +334,13 @@ extension InstanceSelectorTableViewController {
case recommendedInstances
}
enum Item: Equatable, Hashable, Sendable {
case selected(URL, InstanceV1)
case selected(URL, Info)
case recommended(InstanceSelector.Instance)
static func ==(lhs: Item, rhs: Item) -> Bool {
switch (lhs, rhs) {
case let (.selected(urlA, instanceA), .selected(urlB, instanceB)):
return urlA == urlB && instanceA.uri == instanceB.uri
case let (.selected(urlA, _), .selected(urlB, _)):
return urlA == urlB
case let (.recommended(a), .recommended(b)):
return a.domain == b.domain
default:
@ -328,16 +350,21 @@ extension InstanceSelectorTableViewController {
func hash(into hasher: inout Hasher) {
switch self {
case let .selected(url, instance):
case let .selected(url, _):
hasher.combine(0)
hasher.combine(url)
hasher.combine(instance.uri)
case let .recommended(instance):
hasher.combine(1)
hasher.combine(instance.domain)
}
}
}
struct Info: Hashable {
let host: String
let description: String
let thumbnail: URL?
let adult: Bool
}
}
extension InstanceSelectorTableViewController: UISearchResultsUpdating {

View File

@ -16,8 +16,7 @@ class InstanceTableViewCell: UITableViewCell {
@IBOutlet weak var adultLabel: UILabel!
@IBOutlet weak var descriptionTextView: ContentTextView!
var instance: InstanceV1?
var selectorInstance: InstanceSelector.Instance?
private var instance: InstanceSelectorTableViewController.Info?
private var thumbnailTask: Task<Void, Never>?
@ -44,25 +43,14 @@ class InstanceTableViewCell: UITableViewCell {
backgroundConfiguration = .appListGroupedCell(for: state)
}
func updateUI(instance: InstanceSelector.Instance) {
self.selectorInstance = instance
self.instance = nil
domainLabel.text = instance.domain
adultLabel.isHidden = instance.category != "adult"
descriptionTextView.setBodyTextFromHTML(instance.description)
updateThumbnail(url: instance.proxiedThumbnailURL)
}
func updateUI(instance: InstanceV1) {
self.instance = instance
self.selectorInstance = nil
func updateUI(info: InstanceSelectorTableViewController.Info) {
self.instance = info
domainLabel.text = URLComponents(string: instance.uri)?.host ?? instance.uri
adultLabel.isHidden = true
descriptionTextView.setBodyTextFromHTML(instance.shortDescription ?? instance.description)
domainLabel.text = info.host
adultLabel.isHidden = !info.adult
descriptionTextView.setBodyTextFromHTML(info.description)
if let thumbnail = instance.thumbnail {
if let thumbnail = info.thumbnail {
updateThumbnail(url: thumbnail)
} else {
thumbnailImageView.image = nil
@ -85,7 +73,6 @@ class InstanceTableViewCell: UITableViewCell {
thumbnailTask?.cancel()
instance = nil
selectorInstance = nil
}
}