Skip to content

Commit

Permalink
Merge pull request #17142 from wordpress-mobile/task/empty-stats-stan…
Browse files Browse the repository at this point in the history
…dalone-card

Empty Stats: standalone card
  • Loading branch information
momo-ozawa authored Sep 21, 2021
2 parents 3c02738 + 6bd4538 commit 225fe01
Show file tree
Hide file tree
Showing 24 changed files with 540 additions and 10 deletions.
2 changes: 1 addition & 1 deletion WordPress/Classes/Stores/StatsStore+Cache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extension StatsInsightsStore: StatsStoreCacheable {
switch type {
case .latestPostSummary:
return state.lastPostInsight != nil
case .allTimeStats:
case .allTimeStats, .growAudience:
return state.allTimeStats != nil
case .followersTotals, .followers:
return state.dotComFollowers != nil &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UIKit
import WordPressFlux

enum InsightType: Int {
case growAudience
case customize
case latestPostSummary
case allTimeStats
Expand Down Expand Up @@ -79,6 +80,7 @@ enum InsightType: Int {
@objc optional func showPostStats(postID: Int, postTitle: String?, postURL: URL?)
@objc optional func customizeDismissButtonTapped()
@objc optional func customizeTryButtonTapped()
@objc optional func growAudienceDismissButtonTapped()
@objc optional func showAddInsight()
@objc optional func addInsightSelected(_ insight: StatSection)
@objc optional func addInsightDismissed()
Expand All @@ -99,6 +101,9 @@ class SiteStatsInsightsTableViewController: UITableViewController, StoryboardLoa
// Store 'customize' separately as it is not per site.
private let userDefaultsHideCustomizeKey = "StatsInsightsHideCustomizeCard"

// Store 'grow audience' separately as it is not per site.
private let userDefaultsHideGrowAudienceKey = "StatsInsightsHideGrowAudienceCard"

// Store Insights settings for all sites.
// Used when writing to/reading from User Defaults.
// A single site's dictionary contains the InsightType values for that site.
Expand Down Expand Up @@ -183,6 +188,7 @@ private extension SiteStatsInsightsTableViewController {

func tableRowTypes() -> [ImmuTableRow.Type] {
return [InsightCellHeaderRow.self,
GrowAudienceRow.self,
CustomizeInsightsRow.self,
LatestPostSummaryRow.self,
TwoColumnStatsRow.self,
Expand All @@ -191,6 +197,7 @@ private extension SiteStatsInsightsTableViewController {
TopTotalsInsightStatsRow.self,
TableFooterRow.self,
StatsErrorRow.self,
StatsGhostGrowAudienceImmutableRow.self,
StatsGhostChartImmutableRow.self,
StatsGhostTwoColumnImmutableRow.self,
StatsGhostTopImmutableRow.self,
Expand Down Expand Up @@ -247,7 +254,7 @@ private extension SiteStatsInsightsTableViewController {

guard let siteID = SiteStatsInformation.sharedInstance.siteID?.stringValue else {
insightsToShow = InsightType.defaultInsights
loadCustomizeCardSetting()
loadPinnedCards()
return
}

Expand All @@ -259,8 +266,7 @@ private extension SiteStatsInsightsTableViewController {
let insightTypesValues = siteInsights?.values.first ?? InsightType.defaultInsightsValues
insightsToShow = InsightType.typesForValues(insightTypesValues)

// Add the 'customize' card if necessary.
loadCustomizeCardSetting()
loadPinnedCards()
}

func writeInsightsToUserDefaults() {
Expand All @@ -279,7 +285,15 @@ private extension SiteStatsInsightsTableViewController {
UserDefaults.standard.set(allSitesInsights, forKey: userDefaultsInsightTypesKey)
}

/// Loads an insight that can be permanently dismissed. Adds or removes the insight from the list of insights to show.
func loadPinnedCards() {
loadGrowAudienceCardSetting()

if !insightsToShow.contains(.growAudience) {
loadCustomizeCardSetting()
}
}

/// Loads an insight that can be permanently dismissed. Adds or removes the insight from the list of insights to show as needed.
///
/// - Parameters:
/// - insight: An insight that can be permanently dismissed for all sites
Expand All @@ -289,9 +303,14 @@ private extension SiteStatsInsightsTableViewController {
let shouldAddInsight =
!UserDefaults.standard.bool(forKey: userDefaultsHideInsightKey) && !insightsToShow.contains(insight)

/// Note that this flag isn't an inversion of the shouldAddInsight flag.
let shouldRemoveInsight =
UserDefaults.standard.bool(forKey: userDefaultsHideInsightKey) && insightsToShow.contains(insight)

/// Add or remove the insight as needed. If it's already showing and hasn't been dismissed, do nothing.
if shouldAddInsight {
insightsToShow.insert(insight, at: 0)
} else {
} else if shouldRemoveInsight {
insightsToShow = insightsToShow.filter { $0 != insight }
}
}
Expand All @@ -316,6 +335,16 @@ private extension SiteStatsInsightsTableViewController {
permanentlyDismissInsight(.customize, using: userDefaultsHideCustomizeKey)
}

// MARK: - Grow Audience Card Management

func loadGrowAudienceCardSetting() {
loadPermanentlyDismissableInsight(.growAudience, using: userDefaultsHideGrowAudienceKey)
}

func dismissGrowAudienceCard() {
permanentlyDismissInsight(.growAudience, using: userDefaultsHideGrowAudienceKey)
}

// MARK: - Insights Management

func showAddInsightView() {
Expand Down Expand Up @@ -370,7 +399,7 @@ private extension SiteStatsInsightsTableViewController {
}

func canMoveInsightUp(_ insight: InsightType) -> Bool {
let isShowingPinnedCard = insightsToShow.contains(.customize)
let isShowingPinnedCard = insightsToShow.contains(.customize) || insightsToShow.contains(.growAudience)

let minIndex = isShowingPinnedCard ? 1 : 0

Expand Down Expand Up @@ -498,6 +527,11 @@ extension SiteStatsInsightsTableViewController: SiteStatsInsightsDelegate {
showAddInsightView()
}

func growAudienceDismissButtonTapped() {
dismissGrowAudienceCard()
updateView()
}

func showAddInsight() {
showAddInsightView()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ class SiteStatsInsightsViewModel: Observable {
}

switch insightType {
case .growAudience:
tableRows.append(blocks(for: .growAudience,
type: .insights,
status: insightsStore.allTimeStatus,
block: {
let viewsCount = insightsStore.getAllTimeStats()?.viewsCount
return GrowAudienceRow(hintType: .bloggingReminders,
allTimeViewsCount: viewsCount ?? 0,
siteStatsInsightsDelegate: siteStatsInsightsDelegate)
}, loading: {
return StatsGhostGrowAudienceImmutableRow()
}, error: errorBlock))
case .customize:
tableRows.append(CustomizeInsightsRow(siteStatsInsightsDelegate: siteStatsInsightsDelegate))
case .latestPostSummary:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class StatsGhostBaseCell: UITableViewCell {
}
}

class StatsGhostGrowAudienceCell: StatsGhostBaseCell, NibLoadable { }
class StatsGhostTwoColumnCell: StatsGhostBaseCell, NibLoadable { }
class StatsGhostTopCell: StatsGhostBaseCell, NibLoadable { }
class StatsGhostTopHeaderCell: StatsGhostBaseCell, NibLoadable {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="ENf-kV-WdW" customClass="StatsGhostGrowAudienceCell" customModule="WordPress" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="414" height="256"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ENf-kV-WdW" id="jCC-TG-PHL">
<rect key="frame" x="0.0" y="0.0" width="414" height="256"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" horizontalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="oRq-Yy-EB0">
<rect key="frame" x="16" y="24" width="32" height="32"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="04r-ES-3Iq"/>
<constraint firstAttribute="height" constant="32" id="yLV-ij-fdt"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Wex-fe-ee3">
<rect key="frame" x="56" y="40" width="100" height="16"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="8bK-jF-CrV"/>
<constraint firstAttribute="height" constant="16" id="amP-Ph-bTe"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" alignment="top" spacing="80" translatesAutoresizingMaskIntoConstraints="NO" id="JjF-Qe-4WD">
<rect key="frame" x="16" y="80" width="382" height="98"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="NRZ-tk-S2r">
<rect key="frame" x="0.0" y="0.0" width="214" height="96"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DrN-Sa-4uf">
<rect key="frame" x="0.0" y="0.0" width="214" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="xVa-vr-sYv"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uod-lr-D1U">
<rect key="frame" x="0.0" y="48" width="214" height="48"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="92Z-dx-G3Q"/>
</constraints>
</view>
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gs2-8u-XNT">
<rect key="frame" x="294" y="0.0" width="88" height="88"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" secondItem="gs2-8u-XNT" secondAttribute="height" multiplier="1:1" id="1wJ-Qt-dud"/>
<constraint firstAttribute="width" constant="88" id="OIg-sz-Kuv"/>
</constraints>
</view>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="hTQ-wK-Kvh">
<rect key="frame" x="16" y="210" width="382" height="30"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6YA-w0-Isv">
<rect key="frame" x="0.0" y="0.0" width="100" height="30"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="7cY-sR-8xH"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="h4H-Qd-4cd">
<rect key="frame" x="282" y="0.0" width="100" height="30"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="Y7G-6x-chX"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="30" id="VRh-G6-lnr"/>
</constraints>
</stackView>
</subviews>
<constraints>
<constraint firstItem="oRq-Yy-EB0" firstAttribute="top" secondItem="jCC-TG-PHL" secondAttribute="top" constant="24" id="3rh-ER-WG4"/>
<constraint firstAttribute="bottom" secondItem="hTQ-wK-Kvh" secondAttribute="bottom" constant="16" id="4ql-pQ-Cvy"/>
<constraint firstItem="JjF-Qe-4WD" firstAttribute="top" secondItem="oRq-Yy-EB0" secondAttribute="bottom" constant="24" id="6H3-2Q-pB2"/>
<constraint firstItem="hTQ-wK-Kvh" firstAttribute="centerX" secondItem="jCC-TG-PHL" secondAttribute="centerX" id="A04-CH-7Vr"/>
<constraint firstItem="JjF-Qe-4WD" firstAttribute="leading" secondItem="jCC-TG-PHL" secondAttribute="leading" constant="16" id="E1G-sd-f9w"/>
<constraint firstItem="JjF-Qe-4WD" firstAttribute="centerX" secondItem="jCC-TG-PHL" secondAttribute="centerX" id="czi-W6-UOR"/>
<constraint firstItem="oRq-Yy-EB0" firstAttribute="leading" secondItem="jCC-TG-PHL" secondAttribute="leading" constant="16" id="gd3-7K-y6H"/>
<constraint firstAttribute="trailing" secondItem="hTQ-wK-Kvh" secondAttribute="trailing" constant="16" id="key-Dc-hzl"/>
<constraint firstItem="Wex-fe-ee3" firstAttribute="leading" secondItem="oRq-Yy-EB0" secondAttribute="trailing" constant="8" id="l7r-qu-CRf"/>
<constraint firstItem="Wex-fe-ee3" firstAttribute="bottom" secondItem="oRq-Yy-EB0" secondAttribute="bottom" id="ppe-PM-M51"/>
<constraint firstItem="hTQ-wK-Kvh" firstAttribute="top" secondItem="JjF-Qe-4WD" secondAttribute="bottom" constant="32" id="rNc-i2-xdM"/>
<constraint firstItem="hTQ-wK-Kvh" firstAttribute="leading" secondItem="jCC-TG-PHL" secondAttribute="leading" constant="16" id="tR1-Kp-M6A"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<point key="canvasLocation" x="139" y="153"/>
</tableViewCell>
</objects>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ extension StatsRowGhostable {
}
}

struct StatsGhostGrowAudienceImmutableRow: StatsRowGhostable {
static let cell: ImmuTableCell = {
return ImmuTableCell.nib(StatsGhostGrowAudienceCell.defaultNib, StatsGhostGrowAudienceCell.self)
}()
}

struct StatsGhostTwoColumnImmutableRow: StatsRowGhostable {
static let cell: ImmuTableCell = {
return ImmuTableCell.nib(StatsGhostTwoColumnCell.defaultNib, StatsGhostTwoColumnCell.self)
Expand Down
Loading

0 comments on commit 225fe01

Please sign in to comment.