From ceecebaa145a986d72c2e3522cc4cf9bb6fb62ed Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 12:59:28 +0300 Subject: [PATCH 01/12] Allow to set number of columns dynamically on StatsGhostableTopCell --- .../GhostViews/StatsGhostCells.swift | 1 - .../GhostViews/StatsGhostTableViewRows.swift | 2 + .../GhostViews/StatsGhostTopCell.swift | 150 ++++++++++++++++++ .../GhostViews/StatsGhostTopCell.xib | 65 +++----- 4 files changed, 172 insertions(+), 46 deletions(-) create mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift index ae5354573297..98f30e98d3ff 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift @@ -24,7 +24,6 @@ class StatsGhostBaseCell: StatsBaseCell { class StatsGhostGrowAudienceCell: StatsGhostBaseCell, NibLoadable { } class StatsGhostTwoColumnCell: StatsGhostBaseCell, NibLoadable { } -class StatsGhostTopCell: StatsGhostBaseCell, NibLoadable { } class StatsGhostTopHeaderCell: StatsGhostBaseCell, NibLoadable { override func awakeFromNib() { super.awakeFromNib() diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift index 1ce5dcc8788d..3a39501557f0 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift @@ -47,6 +47,7 @@ struct StatsGhostTopImmutableRow: StatsRowGhostable { var hideTopBorder = false var hideBottomBorder = false + var numberOfColumns: Int = 2 var statSection: StatSection? = nil // MARK: - Hashable @@ -66,6 +67,7 @@ struct StatsGhostTopImmutableRow: StatsRowGhostable { detailCell.topBorder?.isHidden = hideTopBorder detailCell.bottomBorder?.isHidden = hideBottomBorder detailCell.statSection = statSection + detailCell.numberOfColumns = numberOfColumns } } } diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift new file mode 100644 index 000000000000..9dbb30374275 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift @@ -0,0 +1,150 @@ +import UIKit +import DesignSystem +import WordPressUI + +final class StatsGhostTopCell: StatsGhostBaseCell, NibLoadable { + @IBOutlet private weak var topCellRow: StatsGhostTopCellRow! + @IBOutlet private weak var topCellHeaders: UIStackView! + + var numberOfColumns: Int = 2 { + didSet { + configureCell(with: numberOfColumns) + } + } + + private func configureCell(with count: Int) { + updateHeaders(count: count) + topCellRow.updateColumns(count: count) + } + + private func updateHeaders(count: Int) { + topCellHeaders.removeAllSubviews() + let headers = Array(repeating: UIView(), count: count-1) + headers.forEach { header in + configureHeader(header) + topCellHeaders.addArrangedSubview(header) + } + } + + private func configureHeader(_ header: UIView) { + header.startGhostAnimation() + header.widthAnchor.constraint(equalToConstant: Constants.columnWidth).isActive = true + } +} + +class StatsGhostTopCellRow: UIView { + private let avatarView = UIView() + private let columnsStackView = createStackView() + private let mainColumn = StatsGhostTopCellColumn() + + override init(frame: CGRect) { + super.init(frame: frame) + setupViews() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupViews() + } + + private static func createStackView() -> UIStackView { + let stackView = UIStackView() + stackView.alignment = .fill + stackView.distribution = .fillEqually + stackView.axis = .horizontal + stackView.spacing = .DS.Padding.double + return stackView + } + + private func setupViews() { + [columnsStackView, mainColumn, avatarView].forEach { + $0.translatesAutoresizingMaskIntoConstraints = false + addSubview($0) + } + setupConstraints() + } + + private func setupConstraints() { + NSLayoutConstraint.activate([ + avatarView.heightAnchor.constraint(equalToConstant: .DS.Padding.medium), + avatarView.widthAnchor.constraint(equalToConstant: .DS.Padding.medium), + avatarView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: .DS.Padding.double), + avatarView.topAnchor.constraint(equalTo: topAnchor, constant: .DS.Padding.double), + avatarView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -.DS.Padding.double), + mainColumn.leadingAnchor.constraint(equalTo: avatarView.trailingAnchor, constant: .DS.Padding.double), + mainColumn.centerYAnchor.constraint(equalTo: centerYAnchor), + columnsStackView.leadingAnchor.constraint(equalTo: mainColumn.trailingAnchor, constant: .DS.Padding.double), + columnsStackView.centerYAnchor.constraint(equalTo: centerYAnchor), + columnsStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -.DS.Padding.double) + ]) + } + + func updateColumns(count: Int) { + columnsStackView.removeAllSubviews() + mainColumn.isHidden = count <= 1 + + let columns = Array(repeating: StatsGhostTopCellColumn(width: StatsGhostTopCell.Constants.columnWidth), count: count-1) + columns.forEach(columnsStackView.addArrangedSubview) + } +} + +private class StatsGhostTopCellColumn: UIView { + private let topView = UIView() + private let bottomView = UIView() + private let width: CGFloat? + + init(width: CGFloat? = nil) { + self.width = width + super.init(frame: .zero) + setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupViews() { + let stackView = createStackView() + addSubview(stackView) + pinSubviewToAllEdges(stackView) + setupConstraints() + } + + private func createStackView() -> UIStackView { + let stackView = UIStackView(arrangedSubviews: [topView, bottomView]) + stackView.axis = .vertical + stackView.spacing = .DS.Padding.half + stackView.alignment = .fill + stackView.distribution = .equalSpacing + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + } + + private func setupConstraints() { + var constraints = [ + topView.heightAnchor.constraint(equalToConstant: .DS.Padding.medium), + bottomView.heightAnchor.constraint(equalToConstant: .DS.Padding.double) + ] + + if let width = width { + constraints += [ + topView.widthAnchor.constraint(equalToConstant: width), + bottomView.widthAnchor.constraint(equalToConstant: width) + ] + } + + NSLayoutConstraint.activate(constraints) + startAnimations() + } + + private func startAnimations() { + topView.startGhostAnimation(style: GhostCellStyle.muriel) + bottomView.startGhostAnimation(style: GhostCellStyle.muriel) + } +} + +fileprivate extension StatsGhostTopCell { + enum Constants { + static let columnWidth: CGFloat = 60 + } +} diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib index 1ee2c60cf05c..d005ec3a1558 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib @@ -1,9 +1,9 @@ - + - + @@ -12,71 +12,46 @@ - + - + - - - - - - - - - - - - - - - - - - - + + - + - - - + + + - - - - - - + - - - - - - - - + + + + + + - - - - + + + From 69d3e805a2e7071864b8a5650fd891b79aac52e8 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 13:25:05 +0300 Subject: [PATCH 02/12] Create StatsGhostSingleValue cell for cells displaying Totals --- .../GhostViews/StatsGhostCells.swift | 2 + .../GhostViews/StatsGhostSingleValueCell.xib | 40 +++++++++++++++++++ .../GhostViews/StatsGhostTableViewRows.swift | 8 ++++ WordPress/WordPress.xcodeproj/project.pbxproj | 12 ++++++ 4 files changed, 62 insertions(+) create mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift index 98f30e98d3ff..e90cf1e06092 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift @@ -114,3 +114,5 @@ fileprivate extension Date { return days } } + +class StatsGhostSingleValueCell: StatsGhostBaseCell, NibLoadable { } diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib new file mode 100644 index 000000000000..2285ac8c545b --- /dev/null +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift index 3a39501557f0..6d27cf368ab7 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift @@ -134,3 +134,11 @@ struct StatsGhostTitleRow: StatsRowGhostable { enum GhostCellStyle { static let muriel = GhostStyle(beatStartColor: .placeholderElement, beatEndColor: .placeholderElementFaded) } + +struct StatsGhostSingleValueRow: StatsRowGhostable { + let statSection: StatSection? + + static let cell: ImmuTableCell = { + return ImmuTableCell.nib(StatsGhostSingleValueCell.defaultNib, StatsGhostSingleValueCell.self) + }() +} diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 16ec4c868263..78bfcea06f8e 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -137,6 +137,8 @@ 011896A629D5B72500D34BA9 /* DomainsDashboardCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011896A429D5B72500D34BA9 /* DomainsDashboardCoordinator.swift */; }; 011896A829D5BBB400D34BA9 /* DomainsDashboardFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011896A729D5BBB400D34BA9 /* DomainsDashboardFactory.swift */; }; 011896A929D5BBB400D34BA9 /* DomainsDashboardFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011896A729D5BBB400D34BA9 /* DomainsDashboardFactory.swift */; }; + 011F156F2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */; }; + 011F15702BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */; }; 011F52BD2A15327700B04114 /* BaseDashboardDomainsCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011F52BC2A15327700B04114 /* BaseDashboardDomainsCardCell.swift */; }; 011F52BE2A15327700B04114 /* BaseDashboardDomainsCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011F52BC2A15327700B04114 /* BaseDashboardDomainsCardCell.swift */; }; 011F52C02A1538EC00B04114 /* FreeToPaidPlansDashboardCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011F52BF2A1538EC00B04114 /* FreeToPaidPlansDashboardCardCell.swift */; }; @@ -222,6 +224,8 @@ 01B7590B2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */; }; 01B7590C2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */; }; 01B7590E2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590D2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift */; }; + 01C591452BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */; }; + 01C591462BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */; }; 01CE5007290A889F00A9C2E0 /* TracksConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */; }; 01CE5008290A88BD00A9C2E0 /* TracksConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */; }; 01CE500E290A88C100A9C2E0 /* TracksConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */; }; @@ -5993,6 +5997,7 @@ 011896A429D5B72500D34BA9 /* DomainsDashboardCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsDashboardCoordinator.swift; sourceTree = ""; }; 011896A729D5BBB400D34BA9 /* DomainsDashboardFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsDashboardFactory.swift; sourceTree = ""; }; 011A2815DB0DE7E3973CBC0E /* Pods-Apps-Jetpack.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Apps-Jetpack.release.xcconfig"; path = "../Pods/Target Support Files/Pods-Apps-Jetpack/Pods-Apps-Jetpack.release.xcconfig"; sourceTree = ""; }; + 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostSingleValueCell.xib; sourceTree = ""; }; 011F52BC2A15327700B04114 /* BaseDashboardDomainsCardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDashboardDomainsCardCell.swift; sourceTree = ""; }; 011F52BF2A1538EC00B04114 /* FreeToPaidPlansDashboardCardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FreeToPaidPlansDashboardCardCell.swift; sourceTree = ""; }; 011F52C22A153A3400B04114 /* FreeToPaidPlansDashboardCardHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FreeToPaidPlansDashboardCardHelper.swift; sourceTree = ""; }; @@ -6051,6 +6056,7 @@ 01B759072B3ECAF300179AE6 /* DomainsStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsStateView.swift; sourceTree = ""; }; 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainDetailsWebViewControllerWrapper.swift; sourceTree = ""; }; 01B7590D2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDomainsViewModelTests.swift; sourceTree = ""; }; + 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostTopCell.swift; sourceTree = ""; }; 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksConfiguration.swift; sourceTree = ""; }; 01CE5010290A890300A9C2E0 /* TracksConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksConfiguration.swift; sourceTree = ""; }; 01D2FF5D2AA733690038E040 /* LockScreenFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenFieldView.swift; sourceTree = ""; }; @@ -14976,11 +14982,13 @@ children = ( 9A09F91D230C4C0200F42AB7 /* StatsGhostTableViewRows.swift */, 9A9E3FAB230E9DD000909BC4 /* StatsGhostCells.swift */, + 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */, 9A9E3FB3230EC4F700909BC4 /* StatsGhostPostingActivityCell.xib */, 9A9E3FB1230EB74300909BC4 /* StatsGhostTabbedCell.xib */, 9A9E3FAF230EA7A300909BC4 /* StatsGhostTopCell.xib */, 9A19D440236C7C7500D393E5 /* StatsGhostTopHeaderCell.xib */, 9A9E3FAC230E9DD000909BC4 /* StatsGhostTwoColumnCell.xib */, + 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */, 9AC3C69A231543C2007933CD /* StatsGhostChartCell.xib */, 9A73CB072350DE4C002EF20C /* StatsGhostSingleRowCell.xib */, 9AB36B83236B25D900FAD72A /* StatsGhostTitleCell.xib */, @@ -19641,6 +19649,7 @@ FA1A55FF25A6F07F0033967D /* RestoreStatusView.xib in Resources */, 4058F41A1FF40EE1000D5559 /* PluginDetailViewHeaderCell.xib in Resources */, 1761F17226209AEE000815EF /* open-source-dark-icon-app-60x60@3x.png in Resources */, + 011F156F2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */, 406A0EF0224D39C50016AD6A /* Flags.xcassets in Resources */, 9A9E3FB0230EA7A300909BC4 /* StatsGhostTopCell.xib in Resources */, 985793C922F23D7000643DBF /* CustomizeInsightsCell.xib in Resources */, @@ -20188,6 +20197,7 @@ FABB1FCE2602FC2C00C8785C /* StatsChildRowsView.xib in Resources */, F41E4EEE28F247D3001880C6 /* white-on-green-icon-app-76.png in Resources */, FABB1FD02602FC2C00C8785C /* xhtml1-transitional.dtd in Resources */, + 011F15702BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */, 8BF281FA27CE8E4100AF8CF3 /* DashboardGhostCardContent.xib in Resources */, F465979A28E65FC800D5F49A /* dark-green-icon-app-60@3x.png in Resources */, FABB1FD22602FC2C00C8785C /* RestoreStatusView.xib in Resources */, @@ -23367,6 +23377,7 @@ E6FACB1E1EC675E300284AC7 /* GravatarProfile.swift in Sources */, D8212CB720AA7703008E8AE8 /* ReaderShareAction.swift in Sources */, C7BB60192863AF9700748FD9 /* QRLoginProtocols.swift in Sources */, + 01C591452BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */, 9826AE8A21B5CC7300C851FA /* PostingActivityMonth.swift in Sources */, 08F531FE2B7E94F20061BD0E /* CachedAsyncImage.swift in Sources */, 3F09CCAE24292EFD00D00A8C /* ReaderTabItem.swift in Sources */, @@ -24626,6 +24637,7 @@ FABB21762602FC2C00C8785C /* CameraHandler.swift in Sources */, F4C1FC642A44831300AD7CB0 /* PrivacySettingsAnalyticsTracker.swift in Sources */, FA73D7EA27987BA500DF24B3 /* SitePickerViewController+SiteIcon.swift in Sources */, + 01C591462BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */, FABB21772602FC2C00C8785C /* JetpackConnectionViewController.swift in Sources */, 803BB97A2959543D00B3F6D6 /* RootViewCoordinator.swift in Sources */, FABB21782602FC2C00C8785C /* NotificationActionsService.swift in Sources */, From 00ad2946a1ed033dff2609451f7b197c24814c56 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 13:37:50 +0300 Subject: [PATCH 03/12] Update StatsGhostTopCell.swift --- .../Stats/Shared Views/GhostViews/StatsGhostTopCell.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift index 9dbb30374275..ef4d7838245d 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift @@ -141,6 +141,12 @@ private class StatsGhostTopCellColumn: UIView { topView.startGhostAnimation(style: GhostCellStyle.muriel) bottomView.startGhostAnimation(style: GhostCellStyle.muriel) } + + override func tintColorDidChange() { + super.tintColorDidChange() + topView.restartGhostAnimation(style: GhostCellStyle.muriel) + bottomView.restartGhostAnimation(style: GhostCellStyle.muriel) + } } fileprivate extension StatsGhostTopCell { From 1cc289468a9a9cd4a16740d1054c64606dc263ba Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 13:38:58 +0300 Subject: [PATCH 04/12] Update SubscribersVM to use new Ghost cells --- .../Stats/Subscribers/StatsSubscribersViewModel.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift index 0fabf6e09ca3..e328b6aa0189 100644 --- a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift +++ b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift @@ -50,8 +50,8 @@ private extension StatsSubscribersViewModel { tableViewSnapshot.send(snapshot) } - func loadingRows(_ section: StatSection) -> [any StatsHashableImmuTableRow] { - return [StatsGhostTopImmutableRow(statSection: section)] + func loadingRows(_ section: StatSection, numberOfColumns: Int) -> [any StatsHashableImmuTableRow] { + return [StatsGhostTopImmutableRow(numberOfColumns: numberOfColumns, statSection: section)] } func errorRows(_ section: StatSection) -> [any StatsHashableImmuTableRow] { @@ -65,7 +65,7 @@ private extension StatsSubscribersViewModel { func subscribersTotalsRows() -> [any StatsHashableImmuTableRow] { switch store.subscribersList.value { case .loading, .idle: - return loadingRows(.subscribersTotal) + return [StatsGhostSingleValueRow(statSection: .subscribersTotal)] case .success(let subscribersData): return [ TotalInsightStatsRow( @@ -110,7 +110,7 @@ private extension StatsSubscribersViewModel { func emailsSummaryRows() -> [any StatsHashableImmuTableRow] { switch store.emailsSummary.value { case .loading, .idle: - return loadingRows(.subscribersEmailsSummary) + return loadingRows(.subscribersEmailsSummary, numberOfColumns: 3) case .success(let emailsSummary): return [ TopTotalsPeriodStatsRow( @@ -146,7 +146,7 @@ private extension StatsSubscribersViewModel { func subscribersListRows() -> [any StatsHashableImmuTableRow] { switch store.subscribersList.value { case .loading, .idle: - return loadingRows(.subscribersList) + return loadingRows(.subscribersList, numberOfColumns: 2) case .success(let subscribersData): return [ TopTotalsPeriodStatsRow( From a18a5dbb4c739a2162ad1982349e6a28eff45f60 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 13:39:11 +0300 Subject: [PATCH 05/12] Register new Ghost cells in Subscribers View Controller --- .../Stats/Subscribers/StatsSubscribersViewController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift index 2df49148e7dd..e3d4a9cba9e3 100644 --- a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift +++ b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift @@ -71,8 +71,10 @@ final class StatsSubscribersViewController: SiteStatsBaseTableViewController { return [ SubscriberChartRow.self, TopTotalsPeriodStatsRow.self, - StatsGhostTopImmutableRow.self, TotalInsightStatsRow.self, + StatsGhostTopImmutableRow.self, + StatsGhostChartImmutableRow.self, + StatsGhostSingleValueRow.self, StatsErrorRow.self ] } From fcee2fb31f08054bd11cb865fbdc69729841544c Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 14:30:52 +0300 Subject: [PATCH 06/12] Create StatsGhostLineChart to display loading of a line chart --- .../GhostViews/StatsGhostLineChartCell.swift | 67 +++++++++++++++++++ .../GhostViews/StatsGhostLineChartCell.xib | 41 ++++++++++++ .../GhostViews/StatsGhostTableViewRows.swift | 8 +++ 3 files changed, 116 insertions(+) create mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift create mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift new file mode 100644 index 000000000000..7dd502228cc5 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift @@ -0,0 +1,67 @@ +import UIKit +import WordPressShared + +class StatsGhostLineChartCell: StatsGhostBaseCell, NibLoadable { + @IBOutlet private weak var lineChart: StatsGhostLineChartView! +} + +final class StatsGhostLineChartView: UIView { + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + private func commonInit() { + backgroundColor = .clear + createMask() + } + + private func createMask() { + let maskLayer = CAShapeLayer() + maskLayer.frame = bounds + + let path = UIBezierPath() + path.move(to: CGPoint(x: 0, y: bounds.maxY)) + + let wavePoints = [ + CGPoint(x: bounds.width * 0.1, y: bounds.maxY * 0.8), + CGPoint(x: bounds.width * 0.3, y: bounds.maxY * 0.6), + CGPoint(x: bounds.width * 0.5, y: bounds.maxY * 0.4), + CGPoint(x: bounds.width * 0.7, y: bounds.maxY * 0.2), + CGPoint(x: bounds.width * 0.9, y: bounds.maxY * 0.5), + CGPoint(x: bounds.width, y: 0) + ] + + for (index, point) in wavePoints.enumerated() { + if index == 0 { + path.addLine(to: point) + } else { + let previousPoint = wavePoints[index - 1] + let midPointX = (previousPoint.x + point.x) / 2 + path.addCurve(to: point, controlPoint1: CGPoint(x: midPointX, y: previousPoint.y), controlPoint2: CGPoint(x: midPointX, y: point.y)) + } + } + + path.addLine(to: CGPoint(x: bounds.width, y: 0)) + path.addLine(to: CGPoint(x: bounds.width, y: bounds.maxY)) + path.addLine(to: CGPoint(x: 0, y: bounds.maxY)) + path.close() + + maskLayer.path = path.cgPath + maskLayer.fillColor = UIColor.white.cgColor + maskLayer.fillRule = .evenOdd + layer.mask = maskLayer + backgroundColor = .clear + } + + override func layoutSubviews() { + super.layoutSubviews() + layer.sublayers?.forEach { $0.frame = bounds } + createMask() + } +} diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib new file mode 100644 index 000000000000..cfbd207a1d6a --- /dev/null +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift index 6d27cf368ab7..fbf039f29e85 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift @@ -142,3 +142,11 @@ struct StatsGhostSingleValueRow: StatsRowGhostable { return ImmuTableCell.nib(StatsGhostSingleValueCell.defaultNib, StatsGhostSingleValueCell.self) }() } + +struct StatsGhostLineChartRow: StatsRowGhostable { + let statSection: StatSection? + + static let cell: ImmuTableCell = { + return ImmuTableCell.nib(StatsGhostLineChartCell.defaultNib, StatsGhostLineChartCell.self) + }() +} From 06ae50ac7a894964c1466f9e162d26b3b2e08703 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 14:31:12 +0300 Subject: [PATCH 07/12] Use StatsGhostLineChart for loading Subscribers line chart --- .../Subscribers/StatsSubscribersViewController.swift | 2 +- .../Subscribers/StatsSubscribersViewModel.swift | 2 +- WordPress/WordPress.xcodeproj/project.pbxproj | 12 ++++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift index e3d4a9cba9e3..48b189837d8f 100644 --- a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift +++ b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewController.swift @@ -73,7 +73,7 @@ final class StatsSubscribersViewController: SiteStatsBaseTableViewController { TopTotalsPeriodStatsRow.self, TotalInsightStatsRow.self, StatsGhostTopImmutableRow.self, - StatsGhostChartImmutableRow.self, + StatsGhostLineChartRow.self, StatsGhostSingleValueRow.self, StatsErrorRow.self ] diff --git a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift index e328b6aa0189..5e6405e72558 100644 --- a/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift +++ b/WordPress/Classes/ViewRelated/Stats/Subscribers/StatsSubscribersViewModel.swift @@ -85,7 +85,7 @@ private extension StatsSubscribersViewModel { func chartRows() -> [any StatsHashableImmuTableRow] { switch store.chartSummary.value { case .loading, .idle: - return loadingRows(.subscribersChart) + return [StatsGhostLineChartRow(statSection: .subscribersChart)] case .success(let chartSummary): let xAxisDates = chartSummary.history.map { $0.date } let viewsChart = StatsSubscribersLineChart(counts: chartSummary.history.map { $0.count }) diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 78bfcea06f8e..76af2d5a4cb2 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -224,6 +224,10 @@ 01B7590B2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */; }; 01B7590C2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */; }; 01B7590E2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590D2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift */; }; + 01C447292BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */; }; + 01C4472A2BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */; }; + 01C4472C2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */; }; + 01C4472D2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */; }; 01C591452BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */; }; 01C591462BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */; }; 01CE5007290A889F00A9C2E0 /* TracksConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */; }; @@ -6056,6 +6060,8 @@ 01B759072B3ECAF300179AE6 /* DomainsStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsStateView.swift; sourceTree = ""; }; 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainDetailsWebViewControllerWrapper.swift; sourceTree = ""; }; 01B7590D2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDomainsViewModelTests.swift; sourceTree = ""; }; + 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostLineChartCell.xib; sourceTree = ""; }; + 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostLineChartCell.swift; sourceTree = ""; }; 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostTopCell.swift; sourceTree = ""; }; 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksConfiguration.swift; sourceTree = ""; }; 01CE5010290A890300A9C2E0 /* TracksConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksConfiguration.swift; sourceTree = ""; }; @@ -14993,6 +14999,8 @@ 9A73CB072350DE4C002EF20C /* StatsGhostSingleRowCell.xib */, 9AB36B83236B25D900FAD72A /* StatsGhostTitleCell.xib */, FA347AF126EB7A420096604B /* StatsGhostGrowAudienceCell.xib */, + 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */, + 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */, ); path = GhostViews; sourceTree = ""; @@ -19628,6 +19636,7 @@ 17222D9B261DDDF90047B163 /* black-icon-app-76x76.png in Resources */, DC772B0828201F5300664C02 /* ViewsVisitorsLineChartCell.xib in Resources */, 5D6C4AF61B603CA3005E3C43 /* WPTableViewActivityCell.xib in Resources */, + 01C447292BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */, A01C55480E25E0D000D411F2 /* defaultPostTemplate.html in Resources */, 17222D89261DDDF90047B163 /* celadon-icon-app-60x60@3x.png in Resources */, 08BA4BC9298A9AD500015BD2 /* JetpackInstallPluginLogoAnimation_ltr.json in Resources */, @@ -20301,6 +20310,7 @@ FABB20302602FC2C00C8785C /* OverviewCell.xib in Resources */, 83A8A2972BDC557F001F9133 /* ReaderTagFooterView.xib in Resources */, F46597E928E6698D00D5F49A /* spectrum-on-black-icon-app-83.5@2x.png in Resources */, + 01C4472A2BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */, FABB20322602FC2C00C8785C /* JetpackRemoteInstallStateView.xib in Resources */, FABB20352602FC2C00C8785C /* TemplatePreviewViewController.xib in Resources */, F46597BB28E6687800D5F49A /* neumorphic-dark-icon-app-76@2x.png in Resources */, @@ -22122,6 +22132,7 @@ E166FA1B1BB0656B00374B5B /* PeopleCellViewModel.swift in Sources */, 436D56292117312700CEAA33 /* RegisterDomainDetailsViewController.swift in Sources */, F4EDAA4C29A516EA00622D3D /* ReaderPostService.swift in Sources */, + 01C4472C2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */, F5E29036243E4F5F00C19CA5 /* FilterProvider.swift in Sources */, F4FE743429C3767300AC2729 /* AddressTableViewCell+ViewModel.swift in Sources */, 027AC51D227896540033E56E /* DomainCreditEligibilityChecker.swift in Sources */, @@ -25279,6 +25290,7 @@ 8B55FAAD2614FC87007D618E /* Text+BoldSubString.swift in Sources */, 01616C8C2B5AA6E50023C123 /* StatsTrafficBarChartTabs.swift in Sources */, FABB23382602FC2C00C8785C /* WordPress-22-23.xcmappingmodel in Sources */, + 01C4472D2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */, FED65D79293511E4008071BF /* SharedDataIssueSolver.swift in Sources */, FABB23392602FC2C00C8785C /* CountriesMap.swift in Sources */, F45EB50C2B883E6E004E9053 /* CommentNotification.swift in Sources */, From edd95a6c6ead4cbcafdd3cffb07211552d70e682 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Fri, 3 May 2024 15:46:17 +0300 Subject: [PATCH 08/12] Update StatsSubscribersViewModelTests.swift --- WordPress/WordPressTest/StatsSubscribersViewModelTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/WordPressTest/StatsSubscribersViewModelTests.swift b/WordPress/WordPressTest/StatsSubscribersViewModelTests.swift index b803c52f8380..521b91bafa35 100644 --- a/WordPress/WordPressTest/StatsSubscribersViewModelTests.swift +++ b/WordPress/WordPressTest/StatsSubscribersViewModelTests.swift @@ -18,7 +18,7 @@ final class StatsSubscribersViewModelTests: XCTestCase { let expectation = expectation(description: "First section should be loading") sut.tableViewSnapshot .sink(receiveValue: { snapshot in - if let _ = snapshot.itemIdentifiers.first?.immuTableRow as? StatsGhostTopImmutableRow { + if let _ = snapshot.itemIdentifiers.first?.immuTableRow as? (any StatsRowGhostable) { expectation.fulfill() } }) From be40a7018954ef93ef67f96b881c694790eddf1e Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 6 May 2024 10:50:28 +0300 Subject: [PATCH 09/12] Implement StatsGhostLineChartCell in the code --- .../GhostViews/StatsGhostCells.swift | 2 - .../GhostViews/StatsGhostLineChartCell.swift | 24 ++++++++++- .../GhostViews/StatsGhostLineChartCell.xib | 41 ------------------- .../GhostViews/StatsGhostTableViewRows.swift | 2 +- WordPress/WordPress.xcodeproj/project.pbxproj | 18 +++----- 5 files changed, 29 insertions(+), 58 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift index e90cf1e06092..98f30e98d3ff 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift @@ -114,5 +114,3 @@ fileprivate extension Date { return days } } - -class StatsGhostSingleValueCell: StatsGhostBaseCell, NibLoadable { } diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift index 7dd502228cc5..043bf18f430d 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift @@ -1,8 +1,28 @@ import UIKit import WordPressShared +import DesignSystem -class StatsGhostLineChartCell: StatsGhostBaseCell, NibLoadable { - @IBOutlet private weak var lineChart: StatsGhostLineChartView! +final class StatsGhostLineChartCell: StatsGhostBaseCell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + let lineChart = StatsGhostLineChartView() + headingLabel.isGhostableDisabled = true + lineChart.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(lineChart) + topConstraint = lineChart.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0) + topConstraint?.isActive = true + NSLayoutConstraint.activate([ + lineChart.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: .DS.Padding.double), + contentView.trailingAnchor.constraint(equalTo: lineChart.trailingAnchor, constant: .DS.Padding.double), + contentView.bottomAnchor.constraint(equalTo: lineChart.bottomAnchor, constant: .DS.Padding.single), + lineChart.heightAnchor.constraint(equalToConstant: 190), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } final class StatsGhostLineChartView: UIView { diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib deleted file mode 100644 index cfbd207a1d6a..000000000000 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.xib +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift index fbf039f29e85..ce04ad21807f 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift @@ -147,6 +147,6 @@ struct StatsGhostLineChartRow: StatsRowGhostable { let statSection: StatSection? static let cell: ImmuTableCell = { - return ImmuTableCell.nib(StatsGhostLineChartCell.defaultNib, StatsGhostLineChartCell.self) + return ImmuTableCell.class(StatsGhostLineChartCell.self) }() } diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 5fd43a2fc0b0..2e230462ae7e 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -137,8 +137,6 @@ 011896A629D5B72500D34BA9 /* DomainsDashboardCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011896A429D5B72500D34BA9 /* DomainsDashboardCoordinator.swift */; }; 011896A829D5BBB400D34BA9 /* DomainsDashboardFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011896A729D5BBB400D34BA9 /* DomainsDashboardFactory.swift */; }; 011896A929D5BBB400D34BA9 /* DomainsDashboardFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011896A729D5BBB400D34BA9 /* DomainsDashboardFactory.swift */; }; - 011F156F2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */; }; - 011F15702BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */; }; 011F52BD2A15327700B04114 /* BaseDashboardDomainsCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011F52BC2A15327700B04114 /* BaseDashboardDomainsCardCell.swift */; }; 011F52BE2A15327700B04114 /* BaseDashboardDomainsCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011F52BC2A15327700B04114 /* BaseDashboardDomainsCardCell.swift */; }; 011F52C02A1538EC00B04114 /* FreeToPaidPlansDashboardCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011F52BF2A1538EC00B04114 /* FreeToPaidPlansDashboardCardCell.swift */; }; @@ -204,6 +202,8 @@ 0189AF062ACAD89700F63393 /* ShoppingCartService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0189AF042ACAD89700F63393 /* ShoppingCartService.swift */; }; 018FF1352AE6771A00F301C3 /* LockScreenVerticalCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 018FF1342AE6771A00F301C3 /* LockScreenVerticalCard.swift */; }; 018FF1372AE67C2600F301C3 /* LockScreenFlexibleCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 018FF1362AE67C2600F301C3 /* LockScreenFlexibleCard.swift */; }; + 019105862BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019105852BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift */; }; + 019105872BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019105852BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift */; }; 019C5B8D2BD6570D00A69DB0 /* StatsSubscribersStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019C5B8C2BD6570D00A69DB0 /* StatsSubscribersStore.swift */; }; 019C5B8E2BD6570D00A69DB0 /* StatsSubscribersStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019C5B8C2BD6570D00A69DB0 /* StatsSubscribersStore.swift */; }; 019C5B942BD6917600A69DB0 /* StatsSubscribersCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019C5B932BD6917600A69DB0 /* StatsSubscribersCache.swift */; }; @@ -224,8 +224,6 @@ 01B7590B2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */; }; 01B7590C2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */; }; 01B7590E2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B7590D2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift */; }; - 01C447292BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */; }; - 01C4472A2BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */; }; 01C4472C2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */; }; 01C4472D2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */; }; 01C591452BDBD63D0071515C /* StatsGhostTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */; }; @@ -6005,7 +6003,6 @@ 011896A429D5B72500D34BA9 /* DomainsDashboardCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsDashboardCoordinator.swift; sourceTree = ""; }; 011896A729D5BBB400D34BA9 /* DomainsDashboardFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsDashboardFactory.swift; sourceTree = ""; }; 011A2815DB0DE7E3973CBC0E /* Pods-Apps-Jetpack.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Apps-Jetpack.release.xcconfig"; path = "../Pods/Target Support Files/Pods-Apps-Jetpack/Pods-Apps-Jetpack.release.xcconfig"; sourceTree = ""; }; - 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostSingleValueCell.xib; sourceTree = ""; }; 011F52BC2A15327700B04114 /* BaseDashboardDomainsCardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDashboardDomainsCardCell.swift; sourceTree = ""; }; 011F52BF2A1538EC00B04114 /* FreeToPaidPlansDashboardCardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FreeToPaidPlansDashboardCardCell.swift; sourceTree = ""; }; 011F52C22A153A3400B04114 /* FreeToPaidPlansDashboardCardHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FreeToPaidPlansDashboardCardHelper.swift; sourceTree = ""; }; @@ -6053,6 +6050,7 @@ 0189AF042ACAD89700F63393 /* ShoppingCartService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingCartService.swift; sourceTree = ""; }; 018FF1342AE6771A00F301C3 /* LockScreenVerticalCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenVerticalCard.swift; sourceTree = ""; }; 018FF1362AE67C2600F301C3 /* LockScreenFlexibleCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenFlexibleCard.swift; sourceTree = ""; }; + 019105852BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostSingleValueCell.swift; sourceTree = ""; }; 019C5B8C2BD6570D00A69DB0 /* StatsSubscribersStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsSubscribersStore.swift; sourceTree = ""; }; 019C5B932BD6917600A69DB0 /* StatsSubscribersCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsSubscribersCache.swift; sourceTree = ""; }; 019C5B962BD6A49900A69DB0 /* StatsSubscribersViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsSubscribersViewModelTests.swift; sourceTree = ""; }; @@ -6064,7 +6062,6 @@ 01B759072B3ECAF300179AE6 /* DomainsStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsStateView.swift; sourceTree = ""; }; 01B7590A2B3ED63B00179AE6 /* DomainDetailsWebViewControllerWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainDetailsWebViewControllerWrapper.swift; sourceTree = ""; }; 01B7590D2B3EEEA400179AE6 /* SiteDomainsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDomainsViewModelTests.swift; sourceTree = ""; }; - 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostLineChartCell.xib; sourceTree = ""; }; 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostLineChartCell.swift; sourceTree = ""; }; 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostTopCell.swift; sourceTree = ""; }; 01CE5006290A889F00A9C2E0 /* TracksConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksConfiguration.swift; sourceTree = ""; }; @@ -15003,13 +15000,12 @@ 9A9E3FAF230EA7A300909BC4 /* StatsGhostTopCell.xib */, 9A19D440236C7C7500D393E5 /* StatsGhostTopHeaderCell.xib */, 9A9E3FAC230E9DD000909BC4 /* StatsGhostTwoColumnCell.xib */, - 011F156E2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib */, 9AC3C69A231543C2007933CD /* StatsGhostChartCell.xib */, 9A73CB072350DE4C002EF20C /* StatsGhostSingleRowCell.xib */, 9AB36B83236B25D900FAD72A /* StatsGhostTitleCell.xib */, FA347AF126EB7A420096604B /* StatsGhostGrowAudienceCell.xib */, - 01C447282BE4F8490006F787 /* StatsGhostLineChartCell.xib */, 01C4472B2BE4F8560006F787 /* StatsGhostLineChartCell.swift */, + 019105852BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift */, ); path = GhostViews; sourceTree = ""; @@ -19644,7 +19640,6 @@ 17222D9B261DDDF90047B163 /* black-icon-app-76x76.png in Resources */, DC772B0828201F5300664C02 /* ViewsVisitorsLineChartCell.xib in Resources */, 5D6C4AF61B603CA3005E3C43 /* WPTableViewActivityCell.xib in Resources */, - 01C447292BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */, A01C55480E25E0D000D411F2 /* defaultPostTemplate.html in Resources */, 17222D89261DDDF90047B163 /* celadon-icon-app-60x60@3x.png in Resources */, 08BA4BC9298A9AD500015BD2 /* JetpackInstallPluginLogoAnimation_ltr.json in Resources */, @@ -19666,7 +19661,6 @@ FA1A55FF25A6F07F0033967D /* RestoreStatusView.xib in Resources */, 4058F41A1FF40EE1000D5559 /* PluginDetailViewHeaderCell.xib in Resources */, 1761F17226209AEE000815EF /* open-source-dark-icon-app-60x60@3x.png in Resources */, - 011F156F2BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */, 406A0EF0224D39C50016AD6A /* Flags.xcassets in Resources */, 9A9E3FB0230EA7A300909BC4 /* StatsGhostTopCell.xib in Resources */, 985793C922F23D7000643DBF /* CustomizeInsightsCell.xib in Resources */, @@ -20213,7 +20207,6 @@ FABB1FCE2602FC2C00C8785C /* StatsChildRowsView.xib in Resources */, F41E4EEE28F247D3001880C6 /* white-on-green-icon-app-76.png in Resources */, FABB1FD02602FC2C00C8785C /* xhtml1-transitional.dtd in Resources */, - 011F15702BE4E8CE008029ED /* StatsGhostSingleValueCell.xib in Resources */, 8BF281FA27CE8E4100AF8CF3 /* DashboardGhostCardContent.xib in Resources */, F465979A28E65FC800D5F49A /* dark-green-icon-app-60@3x.png in Resources */, FABB1FD22602FC2C00C8785C /* RestoreStatusView.xib in Resources */, @@ -20316,7 +20309,6 @@ FABB20302602FC2C00C8785C /* OverviewCell.xib in Resources */, 83A8A2972BDC557F001F9133 /* ReaderTagFooterView.xib in Resources */, F46597E928E6698D00D5F49A /* spectrum-on-black-icon-app-83.5@2x.png in Resources */, - 01C4472A2BE4F8490006F787 /* StatsGhostLineChartCell.xib in Resources */, FABB20322602FC2C00C8785C /* JetpackRemoteInstallStateView.xib in Resources */, FABB20352602FC2C00C8785C /* TemplatePreviewViewController.xib in Resources */, F46597BB28E6687800D5F49A /* neumorphic-dark-icon-app-76@2x.png in Resources */, @@ -22141,6 +22133,7 @@ 436D56292117312700CEAA33 /* RegisterDomainDetailsViewController.swift in Sources */, F4EDAA4C29A516EA00622D3D /* ReaderPostService.swift in Sources */, 01C4472C2BE4F8560006F787 /* StatsGhostLineChartCell.swift in Sources */, + 019105862BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift in Sources */, F5E29036243E4F5F00C19CA5 /* FilterProvider.swift in Sources */, F4FE743429C3767300AC2729 /* AddressTableViewCell+ViewModel.swift in Sources */, 027AC51D227896540033E56E /* DomainCreditEligibilityChecker.swift in Sources */, @@ -25422,6 +25415,7 @@ F41E32FF287B47A500F89082 /* SuggestionsListViewModel.swift in Sources */, F4EDAA5129A795C600622D3D /* BlockedAuthor.swift in Sources */, FABB238E2602FC2C00C8785C /* NotificationSettingsService.swift in Sources */, + 019105872BE8BD6000CDFB16 /* StatsGhostSingleValueCell.swift in Sources */, 8091019429078CFE00FCB4EA /* JetpackFullscreenOverlayViewController.swift in Sources */, FA347AEE26EB6E300096604B /* GrowAudienceCell.swift in Sources */, FABB23922602FC2C00C8785C /* UIImage+Assets.swift in Sources */, From 39e4394ffbb8819c90c5fe6b7346b797f9801b74 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 6 May 2024 10:52:52 +0300 Subject: [PATCH 10/12] Implement StatsGhostSingleValueCell in the code --- .../StatsGhostSingleValueCell.swift | 26 ++++++++++++ .../GhostViews/StatsGhostSingleValueCell.xib | 40 ------------------- .../GhostViews/StatsGhostTableViewRows.swift | 2 +- 3 files changed, 27 insertions(+), 41 deletions(-) create mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift delete mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift new file mode 100644 index 000000000000..61fb4ebc45e3 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift @@ -0,0 +1,26 @@ +import UIKit +import WordPressShared +import DesignSystem + +final class StatsGhostSingleValueCell: StatsGhostBaseCell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + headingLabel.isGhostableDisabled = true + let ghostView = UIView() + ghostView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(ghostView) + topConstraint = ghostView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: .DS.Padding.single) + topConstraint?.isActive = true + NSLayoutConstraint.activate([ + ghostView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: .DS.Padding.double), + ghostView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -.DS.Padding.double), + ghostView.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.35), + ghostView.heightAnchor.constraint(equalToConstant: 36) + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib deleted file mode 100644 index 2285ac8c545b..000000000000 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.xib +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift index ce04ad21807f..82d297c9ea57 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift @@ -139,7 +139,7 @@ struct StatsGhostSingleValueRow: StatsRowGhostable { let statSection: StatSection? static let cell: ImmuTableCell = { - return ImmuTableCell.nib(StatsGhostSingleValueCell.defaultNib, StatsGhostSingleValueCell.self) + return ImmuTableCell.class(StatsGhostSingleValueCell.self) }() } From 0f443e40feac64b5b1ce42840512e61121bbd6b8 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 6 May 2024 11:28:27 +0300 Subject: [PATCH 11/12] Implement StatsGhostTopCell in the code --- .../GhostViews/StatsGhostTableViewRows.swift | 2 +- .../GhostViews/StatsGhostTopCell.swift | 58 ++++++++++++++++-- .../GhostViews/StatsGhostTopCell.xib | 59 ------------------- WordPress/WordPress.xcodeproj/project.pbxproj | 6 -- 4 files changed, 53 insertions(+), 72 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift index 82d297c9ea57..0050af891b61 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTableViewRows.swift @@ -42,7 +42,7 @@ struct StatsGhostTwoColumnImmutableRow: StatsRowGhostable { struct StatsGhostTopImmutableRow: StatsRowGhostable { static let cell: ImmuTableCell = { - return ImmuTableCell.nib(StatsGhostTopCell.defaultNib, StatsGhostTopCell.self) + return ImmuTableCell.class(StatsGhostTopCell.self) }() var hideTopBorder = false diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift index ef4d7838245d..bcbbbeb53f9d 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.swift @@ -3,8 +3,27 @@ import DesignSystem import WordPressUI final class StatsGhostTopCell: StatsGhostBaseCell, NibLoadable { - @IBOutlet private weak var topCellRow: StatsGhostTopCellRow! - @IBOutlet private weak var topCellHeaders: UIStackView! + private let titleHeader: UIView = { + let header = UIView() + header.translatesAutoresizingMaskIntoConstraints = false + return header + }() + + private let valueHeaders: UIStackView = { + let headers = UIStackView() + headers.translatesAutoresizingMaskIntoConstraints = false + headers.spacing = .DS.Padding.double + headers.distribution = .fill + headers.alignment = .fill + headers.axis = .horizontal + return headers + }() + + private let contentRows: StatsGhostTopCellRow = { + let contentRows = StatsGhostTopCellRow() + contentRows.translatesAutoresizingMaskIntoConstraints = false + return contentRows + }() var numberOfColumns: Int = 2 { didSet { @@ -12,17 +31,44 @@ final class StatsGhostTopCell: StatsGhostBaseCell, NibLoadable { } } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + contentView.addSubviews([titleHeader, valueHeaders, contentRows]) + + topConstraint = valueHeaders.topAnchor.constraint(equalTo: contentView.topAnchor, constant: .DS.Padding.single) + topConstraint?.isActive = true + NSLayoutConstraint.activate([ + titleHeader.topAnchor.constraint(equalTo: valueHeaders.topAnchor), + titleHeader.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: .DS.Padding.double), + titleHeader.widthAnchor.constraint(equalToConstant: 50), + titleHeader.heightAnchor.constraint(equalToConstant: .DS.Padding.double), + + valueHeaders.heightAnchor.constraint(equalToConstant: .DS.Padding.double), + valueHeaders.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -.DS.Padding.double), + + contentRows.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0), + contentRows.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0), + contentRows.topAnchor.constraint(equalTo: valueHeaders.bottomAnchor, constant: .DS.Padding.half), + contentRows.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -.DS.Padding.single) + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + private func configureCell(with count: Int) { updateHeaders(count: count) - topCellRow.updateColumns(count: count) + contentRows.updateColumns(count: count) } private func updateHeaders(count: Int) { - topCellHeaders.removeAllSubviews() + valueHeaders.removeAllSubviews() let headers = Array(repeating: UIView(), count: count-1) headers.forEach { header in configureHeader(header) - topCellHeaders.addArrangedSubview(header) + valueHeaders.addArrangedSubview(header) } } @@ -32,7 +78,7 @@ final class StatsGhostTopCell: StatsGhostBaseCell, NibLoadable { } } -class StatsGhostTopCellRow: UIView { +final class StatsGhostTopCellRow: UIView { private let avatarView = UIView() private let columnsStackView = createStackView() private let mainColumn = StatsGhostTopCellColumn() diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib deleted file mode 100644 index d005ec3a1558..000000000000 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostTopCell.xib +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 2e230462ae7e..1eed07272e63 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -2784,7 +2784,6 @@ 9A9E3FA3230D5F0A00909BC4 /* StatsStackViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9E3FA2230D5F0A00909BC4 /* StatsStackViewCell.swift */; }; 9A9E3FAD230E9DD000909BC4 /* StatsGhostCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9E3FAB230E9DD000909BC4 /* StatsGhostCells.swift */; }; 9A9E3FAE230E9DD000909BC4 /* StatsGhostTwoColumnCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A9E3FAC230E9DD000909BC4 /* StatsGhostTwoColumnCell.xib */; }; - 9A9E3FB0230EA7A300909BC4 /* StatsGhostTopCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A9E3FAF230EA7A300909BC4 /* StatsGhostTopCell.xib */; }; 9A9E3FB2230EB74300909BC4 /* StatsGhostTabbedCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A9E3FB1230EB74300909BC4 /* StatsGhostTabbedCell.xib */; }; 9A9E3FB4230EC4F700909BC4 /* StatsGhostPostingActivityCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A9E3FB3230EC4F700909BC4 /* StatsGhostPostingActivityCell.xib */; }; 9AA0ADB1235F11700027AB5D /* AsyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA0ADB0235F116F0027AB5D /* AsyncOperation.swift */; }; @@ -4186,7 +4185,6 @@ FABB1FD22602FC2C00C8785C /* RestoreStatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA1A55FE25A6F07F0033967D /* RestoreStatusView.xib */; }; FABB1FD32602FC2C00C8785C /* PluginDetailViewHeaderCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4058F4191FF40EE1000D5559 /* PluginDetailViewHeaderCell.xib */; }; FABB1FD42602FC2C00C8785C /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 406A0EEF224D39C50016AD6A /* Flags.xcassets */; }; - FABB1FD52602FC2C00C8785C /* StatsGhostTopCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A9E3FAF230EA7A300909BC4 /* StatsGhostTopCell.xib */; }; FABB1FD62602FC2C00C8785C /* CustomizeInsightsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 985793C722F23D7000643DBF /* CustomizeInsightsCell.xib */; }; FABB1FD92602FC2C00C8785C /* oswald_upper.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F5A34D0625DF2F7700C9654B /* oswald_upper.ttf */; }; FABB1FDB2602FC2C00C8785C /* xhtmlValidatorTemplate.xhtml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAE97080E33B21600CA8540 /* xhtmlValidatorTemplate.xhtml */; }; @@ -8179,7 +8177,6 @@ 9A9E3FA2230D5F0A00909BC4 /* StatsStackViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsStackViewCell.swift; sourceTree = ""; }; 9A9E3FAB230E9DD000909BC4 /* StatsGhostCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsGhostCells.swift; sourceTree = ""; }; 9A9E3FAC230E9DD000909BC4 /* StatsGhostTwoColumnCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostTwoColumnCell.xib; sourceTree = ""; }; - 9A9E3FAF230EA7A300909BC4 /* StatsGhostTopCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostTopCell.xib; sourceTree = ""; }; 9A9E3FB1230EB74300909BC4 /* StatsGhostTabbedCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostTabbedCell.xib; sourceTree = ""; }; 9A9E3FB3230EC4F700909BC4 /* StatsGhostPostingActivityCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsGhostPostingActivityCell.xib; sourceTree = ""; }; 9AA0ADB0235F116F0027AB5D /* AsyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncOperation.swift; sourceTree = ""; }; @@ -14997,7 +14994,6 @@ 01C591442BDBD63D0071515C /* StatsGhostTopCell.swift */, 9A9E3FB3230EC4F700909BC4 /* StatsGhostPostingActivityCell.xib */, 9A9E3FB1230EB74300909BC4 /* StatsGhostTabbedCell.xib */, - 9A9E3FAF230EA7A300909BC4 /* StatsGhostTopCell.xib */, 9A19D440236C7C7500D393E5 /* StatsGhostTopHeaderCell.xib */, 9A9E3FAC230E9DD000909BC4 /* StatsGhostTwoColumnCell.xib */, 9AC3C69A231543C2007933CD /* StatsGhostChartCell.xib */, @@ -19662,7 +19658,6 @@ 4058F41A1FF40EE1000D5559 /* PluginDetailViewHeaderCell.xib in Resources */, 1761F17226209AEE000815EF /* open-source-dark-icon-app-60x60@3x.png in Resources */, 406A0EF0224D39C50016AD6A /* Flags.xcassets in Resources */, - 9A9E3FB0230EA7A300909BC4 /* StatsGhostTopCell.xib in Resources */, 985793C922F23D7000643DBF /* CustomizeInsightsCell.xib in Resources */, 1761F17926209AEE000815EF /* wordpress-dark-icon-app-60x60@2x.png in Resources */, 83A8A2962BDC557F001F9133 /* ReaderTagFooterView.xib in Resources */, @@ -20213,7 +20208,6 @@ FABB1FD32602FC2C00C8785C /* PluginDetailViewHeaderCell.xib in Resources */, FABB1FD42602FC2C00C8785C /* Flags.xcassets in Resources */, FE3E427826A868E300C596CE /* ListTableViewCell.xib in Resources */, - FABB1FD52602FC2C00C8785C /* StatsGhostTopCell.xib in Resources */, C7124E4E2638528F00929318 /* JetpackPrologueViewController.xib in Resources */, F465978628E65E1800D5F49A /* blue-on-white-icon-app-83.5@2x.png in Resources */, FABB1FD62602FC2C00C8785C /* CustomizeInsightsCell.xib in Resources */, From 42e742c2a79bc1cedf55561ffee5232ca20633b1 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 6 May 2024 11:29:38 +0300 Subject: [PATCH 12/12] Update StatsGhostBaseCell to have common init for both nib and code paths --- .../Shared Views/GhostViews/StatsGhostCells.swift | 14 ++++++++++++++ .../GhostViews/StatsGhostLineChartCell.swift | 1 - .../GhostViews/StatsGhostSingleValueCell.swift | 1 - 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift index 98f30e98d3ff..61764277b2e4 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostCells.swift @@ -6,6 +6,20 @@ class StatsGhostBaseCell: StatsBaseCell { override func awakeFromNib() { super.awakeFromNib() + commonInit() + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + private func commonInit() { headingLabel.isGhostableDisabled = true Style.configureCell(self) } diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift index 043bf18f430d..5aaef8923418 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostLineChartCell.swift @@ -7,7 +7,6 @@ final class StatsGhostLineChartCell: StatsGhostBaseCell { super.init(style: style, reuseIdentifier: reuseIdentifier) let lineChart = StatsGhostLineChartView() - headingLabel.isGhostableDisabled = true lineChart.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(lineChart) topConstraint = lineChart.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0) diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift index 61fb4ebc45e3..c11bf06e95c4 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/GhostViews/StatsGhostSingleValueCell.swift @@ -6,7 +6,6 @@ final class StatsGhostSingleValueCell: StatsGhostBaseCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - headingLabel.isGhostableDisabled = true let ghostView = UIView() ghostView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(ghostView)