Skip to content

Commit

Permalink
Add FXIOS-7383 [v119] Add footer to settings card (#16407)
Browse files Browse the repository at this point in the history
* Add footer to settings card

* Dismiss bottom sheet when footer button is tapped

* Fix settings tests
  • Loading branch information
thatswinnie authored Sep 19, 2023
1 parent 41f3844 commit 76b68a8
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 14 deletions.
14 changes: 13 additions & 1 deletion BrowserKit/Sources/ComponentLibrary/ActionFooterView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ public struct ActionFooterViewModel {
let actionTitle: String
let a11yTitleIdentifier: String
let a11yActionIdentifier: String
let onTap: (() -> Void)

public init(
title: String,
actionTitle: String,
a11yTitleIdentifier: String,
a11yActionIdentifier: String
a11yActionIdentifier: String,
onTap: @escaping (() -> Void)
) {
self.title = title
self.actionTitle = actionTitle
self.a11yTitleIdentifier = a11yTitleIdentifier
self.a11yActionIdentifier = a11yActionIdentifier
self.onTap = onTap
}
}

Expand All @@ -30,6 +33,8 @@ public final class ActionFooterView: UIView, ThemeApplicable {
static let buttonSize: CGFloat = 13
}

private var viewModel: ActionFooterViewModel?

private lazy var titleLabel: UILabel = .build { label in
label.font = DefaultDynamicFontHelper.preferredFont(
withTextStyle: .footnote,
Expand All @@ -44,6 +49,7 @@ public final class ActionFooterView: UIView, ThemeApplicable {
size: UX.buttonSize)
button.buttonEdgeSpacing = 0
button.contentHorizontalAlignment = .leading
button.addTarget(self, action: #selector(self.didTapButton), for: .touchUpInside)
}

override init(frame: CGRect) {
Expand All @@ -57,13 +63,19 @@ public final class ActionFooterView: UIView, ThemeApplicable {
}

public func configure(viewModel: ActionFooterViewModel) {
self.viewModel = viewModel
titleLabel.text = viewModel.title
primaryButton.setTitle(viewModel.actionTitle, for: .normal)

titleLabel.accessibilityIdentifier = viewModel.a11yTitleIdentifier
primaryButton.accessibilityIdentifier = viewModel.a11yActionIdentifier
}

@objc
private func didTapButton() {
viewModel?.onTap()
}

private func setupLayout() {
addSubview(titleLabel)
addSubview(primaryButton)
Expand Down
2 changes: 2 additions & 0 deletions Client/Application/AccessibilityIdentifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ public struct AccessibilityIdentifiers {
static let productsLabel = "Shopping.SettingsCard.ProductsLabel"
static let turnOffButton = "Shopping.SettingsCard.TurnOffButton"
static let recommendedProductsSwitch = "Shopping.SettingCard.RecommendedProductsSwitch"
static let footerTitle = "Shopping.SettingCard.footerTitle"
static let footerAction = "Shopping.SettingCard.footerAction"
}

struct NoAnalysisCard {
Expand Down
2 changes: 1 addition & 1 deletion Client/Frontend/Fakespot/FakespotViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class FakespotViewController: UIViewController, Themeable, UIAdaptivePresentatio
case .settingsCard:
let view: FakespotSettingsCardView = .build()
view.configure(viewModel.settingsCardViewModel)
viewModel.settingsCardViewModel.onTapTurnOffButton = { [weak self] in
viewModel.settingsCardViewModel.dismissViewController = { [weak self] in
guard let self = self else { return }
self.delegate?.fakespotControllerDidDismiss()
}
Expand Down
60 changes: 48 additions & 12 deletions Client/Frontend/Fakespot/Views/FakespotSettingsCardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ import Shared
import ComponentLibrary

class FakespotSettingsCardViewModel {
let prefs: Prefs
let cardA11yId: String = AccessibilityIdentifiers.Shopping.SettingsCard.card
typealias a11yIds = AccessibilityIdentifiers.Shopping.SettingsCard
private let prefs: Prefs
private let tabManager: TabManager

let cardA11yId: String = a11yIds.card
let showProductsLabelTitle: String = .Shopping.SettingsCardRecommendedProductsLabel
let showProductsLabelTitleA11yId: String = AccessibilityIdentifiers.Shopping.SettingsCard.productsLabel
let showProductsLabelTitleA11yId: String = a11yIds.productsLabel
let turnOffButtonTitle: String = .Shopping.SettingsCardTurnOffButton
let turnOffButtonTitleA11yId: String = AccessibilityIdentifiers.Shopping.SettingsCard.turnOffButton
let recommendedProductsSwitchA11yId: String = AccessibilityIdentifiers.Shopping.SettingsCard.recommendedProductsSwitch
var onTapTurnOffButton: (() -> Void)?
let turnOffButtonTitleA11yId: String = a11yIds.turnOffButton
let recommendedProductsSwitchA11yId: String = a11yIds.recommendedProductsSwitch
let footerTitle: String = ""
let footerActionTitle: String = .Shopping.SettingsCardFooterAction
let footerA11yTitleIdentifier: String = a11yIds.footerTitle
let footerA11yActionIdentifier: String = a11yIds.footerAction
let footerActionUrl = URL(string: "http://fakespot.com/")
var dismissViewController: (() -> Void)?

var isReviewQualityCheckOn: Bool {
get { return prefs.boolForKey(PrefsKeys.Shopping2023OptIn) ?? true }
Expand All @@ -27,8 +35,24 @@ class FakespotSettingsCardViewModel {
set { prefs.setBool(newValue, forKey: PrefsKeys.Shopping2023EnableAds) }
}

init(profile: Profile = AppContainer.shared.resolve()) {
var footerModel: ActionFooterViewModel {
return ActionFooterViewModel(title: footerTitle,
actionTitle: footerActionTitle,
a11yTitleIdentifier: footerA11yTitleIdentifier,
a11yActionIdentifier: footerA11yActionIdentifier,
onTap: { self.onTapButton() })
}

init(profile: Profile = AppContainer.shared.resolve(),
tabManager: TabManager = AppContainer.shared.resolve()) {
prefs = profile.prefs
self.tabManager = tabManager
}

func onTapButton() {
guard let footerActionUrl else { return }
tabManager.addTabsForURLs([footerActionUrl], zombie: false, shouldSelectTab: true)
dismissViewController?()
}

func recordTelemetryForShoppingOptedOut() {
Expand All @@ -49,6 +73,8 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
static let labelSwitchStackViewSpacing: CGFloat = 12
static let contentInsets = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
static let buttonInsets = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)
static let cardBottomSpace: CGFloat = 8
static let footerHorizontalSpace: CGFloat = 8
}

private var viewModel: FakespotSettingsCardViewModel?
Expand Down Expand Up @@ -94,6 +120,8 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
weight: .semibold)
}

private lazy var footerView: ActionFooterView = .build()

override init(frame: CGRect) {
super.init(frame: frame)
setupLayout()
Expand All @@ -105,6 +133,7 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {

private func setupLayout() {
addSubview(collapsibleContainer)
addSubview(footerView)
contentView.addSubviews(contentStackView, turnOffButton)

[showProductsLabel, recommendedProductsSwitch].forEach(labelSwitchStackView.addArrangedSubview)
Expand All @@ -116,7 +145,7 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
collapsibleContainer.leadingAnchor.constraint(equalTo: leadingAnchor),
collapsibleContainer.topAnchor.constraint(equalTo: topAnchor),
collapsibleContainer.trailingAnchor.constraint(equalTo: trailingAnchor),
collapsibleContainer.bottomAnchor.constraint(equalTo: bottomAnchor),
collapsibleContainer.bottomAnchor.constraint(equalTo: footerView.topAnchor, constant: -UX.cardBottomSpace),

contentStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
contentStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
Expand All @@ -129,6 +158,10 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
turnOffButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,
constant: UX.buttonLeadingTrailingPadding),
turnOffButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),

footerView.leadingAnchor.constraint(equalTo: leadingAnchor),
footerView.trailingAnchor.constraint(equalTo: trailingAnchor),
footerView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}

Expand All @@ -144,7 +177,7 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {

recommendedProductsSwitch.accessibilityIdentifier = viewModel.recommendedProductsSwitchA11yId

let viewModel = CollapsibleCardViewModel(
let collapsibleCardViewModel = CollapsibleCardViewModel(
contentView: contentView,
cardViewA11yId: AccessibilityIdentifiers.Shopping.SettingsCard.card,
title: .Shopping.SettingsCardLabelTitle,
Expand All @@ -158,7 +191,8 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
object: .shoppingSettingsChevronButton)
}
}
collapsibleContainer.configure(viewModel)
collapsibleContainer.configure(collapsibleCardViewModel)
footerView.configure(viewModel: viewModel.footerModel)
}

@objc
Expand All @@ -169,7 +203,7 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
@objc
private func didTapTurnOffButton() {
viewModel?.isReviewQualityCheckOn = false
viewModel?.onTapTurnOffButton?()
viewModel?.dismissViewController?()
viewModel?.recordTelemetryForShoppingOptedOut()
}

Expand All @@ -183,6 +217,8 @@ final class FakespotSettingsCardView: UIView, ThemeApplicable {
recommendedProductsSwitch.tintColor = colors.formKnob

turnOffButton.backgroundColor = colors.actionSecondary
turnOffButton.setTitleColor(colors.textOnLight, for: .normal)
turnOffButton.setTitleColor(colors.textPrimary, for: .normal)

footerView.applyTheme(theme: theme)
}
}
5 changes: 5 additions & 0 deletions Client/Frontend/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3701,6 +3701,11 @@ extension String {
tableName: "Shopping",
value: "Settings Card Collapsed",
comment: "Accessibility label for the up chevron, from Settings Card View displayed in the shopping review quality bottom sheet.")
public static let SettingsCardFooterAction = MZLocalizedString(
key: "", // Shopping.SettingsCard.Footer.Action.v119
tableName: "Shopping",
value: "Review checker is powered by Fakespot by Mozilla",
comment: "Action title of the footer underneath the Settings Card displayed in the shopping review quality bottom sheet.")
public static let NoAnalysisCardHeadlineLabelTitle = MZLocalizedString(
key: "", // Shopping.NoAnalysisCard.HeadlineLabel.Title.v118
tableName: "Shopping",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ final class FakespotSettingsCardViewModelTests: XCTestCase {

override func setUp() {
super.setUp()
DependencyHelperMock().bootstrapDependencies()
mockProfile = MockProfile()
viewModel = FakespotSettingsCardViewModel(profile: mockProfile)
}
Expand Down

0 comments on commit 76b68a8

Please sign in to comment.