Skip to content

Commit 582294b

Browse files
Merge pull request #19833 from wordpress-mobile/task/19813-phase-4-button
Jetpack Focus: Add switch card to the menu in phase 4
2 parents ec1870a + 27295ee commit 582294b

File tree

10 files changed

+290
-53
lines changed

10 files changed

+290
-53
lines changed

WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ - (void)configureTableViewData
741741
if (MigrationSuccessCardView.shouldShowMigrationSuccessCard == YES) {
742742
[marr addObject:[self migrationSuccessSectionViewModel]];
743743
}
744-
if (self.shouldShowJetpackBrandingMenuCard == YES) {
744+
if (self.shouldShowTopJetpackBrandingMenuCard == YES) {
745745
[marr addObject:[self jetpackCardSectionViewModel]];
746746
}
747747

@@ -777,6 +777,10 @@ - (void)configureTableViewData
777777
if ([self.blog supports:BlogFeatureRemovable]) {
778778
[marr addObject:[self removeSiteSectionViewModel]];
779779
}
780+
781+
if (self.shouldShowBottomJetpackBrandingMenuCard == YES) {
782+
[marr addObject:[self jetpackCardSectionViewModel]];
783+
}
780784

781785
// Assign non mutable copy.
782786
self.tableSections = [NSArray arrayWithArray:marr];

WordPress/Classes/ViewRelated/Jetpack/Branding/Fullscreen Overlay/JetpackFullscreenOverlayGeneralViewModel.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct JetpackFullscreenOverlayGeneralViewModel: JetpackFullscreenOverlayViewMod
3131
return true
3232

3333
// Phase Four: Show feature-collection overlays. Features are removed by this point so they are irrelevant.
34+
case (.four, .card):
35+
fallthrough
3436
case (.four, .appOpen):
3537
return true
3638

WordPress/Classes/ViewRelated/Jetpack/Branding/Menu Card/BlogDetailsViewController+JetpackBrandingMenuCard.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ import Foundation
22

33
extension BlogDetailsViewController {
44

5-
@objc var shouldShowJetpackBrandingMenuCard: Bool {
5+
@objc var shouldShowTopJetpackBrandingMenuCard: Bool {
66
let presenter = JetpackBrandingMenuCardPresenter()
7-
return presenter.shouldShowCard()
7+
return presenter.shouldShowTopCard()
8+
}
9+
10+
@objc var shouldShowBottomJetpackBrandingMenuCard: Bool {
11+
let presenter = JetpackBrandingMenuCardPresenter()
12+
return presenter.shouldShowBottomCard()
813
}
914

1015
@objc func jetpackCardSectionViewModel() -> BlogDetailsSection {

WordPress/Classes/ViewRelated/Jetpack/Branding/Menu Card/JetpackBrandingMenuCardCell.swift

Lines changed: 153 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class JetpackBrandingMenuCardCell: UITableViewCell {
77

88
private weak var viewController: BlogDetailsViewController?
99
private var presenter: JetpackBrandingMenuCardPresenter
10+
private var config: JetpackBrandingMenuCardPresenter.Config?
1011

1112
/// Sets the animation based on the language orientation
1213
private var animation: Animation? {
@@ -15,35 +16,42 @@ class JetpackBrandingMenuCardCell: UITableViewCell {
1516
Animation.named(Constants.animationRtl)
1617
}
1718

18-
// MARK: Lazy Loading Views
19+
private var cardType: JetpackBrandingMenuCardPresenter.Config.CardType {
20+
config?.type ?? .expanded
21+
}
22+
23+
// MARK: Lazy Loading General Views
1924

2025
private lazy var cardFrameView: BlogDashboardCardFrameView = {
2126
let frameView = BlogDashboardCardFrameView()
2227
frameView.translatesAutoresizingMaskIntoConstraints = false
23-
frameView.configureButtonContainerStackView()
2428
frameView.hideHeader()
2529

26-
frameView.onEllipsisButtonTap = { [weak self] in
27-
self?.presenter.trackContexualMenuAccessed()
30+
if cardType == .expanded {
31+
frameView.configureButtonContainerStackView()
32+
frameView.onEllipsisButtonTap = { [weak self] in
33+
self?.presenter.trackContexualMenuAccessed()
34+
}
35+
frameView.ellipsisButton.showsMenuAsPrimaryAction = true
36+
frameView.ellipsisButton.menu = contextMenu
2837
}
29-
frameView.ellipsisButton.showsMenuAsPrimaryAction = true
30-
frameView.ellipsisButton.menu = contextMenu
31-
3238
return frameView
3339
}()
3440

3541
private lazy var containerStackView: UIStackView = {
3642
let stackView = UIStackView()
37-
stackView.axis = .vertical
43+
stackView.axis = stackViewAxis
3844
stackView.alignment = .fill
3945
stackView.translatesAutoresizingMaskIntoConstraints = false
40-
stackView.spacing = Metrics.spacing
41-
stackView.layoutMargins = Metrics.containerMargins
46+
stackView.spacing = stackViewSpacing
47+
stackView.directionalLayoutMargins = stackViewLayoutMargins
4248
stackView.isLayoutMarginsRelativeArrangement = true
43-
stackView.addArrangedSubviews([logosSuperview, descriptionLabel, learnMoreSuperview])
49+
stackView.addArrangedSubviews(stackViewSubviews)
4450
return stackView
4551
}()
4652

53+
// MARK: Lazy Loading Expanded Card Views
54+
4755
private lazy var logosSuperview: UIView = {
4856
let view = UIView()
4957
view.translatesAutoresizingMaskIntoConstraints = false
@@ -63,7 +71,7 @@ class JetpackBrandingMenuCardCell: UITableViewCell {
6371
view.animation = animation
6472

6573
// Height Constraint
66-
view.heightAnchor.constraint(equalToConstant: Metrics.animationsViewHeight).isActive = true
74+
view.heightAnchor.constraint(equalToConstant: Metrics.Expanded.animationsViewHeight).isActive = true
6775

6876
// Width constraint to achieve aspect ratio
6977
let animationSize = animation?.size ?? .init(width: 1, height: 1)
@@ -73,13 +81,13 @@ class JetpackBrandingMenuCardCell: UITableViewCell {
7381
return view
7482
}()
7583

76-
private lazy var descriptionLabel: UILabel = {
84+
private lazy var label: UILabel = {
7785
let label = UILabel()
7886
label.translatesAutoresizingMaskIntoConstraints = false
79-
label.font = Metrics.descriptionFont
80-
label.numberOfLines = 0
87+
label.font = labelFont
88+
label.textColor = labelTextColor
89+
label.numberOfLines = labelNumberOfLines
8190
label.adjustsFontForContentSizeCategory = true
82-
8391
return label
8492
}()
8593

@@ -117,16 +125,46 @@ class JetpackBrandingMenuCardCell: UITableViewCell {
117125
return button
118126
}()
119127

128+
// MARK: Lazy Loading Compact Card Views
129+
130+
private lazy var jetpackIconImageView: UIImageView = {
131+
let imageView = UIImageView()
132+
let image = UIImage(named: Constants.jetpackIcon)
133+
imageView.translatesAutoresizingMaskIntoConstraints = false
134+
imageView.image = image
135+
imageView.heightAnchor.constraint(equalToConstant: Metrics.Compact.logoImageViewSize).isActive = true
136+
imageView.widthAnchor.constraint(equalToConstant: Metrics.Compact.logoImageViewSize).isActive = true
137+
return imageView
138+
}()
139+
140+
private lazy var ellipsisButton: UIButton = {
141+
let button = UIButton(type: .custom)
142+
button.setImage(UIImage.gridicon(.ellipsis).imageWithTintColor(Metrics.Compact.ellipsisButtonColor), for: .normal)
143+
button.contentEdgeInsets = Metrics.Compact.ellipsisButtonPadding
144+
button.isAccessibilityElement = true
145+
button.accessibilityLabel = Strings.ellipsisButtonAccessibilityLabel
146+
button.accessibilityTraits = .button
147+
button.setContentHuggingPriority(.defaultHigh, for: .horizontal)
148+
button.showsMenuAsPrimaryAction = true
149+
button.menu = contextMenu
150+
button.on([.touchUpInside, .menuActionTriggered]) { [weak self] _ in
151+
self?.presenter.trackContexualMenuAccessed()
152+
}
153+
return button
154+
}()
155+
120156
// MARK: Initializers
121157

122158
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
123159
presenter = JetpackBrandingMenuCardPresenter()
160+
config = presenter.cardConfig()
124161
super.init(style: style, reuseIdentifier: reuseIdentifier)
125162
commonInit()
126163
}
127164

128165
required init?(coder: NSCoder) {
129166
presenter = JetpackBrandingMenuCardPresenter()
167+
config = presenter.cardConfig()
130168
super.init(coder: coder)
131169
commonInit()
132170
}
@@ -148,15 +186,14 @@ class JetpackBrandingMenuCardCell: UITableViewCell {
148186

149187
private func setupContent() {
150188
logosAnimationView.currentProgress = 1.0
151-
let config = presenter.cardConfig()
152-
descriptionLabel.text = config?.description
189+
label.text = config?.description
153190
learnMoreSuperview.isHidden = config?.learnMoreButtonURL == nil
154191
}
155192

156193
// MARK: Actions
157194

158195
@objc private func learnMoreButtonTapped() {
159-
guard let config = presenter.cardConfig(),
196+
guard let config = config,
160197
let urlString = config.learnMoreButtonURL,
161198
let url = URL(string: urlString) else {
162199
return
@@ -200,25 +237,106 @@ private extension JetpackBrandingMenuCardCell {
200237
}
201238
}
202239

240+
private extension JetpackBrandingMenuCardCell {
241+
var stackViewAxis: NSLayoutConstraint.Axis {
242+
switch cardType {
243+
case .compact:
244+
return .horizontal
245+
case .expanded:
246+
return .vertical
247+
}
248+
}
249+
250+
var stackViewSpacing: CGFloat {
251+
switch cardType {
252+
case .compact:
253+
return Metrics.Compact.spacing
254+
case .expanded:
255+
return Metrics.Expanded.spacing
256+
}
257+
}
258+
259+
var stackViewLayoutMargins: NSDirectionalEdgeInsets {
260+
switch cardType {
261+
case .compact:
262+
return Metrics.Compact.containerMargins
263+
case .expanded:
264+
return Metrics.Expanded.containerMargins
265+
}
266+
}
267+
268+
var stackViewSubviews: [UIView] {
269+
switch cardType {
270+
case .compact:
271+
return [jetpackIconImageView, label, ellipsisButton]
272+
case .expanded:
273+
return [logosSuperview, label, learnMoreSuperview]
274+
}
275+
}
276+
277+
var labelFont: UIFont {
278+
switch cardType {
279+
case .compact:
280+
return Metrics.Compact.labelFont
281+
case .expanded:
282+
return Metrics.Expanded.labelFont
283+
}
284+
}
285+
286+
var labelTextColor: UIColor {
287+
switch cardType {
288+
case .compact:
289+
return Metrics.Compact.labelTextColor
290+
case .expanded:
291+
return Metrics.Expanded.labelTextColor
292+
}
293+
}
294+
295+
var labelNumberOfLines: Int {
296+
switch cardType {
297+
case .compact:
298+
return 1
299+
case .expanded:
300+
return 0
301+
}
302+
}
303+
304+
}
305+
203306
private extension JetpackBrandingMenuCardCell {
204307

205308
enum Metrics {
206309
// General
207-
static let spacing: CGFloat = 10
208-
static let containerMargins = UIEdgeInsets(top: 20, left: 20, bottom: 12, right: 20)
209-
static let cardFrameConstraintPriority = UILayoutPriority(999)
210-
211-
// Animation view
212-
static let animationsViewHeight: CGFloat = 32
310+
enum Expanded {
311+
static let spacing: CGFloat = 10
312+
static let containerMargins = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 12, trailing: 20)
313+
static let animationsViewHeight: CGFloat = 32
314+
static var labelFont: UIFont {
315+
let maximumFontPointSize: CGFloat = 16
316+
let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
317+
let font = UIFont(descriptor: fontDescriptor, size: min(fontDescriptor.pointSize, maximumFontPointSize))
318+
return UIFontMetrics.default.scaledFont(for: font)
319+
}
320+
static let labelTextColor: UIColor = .label
321+
}
213322

214-
// Description Label
215-
static var descriptionFont: UIFont {
216-
let maximumFontPointSize: CGFloat = 16
217-
let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
218-
let font = UIFont(descriptor: fontDescriptor, size: min(fontDescriptor.pointSize, maximumFontPointSize))
219-
return UIFontMetrics.default.scaledFont(for: font)
323+
enum Compact {
324+
static let spacing: CGFloat = 15
325+
static let containerMargins = NSDirectionalEdgeInsets(top: 15, leading: 20, bottom: 7, trailing: 12)
326+
static let logoImageViewSize: CGFloat = 24
327+
static let ellipsisButtonPadding = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
328+
static let ellipsisButtonColor = UIColor.muriel(color: .gray, .shade20)
329+
static var labelFont: UIFont {
330+
let maximumFontPointSize: CGFloat = 17
331+
let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
332+
let font = UIFont(descriptor: fontDescriptor, size: min(fontDescriptor.pointSize, maximumFontPointSize))
333+
return UIFontMetrics.default.scaledFont(for: font)
334+
}
335+
static let labelTextColor: UIColor = UIColor.muriel(color: .jetpackGreen, .shade40)
220336
}
221337

338+
static let cardFrameConstraintPriority = UILayoutPriority(999)
339+
222340
// Learn more button
223341
static let learnMoreButtonContentInsets = NSDirectionalEdgeInsets(top: 4, leading: 0, bottom: 4, trailing: 24)
224342
static let learnMoreButtonContentEdgeInsets = UIEdgeInsets(top: 4, left: 0, bottom: 4, right: 24)
@@ -231,6 +349,7 @@ private extension JetpackBrandingMenuCardCell {
231349
static let analyticsSource = "jetpack_menu_card"
232350
static let remindMeLaterSystemImageName = "alarm"
233351
static let hideThisLaterSystemImageName = "eye.slash"
352+
static let jetpackIcon = "icon-jetpack"
234353
}
235354

236355
enum Strings {
@@ -243,6 +362,9 @@ private extension JetpackBrandingMenuCardCell {
243362
static let hideCardMenuItemTitle = NSLocalizedString("jetpack.menuCard.hide",
244363
value: "Hide this",
245364
comment: "Menu item title to hide the card.")
365+
static let ellipsisButtonAccessibilityLabel = NSLocalizedString("ellipsisButton.AccessibilityLabel",
366+
value: "More",
367+
comment: "Accessibility label for more button in dashboard quick start card.")
246368
}
247369

248370
enum MenuItem {

0 commit comments

Comments
 (0)