Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stats Traffic: Ensure deep links and widget routing work #22695

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions WordPress/Classes/Utility/ContentCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ struct DefaultContentCoordinator: ContentCoordinator {
let matches = matcher.routesMatching(url)
if let match = matches.first,
let action = match.action as? StatsRoute,
let timePeriod = action.timePeriod {
// Initializing a StatsPeriodType to ensure we have a valid period
let key = SiteStatsDashboardViewController.lastSelectedStatsPeriodTypeKey(forSiteID: siteID)
UserPersistentStoreFactory.instance().set(timePeriod.rawValue, forKey: key)
let tab = action.tab {
SiteStatsDashboardPreferences.setSelected(tabType: tab, siteID: siteID)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ final class InteractiveNotificationsManager: NSObject {
RootViewCoordinator.sharedPresenter.mySitesCoordinator.showStats(
for: targetBlog,
source: .notification,
timePeriod: .weeks,
tab: .weeks,
date: targetDate)
}

Expand Down
24 changes: 12 additions & 12 deletions WordPress/Classes/Utility/Universal Links/Routes+Stats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum StatsRoute {
case annualStats
case activityLog

var timePeriod: StatsPeriodType? {
var tab: StatsTabType? {
switch self {
case .daySite:
return .days
Expand Down Expand Up @@ -85,19 +85,19 @@ extension StatsRoute: NavigationAction {
showStatsForDefaultBlog(from: values, with: coordinator)
}
case .daySite:
showStatsForBlog(from: values, timePeriod: .days, using: coordinator)
showStatsForBlog(from: values, tab: .days, using: coordinator)
case .weekSite:
showStatsForBlog(from: values, timePeriod: .weeks, using: coordinator)
showStatsForBlog(from: values, tab: .weeks, using: coordinator)
case .monthSite:
showStatsForBlog(from: values, timePeriod: .months, using: coordinator)
showStatsForBlog(from: values, tab: .months, using: coordinator)
case .yearSite:
showStatsForBlog(from: values, timePeriod: .years, using: coordinator)
showStatsForBlog(from: values, tab: .years, using: coordinator)
case .insights:
showStatsForBlog(from: values, timePeriod: .insights, using: coordinator)
showStatsForBlog(from: values, tab: .insights, using: coordinator)
case .dayCategory:
showStatsForBlog(from: values, timePeriod: .days, using: coordinator)
showStatsForBlog(from: values, tab: .days, using: coordinator)
case .annualStats:
showStatsForBlog(from: values, timePeriod: .years, using: coordinator)
showStatsForBlog(from: values, tab: .years, using: coordinator)
case .activityLog:
if let blog = blog(from: values) {
coordinator.showActivityLog(for: blog)
Expand All @@ -109,12 +109,12 @@ extension StatsRoute: NavigationAction {
}

private func showStatsForBlog(from values: [String: String],
timePeriod: StatsPeriodType,
tab: StatsTabType,
using coordinator: MySitesCoordinator) {
if let blog = blog(from: values) {
coordinator.showStats(for: blog,
source: source(from: values),
timePeriod: timePeriod)
tab: tab)
} else {
showMySitesAndFailureNotice(using: coordinator,
values: values)
Expand All @@ -139,12 +139,12 @@ extension StatsRoute: NavigationAction {
// In this case, we'll check whether the last component is actually a
// time period, and if so we'll show that time period for the default site.
guard let component = values["domain"],
let timePeriod = StatsPeriodType(from: component),
let timePeriod = StatsTabType(from: component),
let blog = defaultBlog() else {
return
}

coordinator.showStats(for: blog, source: source(from: values), timePeriod: timePeriod)
coordinator.showStats(for: blog, source: source(from: values), tab: timePeriod)
}

private func source(from values: [String: String]) -> BlogDetailsNavigationSource {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension MySiteViewController {
case .stats:
// Show the stats view for the current blog
if let blog = blog {
RootViewCoordinator.sharedPresenter.mySitesCoordinator.showStats(for: blog, source: .onboarding, timePeriod: .insights)
RootViewCoordinator.sharedPresenter.mySitesCoordinator.showStats(for: blog, source: .onboarding, tab: .insights)
}
case .writing:
// Open the editor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ final class SiteStatsPeriodViewModel: Observable {
private weak var referrerDelegate: SiteStatsReferrerDelegate?
private let store: any StatsPeriodStoreProtocol
private var lastRequestedDate: Date
private var lastRequestedPeriod: StatsPeriodUnit
private var lastRequestedPeriod: StatsPeriodUnit {
didSet {
SiteStatsDashboardPreferences.setSelected(periodUnit: lastRequestedPeriod)
}
}
private var periodReceipt: Receipt?
private var changeReceipt: Receipt?
private typealias Style = WPStyleGuide.Stats
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import UIKit

enum StatsPeriodType: Int, FilterTabBarItem, CaseIterable {
enum StatsTabType: Int, FilterTabBarItem, CaseIterable {
case insights = 0
case days
case weeks
Expand Down Expand Up @@ -38,10 +38,25 @@ enum StatsPeriodType: Int, FilterTabBarItem, CaseIterable {
return nil
}
}

var unit: StatsPeriodUnit? {
switch self {
case .days:
return .day
case .weeks:
return .week
case .months:
return .month
case .years:
return .year
default:
return nil
}
}
}

fileprivate extension StatsPeriodType {
static var displayedPeriods: [StatsPeriodType] {
fileprivate extension StatsTabType {
static var displayedTabs: [StatsTabType] {
if RemoteFeatureFlag.statsTrafficTab.enabled() {
return [.traffic, .insights]
} else {
Expand All @@ -62,13 +77,6 @@ fileprivate extension StatsPeriodType {
}

class SiteStatsDashboardViewController: UIViewController {

// MARK: - Keys

static func lastSelectedStatsPeriodTypeKey(forSiteID siteID: Int) -> String {
return "LastSelectedStatsPeriodType-\(siteID)"
}

static let lastSelectedStatsDateKey = "LastSelectedStatsDate"

// MARK: - Properties
Expand All @@ -80,18 +88,18 @@ class SiteStatsDashboardViewController: UIViewController {
private lazy var periodTableViewControllerDeprecated = SiteStatsPeriodTableViewControllerDeprecated.loadFromStoryboard()
private lazy var trafficTableViewController = {
let date: Date
if let selectedDate = getLastSelectedDateFromUserDefaults() {
if let selectedDate = SiteStatsDashboardPreferences.getLastSelectedDateFromUserDefaults() {
date = selectedDate
} else {
date = StatsDataHelper.currentDateForSite()
}

let currentPeriod = StatsPeriodUnit(rawValue: currentSelectedPeriod.rawValue - 1) ?? .day
let currentPeriod = SiteStatsDashboardPreferences.getSelectedPeriodUnit() ?? .day

return SiteStatsPeriodTableViewController(date: date, period: currentPeriod)
}()
private var pageViewController: UIPageViewController?
private lazy var displayedPeriods: [StatsPeriodType] = StatsPeriodType.displayedPeriods
private lazy var displayedTabs: [StatsTabType] = StatsTabType.displayedTabs

@objc lazy var manageInsightsButton: UIBarButtonItem = {
let button = UIBarButtonItem(
Expand All @@ -113,7 +121,7 @@ class SiteStatsDashboardViewController: UIViewController {
configureTrafficTableViewController()
setupFilterBar()
restoreSelectedDateFromUserDefaults()
restoreSelectedPeriodFromUserDefaults()
restoreSelectedTabFromUserDefaults()
addWillEnterForegroundObserver()
configureNavBar()
view.accessibilityIdentifier = "stats-dashboard"
Expand All @@ -138,7 +146,7 @@ class SiteStatsDashboardViewController: UIViewController {
}

func configureNavBar() {
parent?.navigationItem.rightBarButtonItem = currentSelectedPeriod == .insights ? manageInsightsButton : nil
parent?.navigationItem.rightBarButtonItem = currentSelectedTab == .insights ? manageInsightsButton : nil
}

func configureJetpackBanner() {
Expand Down Expand Up @@ -173,30 +181,30 @@ class SiteStatsDashboardViewController: UIViewController {

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if traitCollection.verticalSizeClass == .regular, traitCollection.horizontalSizeClass == .compact {
updatePeriodView(oldSelectedPeriod: currentSelectedPeriod)
updatePeriodView(oldSelectedTab: currentSelectedTab)
}
}
}

extension SiteStatsDashboardViewController: StatsForegroundObservable {
func reloadStatsData() {
updatePeriodView(oldSelectedPeriod: currentSelectedPeriod)
updatePeriodView(oldSelectedTab: currentSelectedTab)
}
}

// MARK: - Private Extension

private extension SiteStatsDashboardViewController {
var currentSelectedPeriod: StatsPeriodType {
var currentSelectedTab: StatsTabType {
get {
let selectedIndex = filterTabBar?.selectedIndex ?? 0
return displayedPeriods[selectedIndex]
return displayedTabs[selectedIndex]
}
set {
let index = displayedPeriods.firstIndex(of: newValue) ?? 0
let index = displayedTabs.firstIndex(of: newValue) ?? 0
filterTabBar?.setSelectedIndex(index)
let oldSelectedPeriod = getSelectedPeriodFromUserDefaults()
updatePeriodView(oldSelectedPeriod: oldSelectedPeriod)
let oldSelectedPeriod = getSelectedTabFromUserDefaults()
updatePeriodView(oldSelectedTab: oldSelectedPeriod)
saveSelectedPeriodToUserDefaults()
trackAccessEvent()
}
Expand All @@ -209,13 +217,13 @@ private extension SiteStatsDashboardViewController {

func setupFilterBar() {
WPStyleGuide.Stats.configureFilterTabBar(filterTabBar)
filterTabBar.items = displayedPeriods
filterTabBar.items = displayedTabs
filterTabBar.addTarget(self, action: #selector(selectedFilterDidChange(_:)), for: .valueChanged)
filterTabBar.accessibilityIdentifier = "site-stats-dashboard-filter-bar"
}

@objc func selectedFilterDidChange(_ filterBar: FilterTabBar) {
currentSelectedPeriod = displayedPeriods[filterBar.selectedIndex]
currentSelectedTab = displayedTabs[filterBar.selectedIndex]

configureNavBar()
}
Expand All @@ -231,50 +239,38 @@ private extension SiteStatsDashboardViewController {
return
}

let key = Self.lastSelectedStatsPeriodTypeKey(forSiteID: siteID)

guard !insightsTableViewController.isGrowAudienceShowing else {
UserPersistentStoreFactory.instance().set(StatsPeriodType.insights.rawValue, forKey: key)
SiteStatsDashboardPreferences.setSelected(tabType: .insights, siteID: siteID)
return
}

UserPersistentStoreFactory.instance().set(currentSelectedPeriod.rawValue, forKey: key)
SiteStatsDashboardPreferences.setSelected(tabType: currentSelectedTab, siteID: siteID)
}

func getSelectedPeriodFromUserDefaults() -> StatsPeriodType {

guard let siteID = SiteStatsInformation.sharedInstance.siteID?.intValue,
let periodType = StatsPeriodType(rawValue: UserPersistentStoreFactory.instance().integer(forKey: Self.lastSelectedStatsPeriodTypeKey(forSiteID: siteID))) else {
return displayedPeriods[0]
func getSelectedTabFromUserDefaults() -> StatsTabType {
guard let tabType = SiteStatsDashboardPreferences.getSelectedTabType() else {
return displayedTabs[0]
}

return periodType
}

func getLastSelectedDateFromUserDefaults() -> Date? {
UserPersistentStoreFactory.instance().object(forKey: Self.lastSelectedStatsDateKey) as? Date
}

func removeLastSelectedDateFromUserDefaults() {
UserPersistentStoreFactory.instance().removeObject(forKey: Self.lastSelectedStatsDateKey)
return tabType
}

func restoreSelectedDateFromUserDefaults() {
periodTableViewControllerDeprecated.selectedDate = getLastSelectedDateFromUserDefaults()
removeLastSelectedDateFromUserDefaults()
periodTableViewControllerDeprecated.selectedDate = SiteStatsDashboardPreferences.getLastSelectedDateFromUserDefaults()
SiteStatsDashboardPreferences.removeLastSelectedDateFromUserDefaults()
}

func restoreSelectedPeriodFromUserDefaults() {
currentSelectedPeriod = getSelectedPeriodFromUserDefaults()
func restoreSelectedTabFromUserDefaults() {
currentSelectedTab = getSelectedTabFromUserDefaults()
}

func updatePeriodView(oldSelectedPeriod: StatsPeriodType) {
let selectedPeriodChanged = currentSelectedPeriod != oldSelectedPeriod
let previousSelectedPeriodWasInsights = oldSelectedPeriod == .insights
func updatePeriodView(oldSelectedTab: StatsTabType) {
let selectedPeriodChanged = currentSelectedTab != oldSelectedTab
let previousSelectedPeriodWasInsights = oldSelectedTab == .insights
let pageViewControllerIsEmpty = pageViewController?.viewControllers?.isEmpty ?? true
let isGrowAudienceShowingOnInsights = insightsTableViewController.isGrowAudienceShowing

switch currentSelectedPeriod {
switch currentSelectedTab {
case .insights:
if selectedPeriodChanged || pageViewControllerIsEmpty || isGrowAudienceShowingOnInsights {
pageViewController?.setViewControllers([insightsTableViewController],
Expand All @@ -301,7 +297,7 @@ private extension SiteStatsDashboardViewController {
periodTableViewControllerDeprecated.selectedDate = StatsDataHelper.currentDateForSite()
}

let selectedPeriod = StatsPeriodUnit(rawValue: currentSelectedPeriod.rawValue - 1) ?? .day
let selectedPeriod = StatsPeriodUnit(rawValue: currentSelectedTab.rawValue - 1) ?? .day
periodTableViewControllerDeprecated.selectedPeriod = selectedPeriod
}
}
Expand All @@ -321,8 +317,65 @@ private extension SiteStatsDashboardViewController {
}

func trackAccessEvent() {
if let event = currentSelectedPeriod.analyticsAccessEvent {
if let event = currentSelectedTab.analyticsAccessEvent {
captureAnalyticsEvent(event)
}
}
}

// MARK: - Preferences

struct SiteStatsDashboardPreferences {
static func setSelected(tabType: StatsTabType, siteID: Int? = nil) {
guard let siteID = siteID ?? SiteStatsInformation.sharedInstance.siteID?.intValue else { return }

let periodKey = lastSelectedStatsTabTypeKey(forSiteID: siteID)
UserPersistentStoreFactory.instance().set(tabType.rawValue, forKey: periodKey)

let unitKey = lastSelectedStatsUnitTypeKey(forSiteID: siteID)
if let unit = tabType.unit {
UserPersistentStoreFactory.instance().set(unit.rawValue, forKey: unitKey)
}
}

static func setSelected(periodUnit: StatsPeriodUnit) {
guard let siteID = SiteStatsInformation.sharedInstance.siteID?.intValue else { return }

let unitKey = lastSelectedStatsUnitTypeKey(forSiteID: siteID)
UserPersistentStoreFactory.instance().set(periodUnit.rawValue, forKey: unitKey)
}

static func getSelectedTabType() -> StatsTabType? {
guard let siteID = SiteStatsInformation.sharedInstance.siteID?.intValue else { return nil }

let key = Self.lastSelectedStatsTabTypeKey(forSiteID: siteID)
return StatsTabType(rawValue: UserPersistentStoreFactory.instance().integer(forKey: key))
}

static func getSelectedPeriodUnit() -> StatsPeriodUnit? {
guard let siteID = SiteStatsInformation.sharedInstance.siteID?.intValue else { return nil }

let key = Self.lastSelectedStatsUnitTypeKey(forSiteID: siteID)
return StatsPeriodUnit(rawValue: UserPersistentStoreFactory.instance().integer(forKey: key))
}

static func getLastSelectedDateFromUserDefaults() -> Date? {
UserPersistentStoreFactory.instance().object(forKey: Self.lastSelectedStatsDateKey) as? Date
}

static func removeLastSelectedDateFromUserDefaults() {
UserPersistentStoreFactory.instance().removeObject(forKey: Self.lastSelectedStatsDateKey)
}

// MARK: - Keys

private static func lastSelectedStatsTabTypeKey(forSiteID siteID: Int) -> String {
return "LastSelectedStatsTabType-\(siteID)"
}

private static func lastSelectedStatsUnitTypeKey(forSiteID siteID: Int) -> String {
return "LastSelectedStatsUnitType-\(siteID)"
}

private static let lastSelectedStatsDateKey = "LastSelectedStatsDate"
}
Loading