// // ProfileTableViewController.swift // Tusker // // Created by Shadowfacts on 8/27/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import UIKit import Pachyderm import SafariServices class ProfileTableViewController: UITableViewController, PreferencesAdaptive { static func create(for account: Account) -> UIViewController { guard let profileController = UIStoryboard(name: "Profile", bundle: nil).instantiateInitialViewController() as? ProfileTableViewController else { fatalError() } profileController.account = account return profileController } var account: Account! var statusIDs: [String] = [] { didSet { DispatchQueue.main.async { self.tableView.reloadData() } } } var older: RequestRange? var newer: RequestRange? func getStatuses(for range: RequestRange = .default, completion: @escaping Client.Callback<[Status]>) { let request = Account.getStatuses(account, range: range, onlyMedia: false, pinned: false, excludeReplies: !Preferences.shared.showRepliesInProfiles) MastodonController.shared.client.run(request, completion: completion) } override func viewDidLoad() { super.viewDidLoad() tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 140 tableView.register(UINib(nibName: "StatusTableViewCell", bundle: nil), forCellReuseIdentifier: "statusCell") tableView.register(UINib(nibName: "ProfileHeaderTableViewCell", bundle: nil), forCellReuseIdentifier: "headerCell") updateUIForPreferences() getStatuses { response in guard case let .success(statuses, pagination) = response else { fatalError() } StatusCache.addAll(statuses) self.statusIDs = statuses.map { $0.id } self.older = pagination?.older self.newer = pagination?.newer } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) for cell in tableView.visibleCells { if let cell = cell as? PreferencesAdaptive { cell.updateUIForPreferences() } } updateUIForPreferences() } func updateUIForPreferences() { navigationItem.title = account.realDisplayName } func sendMessageMentioning() { let vc = ComposeViewController.create(mentioning: account) present(vc, animated: true) } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } */ // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return 2 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case 0: return 1 case 1: return statusIDs.count default: return 0 } } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch indexPath.section { case 0: guard let cell = tableView.dequeueReusableCell(withIdentifier: "headerCell", for: indexPath) as? ProfileHeaderTableViewCell else { fatalError() } cell.selectionStyle = .none cell.updateUI(for: account) cell.delegate = self return cell case 1: guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? StatusTableViewCell else { fatalError() } let statusID = statusIDs[indexPath.row] cell.updateUI(for: statusID) cell.delegate = self return cell default: fatalError("Invalid section \(indexPath.section) for profile VC") } } override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { if indexPath.section == 1 && indexPath.row == statusIDs.count - 1 { guard let older = older else { return } getStatuses(for: older) { response in guard case let .success(newStatuses, pagination) = response else { fatalError() } self.older = pagination?.older StatusCache.addAll(newStatuses) self.statusIDs.append(contentsOf: newStatuses.map { $0.id }) } } } override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return tableView.cellForRow(at: indexPath) is TableViewSwipeActionProvider } override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.leadingSwipeActionsConfiguration() } override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration() } @IBAction func refreshStatuses(_ sender: Any) { guard let newer = newer else { return } getStatuses(for: newer) { response in guard case let .success(newStatuses, pagination) = response else { fatalError() } self.newer = pagination?.newer StatusCache.addAll(newStatuses) self.statusIDs.insert(contentsOf: newStatuses.map { $0.id }, at: 0) DispatchQueue.main.async { self.refreshControl?.endRefreshing() } } } @IBAction func composePressed(_ sender: Any) { sendMessageMentioning() } } extension ProfileTableViewController: ProfileHeaderTableViewCellDelegate { func showMoreOptions() { let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) alert.addAction(UIAlertAction(title: "Open in Safari...", style: .default, handler: { _ in let vc = SFSafariViewController(url: self.account.url) self.present(vc, animated: true) })) alert.addAction(UIAlertAction(title: "Share...", style: .default, handler: { _ in let vc = UIActivityViewController(activityItems: [self.account.url], applicationActivities: nil) self.present(vc, animated: true) })) alert.addAction(UIAlertAction(title: "Send Message...", style: .default, handler: { _ in self.sendMessageMentioning() })) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) present(alert, animated: true) } } extension ProfileTableViewController: LargeImageViewControllerDelegate {}