226 lines
6.8 KiB
Swift
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..."
|
||
|
)))
|
||
|
}
|