Skip to content

Commit 0689f87

Browse files
committed
Move two-column view to the new TopPerformersSectionHeaderView.
1 parent 319ac6c commit 0689f87

File tree

3 files changed

+128
-42
lines changed

3 files changed

+128
-42
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,7 @@ extension TopPerformerDataViewController: UITableViewDataSource {
223223

224224
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
225225
if isMyStoreTabUpdatesEnabled {
226-
guard let cell =
227-
tableView.dequeueReusableHeaderFooterView(withIdentifier: TwoColumnSectionHeaderView.reuseIdentifier) as? TwoColumnSectionHeaderView else {
228-
fatalError()
229-
}
230-
231-
cell.topMarginSpacing = Constants.sectionHeaderTopSpacing
232-
cell.shouldShowUppercase = false
233-
cell.leftText = Text.sectionLeftColumn
234-
cell.rightText = Text.sectionRightColumn
235-
return cell
226+
return nil
236227
} else {
237228
guard let cell =
238229
tableView.dequeueReusableHeaderFooterView(withIdentifier: TopPerformersHeaderView.reuseIdentifier) as? TopPerformersHeaderView else {
@@ -274,11 +265,11 @@ extension TopPerformerDataViewController: UITableViewDelegate {
274265
}
275266

276267
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
277-
return Constants.estimatedSectionHeight
268+
return isMyStoreTabUpdatesEnabled ? 0: Constants.estimatedSectionHeight
278269
}
279270

280271
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
281-
return UITableView.automaticDimension
272+
return isMyStoreTabUpdatesEnabled ? 0: UITableView.automaticDimension
282273
}
283274
}
284275

WooCommerce/Classes/ViewRelated/Dashboard/Stats v4/StoreStatsAndTopPerformersPeriodViewController.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import UIKit
2+
import struct WordPressUI.GhostStyle
23
import XLPagerTabStrip
34
import Yosemite
45
import Observables
@@ -74,6 +75,10 @@ final class StoreStatsAndTopPerformersPeriodViewController: UIViewController {
7475
return stackView
7576
}()
7677

78+
private lazy var topPerformersHeaderView =
79+
TopPerformersSectionHeaderView(title: NSLocalizedString("Top Performers",
80+
comment: "Header label for Top Performers section of My Store tab."))
81+
7782
// MARK: Child View Controllers
7883

7984
private lazy var storeStatsPeriodViewController: StoreStatsV4PeriodViewController = {
@@ -156,6 +161,9 @@ final class StoreStatsAndTopPerformersPeriodViewController: UIViewController {
156161
// Fix any incomplete animation of the refresh control
157162
// when switching tabs mid-animation
158163
refreshControl.resetAnimation(in: scrollView)
164+
165+
// After returning to the My Store tab, `restartGhostAnimation` is required to resume ghost animation.
166+
restartGhostAnimationIfNeeded()
159167
}
160168

161169
override func viewDidAppear(_ animated: Bool) {
@@ -186,13 +194,15 @@ extension StoreStatsAndTopPerformersPeriodViewController {
186194

187195
func displayGhostContent() {
188196
storeStatsPeriodViewController.displayGhostContent()
197+
topPerformersHeaderView.startGhostAnimation(style: Constants.ghostStyle)
189198
topPerformersPeriodViewController.displayGhostContent()
190199
}
191200

192201
/// Removes the placeholder content for store stats.
193202
///
194203
func removeStoreStatsGhostContent() {
195204
storeStatsPeriodViewController.removeGhostContent()
205+
topPerformersHeaderView.stopGhostAnimation()
196206
}
197207

198208
/// Removes the placeholder content for top performers.
@@ -206,6 +216,13 @@ extension StoreStatsAndTopPerformersPeriodViewController {
206216
var shouldDisplayStoreStatsGhostContent: Bool {
207217
return storeStatsPeriodViewController.shouldDisplayGhostContent
208218
}
219+
220+
func restartGhostAnimationIfNeeded() {
221+
guard topPerformersHeaderView.superview != nil else {
222+
return
223+
}
224+
topPerformersHeaderView.restartGhostAnimation(style: Constants.ghostStyle)
225+
}
209226
}
210227

211228
// MARK: - IndicatorInfoProvider Conformance (Tab Bar)
@@ -286,9 +303,6 @@ private extension StoreStatsAndTopPerformersPeriodViewController {
286303
stackView.addArrangedSubviews(inAppFeedbackCardViewsForStackView)
287304

288305
// Top performers header.
289-
let topPerformersHeaderView = TopPerformersSectionHeaderView(title:
290-
NSLocalizedString("Top Performers",
291-
comment: "Header label for Top Performers section of My Store tab."))
292306
stackView.addArrangedSubview(topPerformersHeaderView)
293307

294308
// Top performers.
@@ -343,5 +357,6 @@ private extension StoreStatsAndTopPerformersPeriodViewController {
343357
private extension StoreStatsAndTopPerformersPeriodViewController {
344358
enum Constants {
345359
static let storeStatsPeriodViewHeight: CGFloat = 444
360+
static let ghostStyle: GhostStyle = .wooDefaultGhostStyle
346361
}
347362
}

WooCommerce/Classes/ViewRelated/Dashboard/Stats v4/TopPerformersSectionHeaderView.swift

Lines changed: 107 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,15 @@ import UIKit
22
import Experiments
33

44
/// Section header view shown above the top performers data view.
5+
/// This contains a vertical stack view of a title label and a two-column view of labels for top performers data (products and items sold).
56
///
6-
class TopPerformersSectionHeaderView: UIView {
7-
private lazy var label: UILabel = {
8-
return UILabel(frame: .zero)
9-
}()
10-
11-
init(title: String, featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService) {
7+
final class TopPerformersSectionHeaderView: UIView {
8+
init(title: String) {
129
super.init(frame: .zero)
1310
translatesAutoresizingMaskIntoConstraints = false
1411

15-
let isMyStoreTabUpdatesEnabled = featureFlagService.isFeatureFlagEnabled(.myStoreTabUpdates)
16-
configureView(isMyStoreTabUpdatesEnabled: isMyStoreTabUpdatesEnabled)
17-
configureLabel(title: title, isMyStoreTabUpdatesEnabled: isMyStoreTabUpdatesEnabled)
12+
configureView()
13+
configureStackView(title: title)
1814
}
1915

2016
required init?(coder aDecoder: NSCoder) {
@@ -23,43 +19,127 @@ class TopPerformersSectionHeaderView: UIView {
2319
}
2420

2521
private extension TopPerformersSectionHeaderView {
26-
func configureView(isMyStoreTabUpdatesEnabled: Bool) {
27-
guard isMyStoreTabUpdatesEnabled else {
28-
return
29-
}
22+
func configureView() {
3023
backgroundColor = Constants.backgroundColor
3124
}
3225

33-
func configureLabel(title: String, isMyStoreTabUpdatesEnabled: Bool) {
34-
addSubview(label)
26+
func configureStackView(title: String) {
27+
let titleView = createTitleLabelContainerView(title: title)
28+
let twoColumnStackView: UIStackView = {
29+
let leftLabelContainer = createColumnLabelContainerView(labelText: Localization.leftColumn, columnPosition: .left)
30+
let rightLabelContainer = createColumnLabelContainerView(labelText: Localization.rightColumn, columnPosition: .right)
31+
let stackView = UIStackView(arrangedSubviews: [leftLabelContainer, rightLabelContainer])
32+
stackView.axis = .horizontal
33+
stackView.distribution = .fillEqually
34+
stackView.spacing = Constants.columnHorizontalSpacing
35+
stackView.translatesAutoresizingMaskIntoConstraints = false
36+
return stackView
37+
}()
38+
39+
let contentStackView: UIStackView = {
40+
let stackView = UIStackView(arrangedSubviews: [titleView, twoColumnStackView])
41+
stackView.axis = .vertical
42+
stackView.alignment = .fill
43+
stackView.spacing = Constants.titleAndColumnSpacing
44+
return stackView
45+
}()
46+
47+
addSubview(contentStackView)
3548

36-
label.text = title
49+
contentStackView.translatesAutoresizingMaskIntoConstraints = false
50+
let labelInsets = Constants.labelInsets
51+
NSLayoutConstraint.activate([
52+
contentStackView.topAnchor.constraint(equalTo: topAnchor, constant: labelInsets.top),
53+
contentStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: labelInsets.left),
54+
contentStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -labelInsets.right),
55+
contentStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -labelInsets.bottom)
56+
])
57+
}
3758

38-
if isMyStoreTabUpdatesEnabled {
59+
func createTitleLabelContainerView(title: String) -> UIView {
60+
let label: UILabel = {
61+
let label = UILabel(frame: .zero)
62+
label.text = title
3963
label.applyHeadlineStyle()
4064
label.textColor = .systemColor(.label)
41-
} else {
65+
return label
66+
}()
67+
68+
let containerView: UIView = {
69+
let view = UIView()
70+
view.addSubview(label)
71+
72+
label.translatesAutoresizingMaskIntoConstraints = false
73+
view.translatesAutoresizingMaskIntoConstraints = false
74+
75+
NSLayoutConstraint.activate([
76+
label.topAnchor.constraint(equalTo: view.topAnchor),
77+
label.bottomAnchor.constraint(equalTo: view.bottomAnchor),
78+
label.leadingAnchor.constraint(equalTo: view.leadingAnchor),
79+
label.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor)
80+
])
81+
return view
82+
}()
83+
return containerView
84+
}
85+
86+
func createColumnLabelContainerView(labelText: String?, columnPosition: ColumnPosition) -> UIView {
87+
let label: UILabel = {
88+
let label = UILabel(frame: .zero)
89+
label.text = labelText
4290
label.applyFootnoteStyle()
91+
label.numberOfLines = 0
4392
label.textColor = .listIcon
44-
}
93+
return label
94+
}()
4595

46-
label.translatesAutoresizingMaskIntoConstraints = false
47-
let labelInsets = isMyStoreTabUpdatesEnabled ? Constants.labelInsets: Constants.legacyLabelInsets
48-
NSLayoutConstraint.activate([
49-
label.topAnchor.constraint(greaterThanOrEqualTo: topAnchor),
50-
label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: labelInsets.left),
51-
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -labelInsets.right),
52-
label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -labelInsets.bottom)
96+
let containerView: UIView = {
97+
let view = UIView()
98+
view.addSubview(label)
99+
100+
label.translatesAutoresizingMaskIntoConstraints = false
101+
view.translatesAutoresizingMaskIntoConstraints = false
102+
103+
NSLayoutConstraint.activate([
104+
label.topAnchor.constraint(equalTo: view.topAnchor),
105+
label.bottomAnchor.constraint(equalTo: view.bottomAnchor)
53106
])
107+
108+
switch columnPosition {
109+
case .left:
110+
NSLayoutConstraint.activate([
111+
label.leadingAnchor.constraint(equalTo: view.leadingAnchor),
112+
label.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor)
113+
])
114+
case .right:
115+
NSLayoutConstraint.activate([
116+
label.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor),
117+
label.trailingAnchor.constraint(equalTo: view.trailingAnchor)
118+
])
119+
}
120+
return view
121+
}()
122+
return containerView
54123
}
55124
}
56125

57126
// MARK: - Constants!
58127
//
59128
private extension TopPerformersSectionHeaderView {
129+
enum Localization {
130+
static let leftColumn = NSLocalizedString("Products", comment: "Description for Top Performers left column header")
131+
static let rightColumn = NSLocalizedString("Items Sold", comment: "Description for Top Performers right column header")
132+
}
133+
60134
enum Constants {
61135
static let labelInsets = UIEdgeInsets(top: 0, left: 16, bottom: 8, right: 16)
62-
static let legacyLabelInsets = UIEdgeInsets(top: 0, left: 14, bottom: 6, right: 14)
63136
static let backgroundColor: UIColor = .systemBackground
137+
static let columnHorizontalSpacing: CGFloat = 30
138+
static let titleAndColumnSpacing: CGFloat = 16
139+
}
140+
141+
enum ColumnPosition {
142+
case left
143+
case right
64144
}
65145
}

0 commit comments

Comments
 (0)