Skip to content

Commit

Permalink
[MBL-902] [MBL-934] [MBL-928] Use of AI Screen, Analytics, Question H…
Browse files Browse the repository at this point in the history
…eaders, Translations (#1843)
  • Loading branch information
msadoon committed Aug 22, 2023
1 parent 9a91c6b commit 3d464ee
Show file tree
Hide file tree
Showing 49 changed files with 1,680 additions and 289 deletions.
Expand Up @@ -84,8 +84,11 @@ public final class ProjectPageViewController: UIViewController, MessageBannerVie
self.tableView.registerCellClass(ProjectFAQsAskAQuestionCell.self)
self.tableView.registerCellClass(ProjectFAQsCell.self)
self.tableView.registerCellClass(ProjectFAQsEmptyStateCell.self)
self.tableView.registerCellClass(ProjectEnvironmentalCommitmentCell.self)
self.tableView.registerCellClass(ProjectEnvironmentalCommitmentDisclaimerCell.self)
self.tableView.registerCellClass(ProjectTabQuestionAnswerCell.self)
self.tableView.registerCellClass(ProjectTabTitleCell.self)
self.tableView.registerCellClass(ProjectTabCategoryDescriptionCell.self)
self.tableView.registerCellClass(ProjectTabDisclaimerCell.self)
self.tableView.registerCellClass(ProjectTabCheckmarkListCell.self)
self.tableView.registerCellClass(ProjectHeaderCell.self)
self.tableView.registerCellClass(ProjectPamphletCreatorHeaderCell.self)
self.tableView.registerCellClass(TextViewElementCell.self)
Expand Down Expand Up @@ -821,7 +824,7 @@ extension ProjectPageViewController: UITableViewDelegate {
}

public func tableView(_: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let cell = cell as? ProjectEnvironmentalCommitmentDisclaimerCell, cell.delegate == nil {
if let cell = cell as? ProjectTabDisclaimerCell, cell.delegate == nil {
cell.delegate = self
} else if let cell = cell as? ProjectRisksDisclaimerCell, cell.delegate == nil {
cell.delegate = self
Expand Down Expand Up @@ -902,14 +905,14 @@ extension ProjectPageViewController: MessageDialogViewControllerDelegate {
internal func messageDialog(_: MessageDialogViewController, postedMessage _: Message) {}
}

// MARK: - ProjectEnvironmentalCommitmentDisclaimerCellDelegate
// MARK: - ProjectTabDisclaimerCellDelegate

extension ProjectPageViewController: ProjectEnvironmentalCommitmentDisclaimerCellDelegate {
func projectEnvironmentalCommitmentDisclaimerCell(
_: ProjectEnvironmentalCommitmentDisclaimerCell,
extension ProjectPageViewController: ProjectTabDisclaimerCellDelegate {
func projectTabDisclaimerCell(
_: ProjectTabDisclaimerCell,
didTapURL: URL
) {
self.viewModel.inputs.projectEnvironmentalCommitmentDisclaimerCellDidTapURL(didTapURL)
self.viewModel.inputs.projectTabDisclaimerCellDidTapURL(didTapURL)
}
}

Expand Down
Expand Up @@ -8,7 +8,7 @@ import XCTest
internal final class ProjectPageViewControllerTests: TestCase {
private var project: Project = .cosmicSurgery
private let extendedProjectProperties = ExtendedProjectProperties(
environmentalCommitments: [ProjectEnvironmentalCommitment(
environmentalCommitments: [ProjectTabCategoryDescription(
description: "Environmental Commitment",
category: .environmentallyFriendlyFactories,
id: 0
Expand Down Expand Up @@ -1031,7 +1031,131 @@ internal final class ProjectPageViewControllerTests: TestCase {
}
}

// FIXME: Add test for "Use of AI" tab: https://kickstarter.atlassian.net/browse/MBL-902
func testLoggedOut_NonBacker_LiveProjectSwitchedToUseOfAITab_Success() {
let config = Config.template

let projectTabFundingOptions = ProjectTabFundingOptions(
fundingForAiAttribution: true,
fundingForAiConsent: true,
fundingForAiOption: true
)

let generatedByAIConsent = ProjectTabCategoryDescription(
description: "consent",
category: .aiDisclosureConsent,
id: 2
)

let generatedByAIDetails = ProjectTabCategoryDescription(
description: "details",
category: .aiDisclosureDetails,
id: 3
)

let generatedByAIOtherDetails = ProjectTabCategoryDescription(
description: "other",
category: .aiDisclosureOtherDetails,
id: 4
)

let useOfAIDisclosure: ProjectAIDisclosure =
ProjectAIDisclosure(
id: 1,
funding: projectTabFundingOptions,
generatedByAiConsent: generatedByAIConsent,
generatedByAiDetails: generatedByAIDetails,
involvesAi: true,
involvesFunding: true,
involvesGeneration: true,
involvesOther: true,
otherAiDetails: generatedByAIOtherDetails
)

let useOfAIExtendedProjectProperties = ExtendedProjectProperties(
environmentalCommitments: [ProjectTabCategoryDescription(
description: "Environmental Commitment",
category: .environmentallyFriendlyFactories,
id: 0
)],
faqs: [ProjectFAQ(
answer: "Answer",
question: "Question",
id: 0,
createdAt: MockDate().timeIntervalSince1970
)],
aiDisclosure: useOfAIDisclosure,
risks: "These are the risks",
story: ProjectStoryElements(htmlViewElements:
[
TextViewElement(components: [
TextComponent(
text: "bold and emphasis",
link: nil,
styles: [.bold, .emphasis]
),
TextComponent(
text: "link",
link: "https://ksr.com",
styles: [.link]
)
]),
ImageViewElement(
src: "bad-url",
href: "https://ksr.com",
caption: "camera"
),
AudioVideoViewElement(
sourceURLString: "https://source.com",
thumbnailURLString: nil,
seekPosition: .zero
),
ExternalSourceViewElement(
embeddedURLString: "https://source.com",
embeddedURLContentHeight: 123
)
]),
minimumPledgeAmount: 1
)

let project = Project.cosmicSurgery
|> Project.lens.photo.full .~ ""
|> (Project.lens.creator.avatar .. User.Avatar.lens.small) .~ ""
|> Project.lens.personalization.isBacking .~ false
|> Project.lens.state .~ .live
|> Project.lens.rewardData.rewards .~ []
|> \.extendedProjectProperties .~ useOfAIExtendedProjectProperties

let mockRemoteConfigClient = MockRemoteConfigClient()
|> \.features .~ ["use_of_ai": true]

combos(Language.allLanguages, [Device.phone4inch, Device.pad]).forEach { language, device in
withEnvironment(
config: config,
language: language,
remoteConfigClient: mockRemoteConfigClient
) {
let vc = ProjectPageViewController.configuredWith(
projectOrParam: .left(project), refTag: nil
)

let (parent, _) = traitControllers(device: device, orientation: .portrait, child: vc)
parent.view.frame.size.height = device == .pad ? 1_200 : parent.view.frame.size.height

scheduler.advance()

// INFO: We are not testing that the navigation selector view, just the content of the view controller after the tab selection occurs.
vc.projectNavigationSelectorViewDidSelect(ProjectNavigationSelectorView(), index: 4)

scheduler.run()

assertSnapshot(
matching: parent.view,
as: .image(perceptualPrecision: 0.98),
named: "lang_\(language)_device_\(device)"
)
}
}
}

func testLoggedOut_NonBacker_LiveProjectSwitchedToEnvironmentalCommitmentsTab_Success() {
let config = Config.template
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -18,6 +18,11 @@ internal final class ProjectPageViewControllerDataSource: ValueCellDataSource {
case risksHeader
case risks
case risksDisclaimer
case aiDisclosureHeader
case aiDisclosureFunding
case aiDisclosureGenerated
case aiDisclosureOtherDetails
case aiDisclosureDisclaimer
case environmentalCommitmentsHeader
case environmentalCommitments
case environmentalCommitmentsDisclaimer
Expand All @@ -29,6 +34,7 @@ internal final class ProjectPageViewControllerDataSource: ValueCellDataSource {
case environmentalCommitments
case faqs
case risks
case aiDisclosure

var description: String {
switch self {
Expand All @@ -42,6 +48,22 @@ internal final class ProjectPageViewControllerDataSource: ValueCellDataSource {
return Strings.Frequently_asked_questions()
case .risks:
return Strings.Risks_and_challenges()
case .aiDisclosure:
return Strings.Use_of_ai()
}
}
}

private enum GeneratedAIQuestionHeaderValue {
case doYouHaveConsentOfOwners
case partsOfProjectAIGenerated

var description: String {
switch self {
case .doYouHaveConsentOfOwners:
return Strings.Do_you_have_the_consent_of_the_owners_of_the_works_used_for_AI()
case .partsOfProjectAIGenerated:
return Strings.What_parts_of_your_project_will_use_AI_generated_content()
}
}
}
Expand Down Expand Up @@ -207,8 +229,82 @@ internal final class ProjectPageViewControllerDataSource: ValueCellDataSource {
inSection: Section.risksDisclaimer.rawValue
)
case .aiDisclosure:
// TODO: Doing in: https://kickstarter.atlassian.net/browse/MBL-902
_ = {}
self.set(
values: [HeaderValue.aiDisclosure.description],
cellClass: ProjectHeaderCell.self,
inSection: Section.aiDisclosureHeader.rawValue
)

guard let aiDisclosure = project.extendedProjectProperties?.aiDisclosure else {
self.set(
values: [.aiDisclosure],
cellClass: ProjectTabDisclaimerCell.self,
inSection: Section.aiDisclosureDisclaimer.rawValue
)

return
}

let aiDisclosureFundingAvailableToDisplay = aiDisclosure.funding.fundingForAiAttribution || aiDisclosure
.funding.fundingForAiConsent || aiDisclosure.funding.fundingForAiOption
let aiDisclosureShouldBeIncluded = aiDisclosure.involvesFunding
let includeAIFunding = aiDisclosureFundingAvailableToDisplay && aiDisclosureShouldBeIncluded

if includeAIFunding {
self.set(
values: [aiDisclosure.funding],
cellClass: ProjectTabCheckmarkListCell.self,
inSection: Section.aiDisclosureFunding.rawValue
)
}

if aiDisclosure.involvesGeneration {
self.appendRow(
value: Strings.I_plan_to_use_AI_generated_content(),
cellClass: ProjectTabTitleCell.self,
toSection: Section.aiDisclosureGenerated.rawValue
)

if let detailsValues = aiDisclosure.generatedByAiDetails {
let value = (
GeneratedAIQuestionHeaderValue.partsOfProjectAIGenerated.description,
detailsValues.description
)
self
.appendRow(
value: value,
cellClass: ProjectTabQuestionAnswerCell.self,
toSection: Section.aiDisclosureGenerated.rawValue
)
}

if let consentValues = aiDisclosure.generatedByAiConsent {
let value = (
GeneratedAIQuestionHeaderValue.doYouHaveConsentOfOwners.description,
consentValues.description
)
self
.appendRow(
value: value,
cellClass: ProjectTabQuestionAnswerCell.self,
toSection: Section.aiDisclosureGenerated.rawValue
)
}
}

if let otherAIDetailValues = aiDisclosure.otherAiDetails, aiDisclosure.involvesOther {
self.set(
values: [otherAIDetailValues],
cellClass: ProjectTabCategoryDescriptionCell.self,
inSection: Section.aiDisclosureOtherDetails.rawValue
)
}

self.set(
values: [.aiDisclosure],
cellClass: ProjectTabDisclaimerCell.self,
inSection: Section.aiDisclosureDisclaimer.rawValue
)
case .environmentalCommitments:
let environmentalCommitments = project.extendedProjectProperties?.environmentalCommitments ?? []

Expand All @@ -220,24 +316,30 @@ internal final class ProjectPageViewControllerDataSource: ValueCellDataSource {

self.set(
values: environmentalCommitments,
cellClass: ProjectEnvironmentalCommitmentCell.self,
cellClass: ProjectTabCategoryDescriptionCell.self,
inSection: Section.environmentalCommitments.rawValue
)

self.set(
values: [()],
cellClass: ProjectEnvironmentalCommitmentDisclaimerCell.self,
values: [.environmental],
cellClass: ProjectTabDisclaimerCell.self,
inSection: Section.environmentalCommitmentsDisclaimer.rawValue
)
}
}

override func configureCell(tableCell cell: UITableViewCell, withValue value: Any) {
switch (cell, value) {
case let (cell as ProjectEnvironmentalCommitmentCell, value as ProjectEnvironmentalCommitment):
case let (cell as ProjectTabTitleCell, value as String):
cell.configureWith(value: value)
case let (cell as ProjectTabQuestionAnswerCell, value as (String, String)):
cell.configureWith(value: value)
case let (cell as ProjectTabCategoryDescriptionCell, value as ProjectTabCategoryDescription):
cell.configureWith(value: value)
case let (cell as ProjectTabCheckmarkListCell, value as ProjectTabFundingOptions):
cell.configureWith(value: value)
case let (cell as ProjectTabDisclaimerCell, value as ProjectDisclaimerType):
cell.configureWith(value: value)
case let (cell as ProjectEnvironmentalCommitmentDisclaimerCell, _):
cell.configureWith(value: ())
case let (cell as ProjectHeaderCell, value as String):
cell.configureWith(value: value)
case let (cell as ProjectFAQsAskAQuestionCell, _):
Expand Down

0 comments on commit 3d464ee

Please sign in to comment.