parent
238f246d64
commit
cb535196e2
@ -11,9 +11,15 @@ import Foundation
|
|||||||
public struct NodeInfo: Decodable, Sendable, Equatable {
|
public struct NodeInfo: Decodable, Sendable, Equatable {
|
||||||
public let version: String
|
public let version: String
|
||||||
public let software: Software
|
public let software: Software
|
||||||
|
public let metadata: Metadata
|
||||||
|
|
||||||
public struct Software: Decodable, Sendable, Equatable {
|
public struct Software: Decodable, Sendable, Equatable {
|
||||||
public let name: String
|
public let name: String
|
||||||
public let version: String
|
public let version: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct Metadata: Decodable, Sendable, Equatable {
|
||||||
|
public let nodeName: String
|
||||||
|
public let nodeDescription: String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,13 +75,14 @@ class InstanceSelectorTableViewController: UITableViewController {
|
|||||||
|
|
||||||
dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
|
dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
|
||||||
switch item {
|
switch item {
|
||||||
case let .selected(_, instance):
|
case let .selected(_, info):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: instanceCell, for: indexPath) as! InstanceTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: instanceCell, for: indexPath) as! InstanceTableViewCell
|
||||||
cell.updateUI(instance: instance)
|
cell.updateUI(info: info)
|
||||||
return cell
|
return cell
|
||||||
case let .recommended(instance):
|
case let .recommended(instance):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: instanceCell, for: indexPath) as! InstanceTableViewCell
|
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
|
return cell
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -164,22 +165,20 @@ class InstanceSelectorTableViewController: UITableViewController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = Client(baseURL: url, session: .appDefault)
|
checkSpecificInstance(url: url) { (info) in
|
||||||
let request = Client.getInstanceV1()
|
|
||||||
client.run(request) { (response) in
|
|
||||||
var snapshot = self.dataSource.snapshot()
|
var snapshot = self.dataSource.snapshot()
|
||||||
if snapshot.indexOfSection(.selected) != nil {
|
if snapshot.indexOfSection(.selected) != nil {
|
||||||
snapshot.deleteSections([.selected])
|
snapshot.deleteSections([.selected])
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .success(instance, _) = response {
|
if let info {
|
||||||
if snapshot.indexOfSection(.recommendedInstances) != nil {
|
if snapshot.indexOfSection(.recommendedInstances) != nil {
|
||||||
snapshot.insertSections([.selected], beforeSection: .recommendedInstances)
|
snapshot.insertSections([.selected], beforeSection: .recommendedInstances)
|
||||||
} else {
|
} else {
|
||||||
snapshot.appendSections([.selected])
|
snapshot.appendSections([.selected])
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot.appendItems([.selected(url, instance)], toSection: .selected)
|
snapshot.appendItems([.selected(url, info)], toSection: .selected)
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.dataSource.apply(snapshot) {
|
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() {
|
private func loadRecommendedInstances() {
|
||||||
InstanceSelector.getInstances(category: nil) { (response) in
|
InstanceSelector.getInstances(category: nil) { (response) in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@ -312,13 +334,13 @@ extension InstanceSelectorTableViewController {
|
|||||||
case recommendedInstances
|
case recommendedInstances
|
||||||
}
|
}
|
||||||
enum Item: Equatable, Hashable, Sendable {
|
enum Item: Equatable, Hashable, Sendable {
|
||||||
case selected(URL, InstanceV1)
|
case selected(URL, Info)
|
||||||
case recommended(InstanceSelector.Instance)
|
case recommended(InstanceSelector.Instance)
|
||||||
|
|
||||||
static func ==(lhs: Item, rhs: Item) -> Bool {
|
static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
case let (.selected(urlA, instanceA), .selected(urlB, instanceB)):
|
case let (.selected(urlA, _), .selected(urlB, _)):
|
||||||
return urlA == urlB && instanceA.uri == instanceB.uri
|
return urlA == urlB
|
||||||
case let (.recommended(a), .recommended(b)):
|
case let (.recommended(a), .recommended(b)):
|
||||||
return a.domain == b.domain
|
return a.domain == b.domain
|
||||||
default:
|
default:
|
||||||
@ -328,16 +350,21 @@ extension InstanceSelectorTableViewController {
|
|||||||
|
|
||||||
func hash(into hasher: inout Hasher) {
|
func hash(into hasher: inout Hasher) {
|
||||||
switch self {
|
switch self {
|
||||||
case let .selected(url, instance):
|
case let .selected(url, _):
|
||||||
hasher.combine(0)
|
hasher.combine(0)
|
||||||
hasher.combine(url)
|
hasher.combine(url)
|
||||||
hasher.combine(instance.uri)
|
|
||||||
case let .recommended(instance):
|
case let .recommended(instance):
|
||||||
hasher.combine(1)
|
hasher.combine(1)
|
||||||
hasher.combine(instance.domain)
|
hasher.combine(instance.domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct Info: Hashable {
|
||||||
|
let host: String
|
||||||
|
let description: String
|
||||||
|
let thumbnail: URL?
|
||||||
|
let adult: Bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension InstanceSelectorTableViewController: UISearchResultsUpdating {
|
extension InstanceSelectorTableViewController: UISearchResultsUpdating {
|
||||||
|
@ -16,8 +16,7 @@ class InstanceTableViewCell: UITableViewCell {
|
|||||||
@IBOutlet weak var adultLabel: UILabel!
|
@IBOutlet weak var adultLabel: UILabel!
|
||||||
@IBOutlet weak var descriptionTextView: ContentTextView!
|
@IBOutlet weak var descriptionTextView: ContentTextView!
|
||||||
|
|
||||||
var instance: InstanceV1?
|
private var instance: InstanceSelectorTableViewController.Info?
|
||||||
var selectorInstance: InstanceSelector.Instance?
|
|
||||||
|
|
||||||
private var thumbnailTask: Task<Void, Never>?
|
private var thumbnailTask: Task<Void, Never>?
|
||||||
|
|
||||||
@ -44,25 +43,14 @@ class InstanceTableViewCell: UITableViewCell {
|
|||||||
backgroundConfiguration = .appListGroupedCell(for: state)
|
backgroundConfiguration = .appListGroupedCell(for: state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUI(instance: InstanceSelector.Instance) {
|
func updateUI(info: InstanceSelectorTableViewController.Info) {
|
||||||
self.selectorInstance = instance
|
self.instance = info
|
||||||
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
|
|
||||||
|
|
||||||
domainLabel.text = URLComponents(string: instance.uri)?.host ?? instance.uri
|
domainLabel.text = info.host
|
||||||
adultLabel.isHidden = true
|
adultLabel.isHidden = !info.adult
|
||||||
descriptionTextView.setBodyTextFromHTML(instance.shortDescription ?? instance.description)
|
descriptionTextView.setBodyTextFromHTML(info.description)
|
||||||
|
|
||||||
if let thumbnail = instance.thumbnail {
|
if let thumbnail = info.thumbnail {
|
||||||
updateThumbnail(url: thumbnail)
|
updateThumbnail(url: thumbnail)
|
||||||
} else {
|
} else {
|
||||||
thumbnailImageView.image = nil
|
thumbnailImageView.image = nil
|
||||||
@ -85,7 +73,6 @@ class InstanceTableViewCell: UITableViewCell {
|
|||||||
|
|
||||||
thumbnailTask?.cancel()
|
thumbnailTask?.cancel()
|
||||||
instance = nil
|
instance = nil
|
||||||
selectorInstance = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user