diff --git a/Bank/AccountViewController.swift b/Bank/AccountViewController.swift index 921a267..3c062d1 100644 --- a/Bank/AccountViewController.swift +++ b/Bank/AccountViewController.swift @@ -15,6 +15,11 @@ class AccountViewController: UITableViewController, AccountHeaderViewDelegate { override func viewDidLoad() { super.viewDidLoad() + // Add refresh control + refreshControl = UIRefreshControl() + refreshControl!.addTarget(self, action: #selector(shouldRefresh), for: .valueChanged) + // Listen for when refreshes finish + NotificationCenter.default.addObserver(self, selector: #selector(refreshDidFinish), name: ViewController.finishedRefreshingDataNotification, object: nil) // Setup header view headerView.account = account headerView.accountIndex = index @@ -61,6 +66,18 @@ class AccountViewController: UITableViewController, AccountHeaderViewDelegate { } } + // MARK: - Refresh Control Handling + + @objc func shouldRefresh() { + NotificationCenter.default.post(name: ViewController.shouldRefreshDataNotification, object: nil) + } + + @objc func refreshDidFinish() { + DispatchQueue.main.async { + self.refreshControl!.endRefreshing() + } + } + // MARK: - Tap Handling @objc func tapped(with gestureRecognizer: UITapGestureRecognizer) { diff --git a/Bank/ViewController.swift b/Bank/ViewController.swift index 4577e58..5c05946 100644 --- a/Bank/ViewController.swift +++ b/Bank/ViewController.swift @@ -9,6 +9,8 @@ import UIKit class ViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, AccountViewControllerDelegate, NoAccountsViewControllerDelegate { + static let shouldRefreshDataNotification = Notification.Name(rawValue: "ViewControllerShouldRefreshDataNotificationName") + static let finishedRefreshingDataNotification = Notification.Name(rawValue: "ViewControllerFinishedRefreshingDataNotificationName") var statusViewController: StatusViewController? var statusBarOverlayView: StatusBarOverlayView! var isExchanging = false @@ -38,18 +40,30 @@ class ViewController: UIPageViewController, UIPageViewControllerDataSource, UIPa // Listen for and reload on fetched bank account changes NotificationCenter.default.addObserver(self, selector: #selector(reloadViewControllers), name: SessionDataStorage.accountsChangedNotification, object: nil) + // Listen for others wanting data refresh + NotificationCenter.default.addObserver(self, selector: #selector(startLoading), name: ViewController.shouldRefreshDataNotification, object: nil) + setupStatus() } /// Called when we're ready to start finding out about the linked accounts. - func startLoading() { + @objc func startLoading() { PlaidManager.shared.api.getTransactions { (transactions, accounts, error) in + let alreadyHasData = SessionDataStorage.shared.accounts != nil + if alreadyHasData { + // Notify others we finished refreshing + NotificationCenter.default.post(name: ViewController.finishedRefreshingDataNotification, object: nil) + } guard error == nil, let transactions = transactions, let accounts = accounts else { print("Couldn't load bank accounts:", error?.localizedDescription ?? "no error") - (self.statusViewController ?? self).showAlert(title: "Couldn't Load Bank Accounts", message: error?.localizedDescription ?? "An unknown error occurred while attempting to load your bank accounts.", actions: [.cancel("Retry") { _ in self.startLoading() }, .normal("Unlink Bank") { _ in + func handleRetry(_ action: UIAlertAction) { + self.startLoading() + } + let actions: [UIAlertAction] = alreadyHasData ? [.normal("Retry", handler: handleRetry), .cancel] : [.cancel("Retry", handler: handleRetry), .normal("Unlink Bank") { _ in PlaidManager.shared.accessToken = nil self.determineStatus() - }]) + }] + (self.statusViewController ?? self).showAlert(title: "Couldn't Load Bank Accounts", message: error?.localizedDescription ?? "An unknown error occurred while attempting to load your bank accounts.", actions: actions) return } print("Got accounts from server") diff --git a/README.md b/README.md index f159415..f3334fd 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This app uses the [Plaid API](https://www.plaid.com) to fetch information about ## IMPORTANT: Production Usage -**This project is meant for personal use.**. If you plan to ship any of the code, [please read this](/production-usage.md) to **ensure you distribute it safely.** +**This project is meant for personal use.** If you plan to ship any of the code, [please read this](/production-usage.md) to **ensure you distribute it safely.** ## Reporting Issues