From 060e615878f9f9f7d5f1a822271adec61380d7a2 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 18 Aug 2018 17:46:28 -0400 Subject: [PATCH] Add infinite scrolling and pull to refresh to timeline --- Tusker/Storyboards/Statuses.storyboard | 6 ++ .../StatusesTableViewController.swift | 99 +++++++++---------- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/Tusker/Storyboards/Statuses.storyboard b/Tusker/Storyboards/Statuses.storyboard index f4ca6ff3..705c9242 100644 --- a/Tusker/Storyboards/Statuses.storyboard +++ b/Tusker/Storyboards/Statuses.storyboard @@ -68,6 +68,12 @@ + + + + + + diff --git a/Tusker/View Controllers/StatusesTableViewController.swift b/Tusker/View Controllers/StatusesTableViewController.swift index 9fc79b04..2280ace8 100644 --- a/Tusker/View Controllers/StatusesTableViewController.swift +++ b/Tusker/View Controllers/StatusesTableViewController.swift @@ -20,26 +20,38 @@ class StatusesTableViewController: UITableViewController { } } + var newer: RequestRange? + var older: RequestRange? + override func viewWillAppear(_ animated: Bool) { MastodonController.shared.client.run(Timelines.home()) { result in - guard case let .success(statuses, _) = result else { fatalError() } + guard case let .success(statuses, pagination) = result else { fatalError() } self.statuses = statuses + self.newer = pagination?.previous + self.older = pagination?.next + DispatchQueue.main.async { + self.tableView.reloadData() + } } } override func viewDidLoad() { super.viewDidLoad() - + tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 140 - - // Uncomment the following line to preserve selection between presentations - // self.clearsSelectionOnViewWillAppear = false - - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem } + /* + // 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 { @@ -47,7 +59,6 @@ class StatusesTableViewController: UITableViewController { } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - // #warning Incomplete implementation, return the number of rows return statuses.count } @@ -63,51 +74,33 @@ class StatusesTableViewController: UITableViewController { return cell } - - - /* - // Override to support conditional editing of the table view. - override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the specified item to be editable. - return true + + override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if indexPath.row == statuses.count - 1 { + guard let older = older else { return } + + MastodonController.shared.client.run(Timelines.home(range: older)) { result in + guard case let .success(newStatuses, pagination) = result else { fatalError() } + self.older = pagination?.next + self.statuses.append(contentsOf: newStatuses) + } + } } - */ - /* - // Override to support editing the table view. - override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - // Delete the row from the data source - tableView.deleteRows(at: [indexPath], with: .fade) - } else if editingStyle == .insert { - // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view - } + @IBAction func refreshStatuses(_ sender: Any) { + guard let newer = newer else { return } + + MastodonController.shared.client.run(Timelines.home(range: newer)) { result in + guard case let .success(newStatuses, pagination) = result else { fatalError() } + self.newer = pagination?.previous + self.statuses.insert(contentsOf: newStatuses, at: 0) + DispatchQueue.main.async { + self.refreshControl?.endRefreshing() + + // maintain the current position in the list (don't scroll to the top) + self.tableView.scrollToRow(at: IndexPath(row: newStatuses.count, section: 0), at: .top, animated: false) + } + } } - */ - - /* - // Override to support rearranging the table view. - override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { - - } - */ - - /* - // Override to support conditional rearranging of the table view. - override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the item to be re-orderable. - return 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. - } - */ - + }