[Framework] Show top words for filtered items in the Feed List (#12)

This PR contains the work done to show the top 3 words belonging to the filtered reviews  in the `FeedListViewController` view controller.

Reviewed-on: rock-n-code/app-reviews#12
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #12.
This commit is contained in:
2024-03-21 01:13:12 +00:00
committed by javier
parent eac34c61c1
commit d00cfceb32
10 changed files with 339 additions and 43 deletions
@@ -0,0 +1,17 @@
//
// FeedItemCell.swift
// ReviewsFeed
//
// Created by Javier Cicchelli on 21/03/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
import ReviewsUIKit
import UIKit
final class FeedItemCell: UITableViewCell, TableCell {
// MARK: Constants
static let cellID = "FeedItemCell"
}
@@ -0,0 +1,17 @@
//
// TopWordsCell.swift
// ReviewsFeed
//
// Created by Javier Cicchelli on 21/03/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
import ReviewsUIKit
import UIKit
final class TopWordsCell: UITableViewCell, TableCell {
// MARK: Constants
static let cellID = "TopWordsCell"
}
@@ -40,11 +40,12 @@ public class FeedListViewController: UITableViewController {
image: UIImage.Icon.star,
children: {
FilterOption.allCases.map { option -> UIAction in
.init(title: option.text,
image: .init(systemName: option.icon)
) { [weak self] _ in
self?.viewModel.filter(by: option)
}
.init(
title: option.text,
image: .init(systemName: option.icon)
) { [weak self] _ in
self?.viewModel.filter(by: option)
}
}
}()
)
@@ -83,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 = tableView.dequeueReusableCell(withIdentifier: .Cell.feedItem) 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 {
FeedItemCell(items[indexPath.row])
}
} else {
HostingConfiguration {
FeedItemCell(items[indexPath.row])
}
}
}()
return cell
}
// MARK: UITableViewDelegate
@@ -158,8 +147,57 @@ 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() {
tableView.register(UITableViewCell.self, forCellReuseIdentifier: .Cell.feedItem)
FeedItemCell.register(in: tableView)
TopWordsCell.register(in: tableView)
}
func setNavigationBar() {
@@ -232,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
@@ -1,5 +1,5 @@
//
// FeedItemCell.swift
// FeedItemView.swift
// ReviewsFeed
//
// Created by Javier Cicchelli on 19/03/2024.
@@ -9,7 +9,7 @@
import ReviewsUIKit
import SwiftUI
struct FeedItemCell: View {
struct FeedItemView: View {
// MARK: Constants
private let item: Review
@@ -66,8 +66,8 @@ struct FeedItemCell: View {
}
// MARK: - Previews
#Preview("Feed Item Cell") {
FeedItemCell(.init(
#Preview("Feed Item") {
FeedItemView(.init(
author: "Some author name here...",
comment: "Some review comment here...",
id: 0,
@@ -0,0 +1,82 @@
//
// TopWordsView.swift
// ReviewsFeed
//
// Created by Javier Cicchelli on 21/03/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
import SwiftUI
struct TopWordsView: View {
// MARK: Constants
private let topWords: [TopWord]
// MARK: Initialisers
init(_ topWords: [TopWord]) {
self.topWords = topWords
}
// MARK: Body
var body: some View {
HStack {
Spacer()
HStack(spacing: 12) {
ForEach(topWords) { topWord in
Item(
term: topWord.term,
count: String(topWord.count)
)
}
}
Spacer()
}
}
}
// MARK: - Structs
private extension TopWordsView {
struct Item: View {
// MARK: Constants
let term: String
let count: String
// MARK: Body
var body: some View {
HStack(
alignment: .center,
spacing: 6
) {
Text(count)
.font(.footnote)
.foregroundColor(.primary.opacity(0.75))
Text(term)
.lineLimit(1)
.font(.body.bold())
.foregroundColor(.primary)
}
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(Color.secondary.opacity(0.75))
.cornerRadius(8)
}
}
}
// MARK: - Previews
#Preview {
TopWordsView([
.init(id: "1", term: "Something", count: 3),
.init(id: "2", term: "Something", count: 2),
.init(id: "3", term: "Something", count: 1),
])
.padding(.horizontal)
}