Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[NT-876] Add Pledge CTA to ProjectDescriptionViewController #1072

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ internal final class ProjectPamphletContentDataSource: ValueCellDataSource {
)
}

internal func load(project: Project) {
internal func load(projectAndRefTag: (Project, RefTag?)) {
self.clearValues()

let (project, _) = projectAndRefTag

if currentUserIsCreator(of: project) {
self.set(
values: [project],
Expand All @@ -36,7 +38,11 @@ internal final class ProjectPamphletContentDataSource: ValueCellDataSource {
)
}

self.set(values: [project], cellClass: ProjectPamphletMainCell.self, inSection: Section.main.rawValue)
self.set(
values: [projectAndRefTag],
cellClass: ProjectPamphletMainCell.self,
inSection: Section.main.rawValue
)

let values: [ProjectPamphletSubpage] = [
.comments(project.stats.commentsCount as Int?, .first),
Expand Down Expand Up @@ -66,7 +72,7 @@ internal final class ProjectPamphletContentDataSource: ValueCellDataSource {
switch (cell, value) {
case let (cell as ProjectPamphletCreatorHeaderCell, value as Project):
cell.configureWith(value: value)
case let (cell as ProjectPamphletMainCell, value as Project):
case let (cell as ProjectPamphletMainCell, value as (Project, RefTag?)):
cell.configureWith(value: value)
case let (cell as ProjectPamphletMinimalCell, value as Project):
cell.configureWith(value: value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class ProjectPamphletContentDataSourceTests: TestCase {
|> Project.lens.creator .~ user

withEnvironment(currentUser: user) {
self.dataSource.load(project: project)
self.dataSource.load(projectAndRefTag: (project, .discovery))

XCTAssertEqual(1, self.dataSource.tableView(self.tableView, numberOfRowsInSection: viewProgressSection))
}
Expand All @@ -30,7 +30,7 @@ final class ProjectPamphletContentDataSourceTests: TestCase {
let project = Project.template

withEnvironment(currentUser: user) {
self.dataSource.load(project: project)
self.dataSource.load(projectAndRefTag: (project, .discovery))

XCTAssertEqual(0, self.dataSource.tableView(self.tableView, numberOfRowsInSection: viewProgressSection))
}
Expand All @@ -42,7 +42,7 @@ final class ProjectPamphletContentDataSourceTests: TestCase {
lang: "en"
)
withEnvironment(config: config, mainBundle: releaseBundle) {
dataSource.load(project: .template)
self.dataSource.load(projectAndRefTag: (.template, .discovery))

XCTAssertEqual(8, self.dataSource.numberOfSections(in: self.tableView))
}
Expand Down
7 changes: 6 additions & 1 deletion Kickstarter-iOS/Library/WebViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import WebKit

internal class WebViewController: UIViewController {
internal let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
internal var bottomAnchorConstraint: NSLayoutConstraint?

override func loadView() {
super.loadView()
Expand All @@ -17,10 +18,14 @@ internal class WebViewController: UIViewController {
self.webView.customUserAgent = Service.userAgent

self.view.addSubview(self.webView)

let bottomAnchorConstraint = self.webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
self.bottomAnchorConstraint = bottomAnchorConstraint

NSLayoutConstraint.activate(
[
self.webView.topAnchor.constraint(equalTo: self.view.topAnchor),
self.webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
bottomAnchorConstraint,
self.webView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
self.webView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
]
Expand Down
31 changes: 18 additions & 13 deletions Kickstarter-iOS/ViewModels/AppDelegateViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -418,19 +418,20 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
AppEnvironment.current.apiService.fetchProject(param: param)
.demoteErrors()
.observeForUI()
.map { project -> (Project, Navigation.Project, [UIViewController]) in
.map { project -> (Project, Navigation.Project, [UIViewController], RefTag?) in
(
project, subpage,
[ProjectPamphletViewController.configuredWith(projectOrParam: .left(project), refTag: refTag)]
[ProjectPamphletViewController.configuredWith(projectOrParam: .left(project), refTag: refTag)],
refTag
)
}
}

let projectLink = projectLinkValues
.filter { project, _, _ in project.prelaunchActivated != true }
.filter { project, _, _, _ in project.prelaunchActivated != true }

let projectPreviewLink = projectLinkValues
.filter { project, _, _ in project.prelaunchActivated == true }
.filter { project, _, _, _ in project.prelaunchActivated == true }

let resolvedRedirectUrl = deepLinkUrl
.filter { Navigation.deepLinkMatch($0) == nil }
Expand All @@ -448,12 +449,14 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
.skipNil()

let projectRootLink = projectLink
.filter { _, subpage, _ in subpage == .root }
.map { _, _, vcs in vcs }
.filter { _, subpage, _, _ in subpage == .root }
.map { _, _, vcs, _ in vcs }

let projectCommentsLink = projectLink
.filter { _, subpage, _ in subpage == .comments }
.map { project, _, vcs in vcs + [CommentsViewController.configuredWith(project: project, update: nil)] }
.filter { _, subpage, _, _ in subpage == .comments }
.map { project, _, vcs, _ in
vcs + [CommentsViewController.configuredWith(project: project, update: nil)]
}

let surveyResponseLink = deepLink
.map { link -> Int? in
Expand All @@ -472,15 +475,17 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
}

let campaignFaqLink = projectLink
.filter { _, subpage, _ in subpage == .faqs }
.map { project, _, vcs in vcs + [ProjectDescriptionViewController.configuredWith(project: project)] }
.filter { _, subpage, _, _ in subpage == .faqs }
.map { project, _, vcs, refTag in
vcs + [ProjectDescriptionViewController.configuredWith(value: (project, refTag))]
}

let updatesLink = projectLink
.filter { _, subpage, _ in subpage == .updates }
.map { project, _, vcs in vcs + [ProjectUpdatesViewController.configuredWith(project: project)] }
.filter { _, subpage, _, _ in subpage == .updates }
.map { project, _, vcs, _ in vcs + [ProjectUpdatesViewController.configuredWith(project: project)] }

let updateLink = projectLink
.map { project, subpage, vcs -> (Project, Int, Navigation.Project.Update, [UIViewController])? in
.map { project, subpage, vcs, _ -> (Project, Int, Navigation.Project.Update, [UIViewController])? in
guard case let .update(id, updateSubpage) = subpage else { return nil }
return (project, id, updateSubpage, vcs)
}
Expand Down
27 changes: 15 additions & 12 deletions Kickstarter-iOS/Views/Cells/ProjectPamphletMainCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import UIKit

internal protocol ProjectPamphletMainCellDelegate: VideoViewControllerDelegate {
func projectPamphletMainCell(_ cell: ProjectPamphletMainCell, addChildController child: UIViewController)
func projectPamphletMainCell(_ cell: ProjectPamphletMainCell, goToCampaignForProject project: Project)
func projectPamphletMainCell(
_ cell: ProjectPamphletMainCell,
goToCampaignForProjectWith projectAndRefTag: (project: Project, refTag: RefTag?)
)
func projectPamphletMainCell(_ cell: ProjectPamphletMainCell, goToCreatorForProject project: Project)
}

Expand Down Expand Up @@ -70,8 +73,8 @@ internal final class ProjectPamphletMainCell: UITableViewCell, ValueCell {
self.viewModel.inputs.awakeFromNib()
}

internal func configureWith(value project: Project) {
self.viewModel.inputs.configureWith(project: project)
internal func configureWith(value: (Project, RefTag?)) {
self.viewModel.inputs.configureWith(value: value)
}

internal func scrollContentOffset(_ offset: CGFloat) {
Expand Down Expand Up @@ -282,32 +285,32 @@ internal final class ProjectPamphletMainCell: UITableViewCell, ValueCell {
.skipNil()
.observeValues { [weak self] in self?.creatorImageView.af_setImage(withURL: $0) }

self.viewModel.outputs.notifyDelegateToGoToCampaign
self.viewModel.outputs.notifyDelegateToGoToCampaignWithProjectAndRefTag
.observeForControllerAction()
.observeValues { [weak self] in
guard let _self = self else { return }
self?.delegate?.projectPamphletMainCell(_self, goToCampaignForProject: $0)
guard let self = self else { return }
self.delegate?.projectPamphletMainCell(self, goToCampaignForProjectWith: $0)
}

self.viewModel.outputs.notifyDelegateToGoToCreator
.observeForControllerAction()
.observeValues { [weak self] in
guard let _self = self else { return }
self?.delegate?.projectPamphletMainCell(_self, goToCreatorForProject: $0)
guard let self = self else { return }
self.delegate?.projectPamphletMainCell(self, goToCreatorForProject: $0)
}

self.viewModel.outputs.opacityForViews
.observeForUI()
.observeValues { [weak self] alpha in
guard let _self = self else { return }
guard let self = self else { return }
UIView.animate(
withDuration: alpha == 0.0 ? 0.0 : 0.3,
delay: 0.0,
options: .curveEaseOut,
animations: {
_self.creatorStackView.alpha = alpha
_self.statsStackView.alpha = alpha
_self.blurbAndReadMoreStackView.alpha = alpha
self.creatorStackView.alpha = alpha
self.statsStackView.alpha = alpha
self.blurbAndReadMoreStackView.alpha = alpha
},
completion: nil
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,28 @@ import UIKit
import WebKit

internal final class ProjectDescriptionViewController: WebViewController {
fileprivate let viewModel: ProjectDescriptionViewModelType = ProjectDescriptionViewModel()
private let loadingIndicator = UIActivityIndicatorView()
private lazy var pledgeCTAContainerView: PledgeCTAContainerView = {
PledgeCTAContainerView(frame: .zero)
|> \.translatesAutoresizingMaskIntoConstraints .~ false
|> \.delegate .~ self
}()

fileprivate let loadingIndicator = UIActivityIndicatorView()
private let viewModel: ProjectDescriptionViewModelType = ProjectDescriptionViewModel()

internal static func configuredWith(project: Project) -> ProjectDescriptionViewController {
internal static func configuredWith(value: (Project, RefTag?)) -> ProjectDescriptionViewController {
let vc = ProjectDescriptionViewController()
vc.viewModel.inputs.configureWith(project: project)
vc.viewModel.inputs.configureWith(value: value)
return vc
}

// MARK: - Lifecycle

override func viewDidLoad() {
super.viewDidLoad()

self.configurePledgeCTAContainerView()

self.loadingIndicator.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(self.loadingIndicator)
NSLayoutConstraint.activate(
Expand All @@ -37,6 +46,15 @@ internal final class ProjectDescriptionViewController: WebViewController {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

self.bottomAnchorConstraint?.constant = -(!self.pledgeCTAContainerView.isHidden ?
self.pledgeCTAContainerView.frame.size.height : 0)
}

// MARK: - Styles

override func bindStyles() {
super.bindStyles()

Expand All @@ -50,9 +68,14 @@ internal final class ProjectDescriptionViewController: WebViewController {
|> baseActivityIndicatorStyle
}

// MARK: - View model

override func bindViewModel() {
super.bindViewModel()

self.loadingIndicator.rac.animating = self.viewModel.outputs.isLoading
self.pledgeCTAContainerView.rac.hidden = self.viewModel.outputs.pledgeCTAContainerViewIsHidden

self.viewModel.outputs.goToMessageDialog
.observeForControllerAction()
.observeValues { [weak self] in self?.goToMessageDialog(subject: $0, context: $1) }
Expand All @@ -69,8 +92,6 @@ internal final class ProjectDescriptionViewController: WebViewController {
self?.goTo(url: $0)
}

self.loadingIndicator.rac.animating = self.viewModel.outputs.isLoading

self.viewModel.outputs.loadWebViewRequest
.observeForControllerAction()
.observeValues { [weak self] in
Expand All @@ -86,8 +107,39 @@ internal final class ProjectDescriptionViewController: WebViewController {
completion: nil
)
}

self.viewModel.outputs.configurePledgeCTAContainerView
.observeForUI()
.observeValues { [weak self] value in
self?.pledgeCTAContainerView.configureWith(value: value)
}

self.viewModel.outputs.goToRewards
.observeForControllerAction()
.observeValues { value in
let vc = RewardsCollectionViewController.controller(with: value.0, refTag: value.1)

self.present(vc, animated: true)
}
}

// MARK: - Subviews

private func configurePledgeCTAContainerView() {
_ = (self.pledgeCTAContainerView, self.view)
|> ksr_addSubviewToParent()

let pledgeCTAContainerViewConstraints = [
self.pledgeCTAContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
self.pledgeCTAContainerView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
self.pledgeCTAContainerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
]

NSLayoutConstraint.activate(pledgeCTAContainerViewConstraints)
}

// MARK: - WKNavigationDelegate

internal func webView(
_: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
Expand All @@ -113,6 +165,8 @@ internal final class ProjectDescriptionViewController: WebViewController {
self.viewModel.inputs.webViewDidFailProvisionalNavigation(withError: error)
}

// MARK: - Navigation

fileprivate func goToMessageDialog(subject: MessageSubject, context: Koala.MessageDialogContext) {
let vc = MessageDialogViewController.configuredWith(messageSubject: subject, context: context)
vc.delegate = self
Expand All @@ -124,10 +178,20 @@ internal final class ProjectDescriptionViewController: WebViewController {
}
}

// MARK: - MessageDialogViewControllerDelegate

extension ProjectDescriptionViewController: MessageDialogViewControllerDelegate {
internal func messageDialogWantsDismissal(_ dialog: MessageDialogViewController) {
dialog.dismiss(animated: true, completion: nil)
}

internal func messageDialog(_: MessageDialogViewController, postedMessage _: Message) {}
}

// MARK: - PledgeCTAContainerViewDelegate

extension ProjectDescriptionViewController: PledgeCTAContainerViewDelegate {
func pledgeCTAButtonTapped(with state: PledgeStateCTAType) {
self.viewModel.inputs.pledgeCTAButtonTapped(with: state)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public final class ProjectPamphletContentViewController: UITableViewController {
fileprivate let viewModel: ProjectPamphletContentViewModelType = ProjectPamphletContentViewModel()
fileprivate var navBarController: ProjectNavBarViewController!

internal func configureWith(project: Project) {
self.viewModel.inputs.configureWith(project: project)
internal func configureWith(value: (Project, RefTag?)) {
self.viewModel.inputs.configureWith(value: value)
}

public override func viewDidLoad() {
Expand Down Expand Up @@ -59,10 +59,10 @@ public final class ProjectPamphletContentViewController: UITableViewController {
public override func bindViewModel() {
super.bindViewModel()

self.viewModel.outputs.loadProjectIntoDataSource
self.viewModel.outputs.loadProjectAndRefTagIntoDataSource
.observeForUI()
.observeValues { [weak self] project in
self?.dataSource.load(project: project)
.observeValues { [weak self] projectAndRefTag in
self?.dataSource.load(projectAndRefTag: projectAndRefTag)
self?.tableView.reloadData()
}

Expand Down Expand Up @@ -187,9 +187,9 @@ public final class ProjectPamphletContentViewController: UITableViewController {
extension ProjectPamphletContentViewController: ProjectPamphletMainCellDelegate {
internal func projectPamphletMainCell(
_: ProjectPamphletMainCell,
goToCampaignForProject project: Project
goToCampaignForProjectWith projectAndRefTag: (project: Project, refTag: RefTag?)
) {
let vc = ProjectDescriptionViewController.configuredWith(project: project)
let vc = ProjectDescriptionViewController.configuredWith(value: projectAndRefTag)
self.navigationController?.pushViewController(vc, animated: true)
}

Expand Down
Loading