[ABANDONED] Mastodon iOS client.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
9.8 KiB

//
// InstancesTableViewController.swift
// elpha-ios
//
// Created by Dwayne Harris on 8/29/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import CoreData
import UIKit
struct Instance {
var id: String?
var name: String?
var addedAt: String?
var updatedAt: String?
var checkedAt: String?
var uptime: Int?
var up: Bool?
var dead: Bool?
var version: String?
var ipv6: Bool?
var httpsScore: Int?
var httpsRank: String?
var users: String?
var statuses: String?
var connections: Int?
var openRegistrations: Bool?
var thumbnail: String?
var thumbnailProxy: String?
var activeUsers: Int?
var shortDescription: String?
var fullDescription: String?
var topic: String?
var languages: [String]?
var categories: [String]?
}
class InstancesTableViewController: UITableViewController, UIViewControllerPreviewingDelegate {
@IBOutlet var mainNavigationItem: UINavigationItem!
let instanceRequestCount = 20
var instances: [Instance] = []
var nextID: String? = nil
var finished: Bool = false
var loading: Bool = false {
didSet {
DispatchQueue.main.async {
if self.loading {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
self.refreshControl?.beginRefreshing()
} else {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
self.refreshControl?.endRefreshing()
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
mainNavigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))
registerForPreviewing(with: self, sourceView: tableView)
refreshControl?.addTarget(self, action: #selector(self.reloadInstances), for: .valueChanged)
loadInstances()
}
@objc func done() {
dismiss(animated: true, completion: nil)
}
@objc func reloadInstances() {
self.nextID = nil
self.finished = false
loadInstances()
}
func loadInstances() {
loading = true
var params = [
"count=\(instanceRequestCount)",
"sort_by=users",
"sort_order=desc",
"include_closed=true",
"include_down=false",
]
if let nextID = nextID {
params.append("min_id=\(nextID)")
} else {
instances = []
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
let requestURL = "\(Config.instancesServiceUrl)\(Config.instancesServiceEndpoint)?\(params.joined(separator: "&"))"
print("loading instances: requestURL: \(requestURL)")
var request = URLRequest(url: URL(string: requestURL)!)
request.addValue("Bearer \(Config.instancesServiceSecret)", forHTTPHeaderField: "Authorization")
let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
return
}
defer {
self.loading = false
}
if let response = response as? HTTPURLResponse {
switch response.statusCode {
case 200..<300:
if let data = data {
do {
let instancesResult = try JSONSerialization.jsonObject(with: data) as! [String: Any]
if let pagination = instancesResult["pagination"] as? [String: Any] {
if let nextID = pagination["next_id"] as? String {
self.nextID = nextID
} else {
self.nextID = nil
self.finished = true
}
}
if let instances = instancesResult["instances"] as? [Any] {
for case let instance as [String: Any] in instances {
var i = Instance()
i.id = instance["id"] as? String
i.name = instance["name"] as? String
i.addedAt = instance["added_at"] as? String
i.updatedAt = instance["updated_at"] as? String
i.checkedAt = instance["checked_at"] as? String
i.uptime = instance["uptime"] as? Int
i.up = instance["up"] as? Bool
i.dead = instance["dead"] as? Bool
i.version = instance["version"] as? String
i.ipv6 = instance["ipv6"] as? Bool
i.httpsScore = instance["https_score"] as? Int
i.httpsRank = instance["https_rank"] as? String
i.users = instance["users"] as? String
i.statuses = instance["statuses"] as? String
i.connections = instance["connections"] as? Int
i.openRegistrations = instance["open_registrations"] as? Bool
i.thumbnail = instance["thumbnail"] as? String
i.thumbnailProxy = instance["thumbnail_proxy"] as? String
i.activeUsers = instance["active_users"] as? Int
let info = instance["info"] as? [String: Any]
if let info = info {
i.shortDescription = info["short_description"] as? String
i.fullDescription = info["full_description"] as? String
i.topic = info["topic"] as? String
i.languages = info["languages"] as? [String]
i.categories = info["categories"] as? [String]
}
self.instances.append(i)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
} catch let error {
print(error)
return
}
}
case 400:
print("instances.social: 400")
default:
return
}
}
}
dataTask.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return instances.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "InstancesTableViewCell", for: indexPath) as? InstancesTableViewCell else {
fatalError("Unable to find reusable cell")
}
let instance = instances[indexPath.row]
cell.instanceNameLabel.text = instance.name
if let statuses = instance.statuses {
cell.statusesLabel.text = NumberFormatter.localizedString(from: NSNumber(value: Int64(statuses)!), number: .decimal)
}
if let users = instance.users {
cell.usersLabel.text = NumberFormatter.localizedString(from: NSNumber(value: Int64(users)!), number: .decimal)
}
if let thumbnail = instance.thumbnail {
cell.thumbnailURL = thumbnail
}
if indexPath.row == instances.count - 1 && !loading && !finished {
loadInstances()
}
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "InstanceDetailSegue", let cell = segue.destination as? InstanceViewController {
if let row = tableView.indexPathForSelectedRow?.row {
cell.instance = instances[row]
}
}
}
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = tableView.indexPathForRow(at: location) else {
return nil
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let detailViewController = storyboard.instantiateViewController(withIdentifier: "InstanceViewController") as? InstanceViewController {
detailViewController.instance = instances[indexPath.row]
return detailViewController
} else {
return nil
}
}
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
}