diff --git a/Frameworks/Feed/Bundle/Sources/Logic/View Models/FeedListViewModel.swift b/Frameworks/Feed/Bundle/Sources/Logic/View Models/FeedListViewModel.swift index 4ece55b..a384c3a 100644 --- a/Frameworks/Feed/Bundle/Sources/Logic/View Models/FeedListViewModel.swift +++ b/Frameworks/Feed/Bundle/Sources/Logic/View Models/FeedListViewModel.swift @@ -29,7 +29,7 @@ extension FeedListViewController { @Published var isLoading: Bool = false var items: [Review] = [] - var words: [WordCount] = [] + var words: [TopWord] = [] private var reviewsAll: [Review] = [] private var reviewsFiltered: FilteredReviews = [:] @@ -43,6 +43,18 @@ extension FeedListViewController { init(configuration: Configuration = .init()) { self.configuration = configuration } + + // MARK: Computed + var itemsCount: Int { + isWordsShowing + ? items.count + : items.count + 1 + } + + var isWordsShowing: Bool { + filter != .all + && !words.isEmpty + } // MARK: Functions func fetch() { @@ -66,7 +78,9 @@ extension FeedListViewController { reviews.map(\.comment) .compactMap { try? filterWords($0) } } - .mapValues { topWords($0) } + .mapValues { + topWords($0).map(TopWord.init) + } items = reviewsAll isFilterEnabled = !items.isEmpty @@ -89,6 +103,14 @@ extension FeedListViewController { filter = option } + + func item(for index: Int) -> Review? { + guard index < items.count else { return nil } + + return isWordsShowing + ? items[index - 1] + : items[index] + } } } @@ -98,6 +120,6 @@ private extension FeedListViewController.ViewModel { // MARK: Type aliases typealias FilteredReviews = [FilterOption: [Review]] - typealias TopWordsReviews = [FilterOption: [WordCount]] + typealias TopWordsReviews = [FilterOption: [TopWord]] } diff --git a/Frameworks/Feed/Bundle/Sources/UI/View Controllers/FeedListViewController.swift b/Frameworks/Feed/Bundle/Sources/UI/View Controllers/FeedListViewController.swift index 26876e1..eb78d32 100644 --- a/Frameworks/Feed/Bundle/Sources/UI/View Controllers/FeedListViewController.swift +++ b/Frameworks/Feed/Bundle/Sources/UI/View Controllers/FeedListViewController.swift @@ -84,30 +84,18 @@ public class FeedListViewController: UITableViewController { _ tableView: UITableView, numberOfRowsInSection section: Int ) -> Int { - viewModel.items.count + viewModel.itemsCount } public override func tableView( _ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell { - guard let cell = FeedItemCell.dequeue(from: tableView) else { - return .init() + if viewModel.isWordsShowing && indexPath.row == 0 { + makeTopWordsCell(tableView) + } else { + makeFeedItemCell(tableView, at: indexPath.row) } - - cell.contentConfiguration = { - if #available(iOS 16.0, *) { - UIHostingConfiguration { - FeedItemView(items[indexPath.row]) - } - } else { - HostingConfiguration { - FeedItemView(items[indexPath.row]) - } - } - }() - - return cell } // MARK: UITableViewDelegate @@ -159,6 +147,54 @@ private extension FeedListViewController { .store(in: &cancellables) } + func makeFeedItemCell( + _ tableView: UITableView, + at row: Int + ) -> UITableViewCell { + guard + let cell = FeedItemCell.dequeue(from: tableView), + let item = viewModel.item(for: row) + else { + return .init() + } + + cell.separatorInset = .init(width: tableView.bounds.size.width) + cell.contentConfiguration = { + if #available(iOS 16.0, *) { + UIHostingConfiguration { + FeedItemView(item) + } + } else { + HostingConfiguration { + FeedItemView(item) + } + } + }() + + return cell + } + + func makeTopWordsCell(_ tableView: UITableView) -> UITableViewCell { + guard let cell = TopWordsCell.dequeue(from: tableView) else { + return .init() + } + + cell.separatorInset = .init(width: tableView.bounds.size.width) + cell.contentConfiguration = { + if #available(iOS 16.0, *) { + UIHostingConfiguration { + TopWordsView(viewModel.words) + } + } else { + HostingConfiguration { + TopWordsView(viewModel.words) + } + } + }() + + return cell + } + func registerTableCells() { FeedItemCell.register(in: tableView) TopWordsCell.register(in: tableView) @@ -234,6 +270,21 @@ private extension String { } } +// MARK: - UIEdgeInsets+Inits +private extension UIEdgeInsets { + + // MARK: Initialisers + init(width: CGFloat) { + self = .init( + top: 0, + left: width, + bottom: 0, + right: 0 + ) + } + +} + // MARK: - Previews #if DEBUG import ReviewsiTunesKit