Javier Cicchelli c9f4b9a677 [Framework] Feed item view in the Feed framework (#10)
This PR contains the work done to implement the `FeedItemViewController` view controller, that shows in details a selected review from the `FeedListViewController` view controller.

Reviewed-on: #10
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2024-03-20 01:42:21 +00:00

226 lines
6.8 KiB
Swift

//
// FeedItemViewController.swift
// ReviewsFeed
//
// Created by Dmitrii Ivanov on 21/07/2020.
// Copyright © 2020 ING. All rights reserved.
//
import ReviewsUIKit
import SwiftUI
import UIKit
final class FeedItemViewController: UIViewController {
// MARK: Constants
private let item: Review
// MARK: Properties
private lazy var appVersionController = {
UIHostingController(rootView: FakeLabel(
systemIcon: .Icon.info,
title: item.rating.appVersion
))
}()
private lazy var authorController = {
UIHostingController(rootView: FakeLabel(
systemIcon: .Icon.person,
title: item.author
))
}()
private lazy var starRatingController = {
UIHostingController(rootView: StarRating(
item.rating.stars,
of: .Rating.total
))
}()
// MARK: Outlets
private lazy var appVersionView = {
guard let view = appVersionController.view else {
fatalError("The StarRating component must be initialised")
}
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var authorView = {
guard let view = authorController.view else {
fatalError("The StarRating component must be initialised")
}
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var commentLabel = {
let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .body)
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.text = item.comment
return label
}()
private lazy var ratingView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.backgroundColor = .clear
stack.distribution = .fillProportionally
stack.translatesAutoresizingMaskIntoConstraints = false
stack.addArrangedSubview(starRatingView)
stack.addArrangedSubview(appVersionView)
return stack
}()
private lazy var scrollView = {
let scroll = UIScrollView()
scroll.backgroundColor = .clear
scroll.showsVerticalScrollIndicator = true
scroll.translatesAutoresizingMaskIntoConstraints = false
return scroll
}()
private lazy var stackView = {
let stack = UIStackView()
stack.axis = .vertical
stack.alignment = .leading
stack.backgroundColor = .clear
stack.distribution = .fill
stack.spacing = 16
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
private lazy var starRatingView = {
guard let view = starRatingController.view else {
fatalError("The StarRating component must be initialised")
}
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var titleLabel = {
let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .headline)
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.text = item.title
return label
}()
// MARK: Initialisers
init(_ item: Review) {
self.item = item
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
addChild(appVersionController)
addChild(authorController)
addChild(starRatingController)
setView()
setNavigationBar()
setLayout()
appVersionController.didMove(toParent: self)
authorController.didMove(toParent: self)
starRatingController.didMove(toParent: self)
}
}
// MARK: - Helpers
private extension FeedItemViewController {
// MARK: Functions
func setLayout() {
let scrollContentGuide = scrollView.contentLayoutGuide
let scrollFrameGuide = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollContentGuide.bottomAnchor, constant: -16),
stackView.leadingAnchor.constraint(equalTo: scrollContentGuide.leadingAnchor),
stackView.topAnchor.constraint(equalTo: scrollContentGuide.topAnchor, constant: 8),
stackView.trailingAnchor.constraint(equalTo: scrollContentGuide.trailingAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollFrameGuide.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollFrameGuide.trailingAnchor),
authorView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: 16),
ratingView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: 16),
titleLabel.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: 16),
titleLabel.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: -16),
commentLabel.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: 16),
commentLabel.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: -16),
])
}
func setNavigationBar() {
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.isTranslucent = true
navigationItem.title = "# \(String(item.id))"
}
func setView() {
view.backgroundColor = .systemBackground
view.addSubview(scrollView)
scrollView.addSubview(stackView)
stackView.addArrangedSubview(authorView)
stackView.addArrangedSubview(ratingView)
stackView.addArrangedSubview(titleLabel)
stackView.addArrangedSubview(commentLabel)
}
}
// MARK: - Previews
@available(iOS 17.0, *)
#Preview("Feed Item with a review") {
UINavigationController(rootViewController: FeedItemViewController(.init(
author: "Some author name here...",
comment: "Some long, explanatory review comment goes here...",
id: 1,
rating: .init(stars: 3, appVersion: "v1.0.0"),
title: "Some review title goes here..."
)))
}