[Framework] Pull to refresh in the Feed List (#13)

This PR contains the work done to implement the pull to refresh into the `FeedListViewController` view controller.

Reviewed-on: #13
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit is contained in:
Javier Cicchelli 2024-03-21 02:29:43 +00:00 committed by Javier Cicchelli
parent d00cfceb32
commit 0b5ca9ef9f
3 changed files with 62 additions and 7 deletions

View File

@ -108,6 +108,18 @@
} }
} }
} }
},
"view.feed-list.pull-to-refresh.title.text" : {
"comment" : "The title for the Pull To Refresh control associated to the table in the Feed List view.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pull to fetch the latest reviews"
}
}
}
} }
}, },
"version" : "1.0" "version" : "1.0"

View File

@ -82,7 +82,10 @@ extension FeedListViewController {
topWords($0).map(TopWord.init) topWords($0).map(TopWord.init)
} }
items = reviewsAll items = filter == .all
? reviewsAll
: reviewsFiltered[filter] ?? []
isFilterEnabled = !items.isEmpty isFilterEnabled = !items.isEmpty
} catch { } catch {
// TODO: handle this error gracefully. // TODO: handle this error gracefully.

View File

@ -51,6 +51,24 @@ public class FeedListViewController: UITableViewController {
) )
) )
}() }()
private lazy var pullControl = {
let control = UIRefreshControl()
control.attributedTitle = .init(string: NSLocalizedString(
.Key.PullToRefresh.title,
bundle: .module,
comment: .empty
))
control.addTarget(
self,
action: #selector(refresh(_:)),
for: .valueChanged
)
return control
}()
// MARK: Initialisers // MARK: Initialisers
public init(configuration: Configuration = .init()) { public init(configuration: Configuration = .init()) {
@ -73,6 +91,7 @@ public class FeedListViewController: UITableViewController {
super.viewDidLoad() super.viewDidLoad()
setNavigationBar() setNavigationBar()
setView()
registerTableCells() registerTableCells()
bindViewModel() bindViewModel()
@ -103,20 +122,28 @@ public class FeedListViewController: UITableViewController {
_ tableView: UITableView, _ tableView: UITableView,
didSelectRowAt indexPath: IndexPath didSelectRowAt indexPath: IndexPath
) { ) {
let details = FeedItemViewController(items[indexPath.row]) guard let item = viewModel.item(for: indexPath.row) else { return }
tableView.deselectRow( tableView.deselectRow(
at: indexPath, at: indexPath,
animated: true animated: true
) )
navigationController?.pushViewController(details, animated: true) navigationController?.pushViewController(
FeedItemViewController(item),
animated: true
)
} }
} }
// MARK: - Helpers // MARK: - Helpers
private extension FeedListViewController { private extension FeedListViewController {
// MARK: Actions
@objc func refresh(_ sender: AnyObject) {
self.viewModel.fetch()
}
// MARK: Functions // MARK: Functions
func bindViewModel() { func bindViewModel() {
@ -139,10 +166,15 @@ private extension FeedListViewController {
viewModel.$isLoading viewModel.$isLoading
.dropFirst() .dropFirst()
.filter { $0 == false } .filter { $0 == false }
.removeDuplicates()
.receive(on: RunLoop.main) .receive(on: RunLoop.main)
.sink { [weak self] _ in .sink { [weak self] _ in
self?.pullControl.endRefreshing()
self?.tableView.reloadData() self?.tableView.reloadData()
self?.tableView.scrollToRow(
at: .init(row: 0, section: 0),
at: .middle,
animated: true
)
} }
.store(in: &cancellables) .store(in: &cancellables)
} }
@ -194,7 +226,7 @@ private extension FeedListViewController {
return cell return cell
} }
func registerTableCells() { func registerTableCells() {
FeedItemCell.register(in: tableView) FeedItemCell.register(in: tableView)
TopWordsCell.register(in: tableView) TopWordsCell.register(in: tableView)
@ -212,6 +244,10 @@ private extension FeedListViewController {
) )
} }
func setView() {
tableView.refreshControl = pullControl
}
func updateFilterMenu(_ option: FilterOption) { func updateFilterMenu(_ option: FilterOption) {
filterButton filterButton
.menu? .menu?
@ -267,6 +303,10 @@ private extension String {
static let filter = "view.feed-list.navigation-bar.button.filter-list.text" static let filter = "view.feed-list.navigation-bar.button.filter-list.text"
} }
} }
enum PullToRefresh {
static let title = "view.feed-list.pull-to-refresh.title.text"
}
} }
} }