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

Update JetpackStatsWidget #24222

Merged
merged 3 commits into from
Mar 19, 2025
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
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import Foundation
import JetpackStatsWidgetsCore

/// Cache manager that stores `HomeWidgetData` values in a plist file, contained in the specified security application group and with the specified file name.
/// The corresponding dictionary is always in the form `[Int: T]`, where the `Int` key is the SiteID, and the `T` value is any `HomeWidgetData` instance.
struct HomeWidgetCache<T: HomeWidgetData> {
public struct HomeWidgetCache<T: HomeWidgetData> {
let fileName: String
let appGroup: String

init(fileName: String = T.filename, appGroup: String) {
public init(fileName: String = T.filename, appGroup: String) {
self.fileName = fileName
self.appGroup = appGroup
}
Expand All @@ -27,42 +26,34 @@ struct HomeWidgetCache<T: HomeWidgetData> {
return directoryURL.appendingPathComponent(fileName)
}

func read() throws -> [Int: T]? {

guard let fileURL,
FileManager.default.fileExists(atPath: fileURL.path) else {
return nil
public func read() throws -> [Int: T]? {
guard let fileURL, FileManager.default.fileExists(atPath: fileURL.path) else {
return nil
}

let data = try Data(contentsOf: fileURL)
return try PropertyListDecoder().decode([Int: T].self, from: data)
}

func write(items: [Int: T]) throws {

guard let fileURL else {
return
}
public func write(items: [Int: T]) throws {
guard let fileURL else { return }

let encodedData = try PropertyListEncoder().encode(items)
try encodedData.write(to: fileURL)
}

func setItem(item: T) throws {
public func setItem(item: T) throws {
var cachedItems = try read() ?? [Int: T]()

cachedItems[item.siteID] = item

try write(items: cachedItems)
}

func delete() throws {

guard let fileURL else {
return
}
public func delete() throws {
guard let fileURL else { return }
try FileManager.default.removeItem(at: fileURL)
}

static var testAppGroupNamePrefix: String { "xctest" }
public static var testAppGroupNamePrefix: String { "xctest" }
}
106 changes: 63 additions & 43 deletions WordPress/Classes/Stores/StatsWidgetsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,18 @@ private extension StatsWidgetsStore {
var initializedWeekdays: [ThisWeekWidgetDay] {
var days = [ThisWeekWidgetDay]()
for index in 0...7 {
days.insert(ThisWeekWidgetDay(date: NSCalendar.current.date(byAdding: .day,
value: -index,
to: Date()) ?? Date(),
viewsCount: 0,
dailyChangePercent: 0),
at: index)
let day = ThisWeekWidgetDay(
date: NSCalendar.current.date(byAdding: .day, value: -index, to: Date()) ?? Date(),
viewsCount: 0,
dailyChangePercent: 0
)
days.insert(day, at: index)
}
return days
}

func refreshStats<T: HomeWidgetData>(type: T.Type) -> [Int: T]? {
guard let currentData = T.read() else {
guard let currentData = getCachedItems(for: T.self) else {
return nil
}
let updatedSiteList = (try? BlogQuery().hostedByWPCom(true).blogs(in: coreDataStack.mainContext)) ?? []
Expand All @@ -223,33 +223,39 @@ private extension StatsWidgetsStore {

let stats = (existingSite as? HomeWidgetTodayData)?.stats ?? TodayWidgetStats()

sitesList[blogID.intValue] = HomeWidgetTodayData(siteID: blogID.intValue,
siteName: siteName,
url: siteURL,
timeZone: timeZone,
date: date,
stats: stats) as? T
sitesList[blogID.intValue] = HomeWidgetTodayData(
siteID: blogID.intValue,
siteName: siteName,
url: siteURL,
timeZone: timeZone,
date: date,
stats: stats
) as? T
} else if type == HomeWidgetAllTimeData.self {

let stats = (existingSite as? HomeWidgetAllTimeData)?.stats ?? AllTimeWidgetStats()

sitesList[blogID.intValue] = HomeWidgetAllTimeData(siteID: blogID.intValue,
siteName: siteName,
url: siteURL,
timeZone: timeZone,
date: date,
stats: stats) as? T
sitesList[blogID.intValue] = HomeWidgetAllTimeData(
siteID: blogID.intValue,
siteName: siteName,
url: siteURL,
timeZone: timeZone,
date: date,
stats: stats
) as? T

} else if type == HomeWidgetThisWeekData.self {

let stats = (existingSite as? HomeWidgetThisWeekData)?.stats ?? ThisWeekWidgetStats(days: initializedWeekdays)

sitesList[blogID.intValue] = HomeWidgetThisWeekData(siteID: blogID.intValue,
siteName: siteName,
url: siteURL,
timeZone: timeZone,
date: date,
stats: stats) as? T
sitesList[blogID.intValue] = HomeWidgetThisWeekData(
siteID: blogID.intValue,
siteName: siteName,
url: siteURL,
timeZone: timeZone,
date: date,
stats: stats
) as? T
}
}
return newData
Expand All @@ -265,26 +271,40 @@ private extension StatsWidgetsStore {
let title = (element.title ?? url).isEmpty ? url : element.title ?? url
let timeZone = blog.timeZone
if type == HomeWidgetTodayData.self {
result[blogID.intValue] = HomeWidgetTodayData(siteID: blogID.intValue,
siteName: title,
url: url,
timeZone: timeZone ?? TimeZone.current,
date: Date(timeIntervalSinceReferenceDate: 0),
stats: TodayWidgetStats()) as? T
result[blogID.intValue] = HomeWidgetTodayData(
siteID: blogID.intValue,
siteName: title,
url: url,
timeZone: timeZone ?? TimeZone.current,
date: Date(
timeIntervalSinceReferenceDate: 0
),
stats: TodayWidgetStats()
) as? T
} else if type == HomeWidgetAllTimeData.self {
result[blogID.intValue] = HomeWidgetAllTimeData(siteID: blogID.intValue,
siteName: title,
url: url,
timeZone: timeZone ?? TimeZone.current,
date: Date(timeIntervalSinceReferenceDate: 0),
stats: AllTimeWidgetStats()) as? T
result[blogID.intValue] = HomeWidgetAllTimeData(
siteID: blogID.intValue,
siteName: title,
url: url,
timeZone: timeZone ?? TimeZone.current,
date: Date(
timeIntervalSinceReferenceDate: 0
),
stats: AllTimeWidgetStats()
) as? T
} else if type == HomeWidgetThisWeekData.self {
result[blogID.intValue] = HomeWidgetThisWeekData(siteID: blogID.intValue,
siteName: title,
url: url,
timeZone: timeZone ?? TimeZone.current,
date: Date(timeIntervalSinceReferenceDate: 0),
stats: ThisWeekWidgetStats(days: initializedWeekdays)) as? T
result[blogID.intValue] = HomeWidgetThisWeekData(
siteID: blogID.intValue,
siteName: title,
url: url,
timeZone: timeZone ?? TimeZone.current,
date: Date(
timeIntervalSinceReferenceDate: 0
),
stats: ThisWeekWidgetStats(
days: initializedWeekdays
)
) as? T
}
}
}
Expand Down
33 changes: 0 additions & 33 deletions WordPress/Jetpack/WidgetConfiguration.swift

This file was deleted.

12 changes: 12 additions & 0 deletions WordPress/JetpackIntents/SitesDataProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,15 @@ class SitesDataProvider {
}
}
}

private extension HomeWidgetData {
static func read(from cache: HomeWidgetCache<Self>? = nil) -> [Int: Self]? {

let cache = cache ?? HomeWidgetCache<Self>(fileName: Self.filename, appGroup: BuildSettings.current.appGroupName)
do {
return try cache.read()
} catch {
return nil
}
}
}
7 changes: 0 additions & 7 deletions WordPress/JetpackStatsWidgets/LocalizationConfiguration.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Foundation
import CocoaLumberjackSwift
import WidgetKit
import SwiftUI
import BuildSettingsKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ struct LockScreenMultiStatWidgetViewProvider<WidgetData: HomeWidgetData>: LockSc
let message: String
switch widgetKind {
case .today:
message = AppConfiguration.Widget.Localization.unconfiguredViewTodayTitle
message = LocalizableStrings.unconfiguredViewJetpackTodayTitle
case .allTime:
message = AppConfiguration.Widget.Localization.unconfiguredViewAllTimeTitle
message = LocalizableStrings.unconfiguredViewJetpackAllTimeTitle
case .thisWeek:
message = AppConfiguration.Widget.Localization.unconfiguredViewThisWeekTitle
message = LocalizableStrings.unconfiguredViewJetpackThisWeekTitle
}
let viewModel = LockScreenUnconfiguredViewModel(message: message)
return LockScreenUnconfiguredView(viewModel: viewModel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ struct LockScreenSingleStatWidgetViewProvider<WidgetData: HomeWidgetData>: LockS
let message: String
switch widgetKind {
case .today:
message = AppConfiguration.Widget.Localization.unconfiguredViewTodayTitle
message = LocalizableStrings.unconfiguredViewJetpackTodayTitle
case .allTime:
message = AppConfiguration.Widget.Localization.unconfiguredViewAllTimeTitle
message = LocalizableStrings.unconfiguredViewJetpackAllTimeTitle
case .thisWeek:
message = AppConfiguration.Widget.Localization.unconfiguredViewThisWeekTitle
message = LocalizableStrings.unconfiguredViewJetpackThisWeekTitle
}
let viewModel = LockScreenUnconfiguredViewModel(message: message)
return LockScreenUnconfiguredView(viewModel: viewModel)
Expand Down
37 changes: 8 additions & 29 deletions WordPress/JetpackStatsWidgets/Model/HomeWidgetData.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Foundation
import CocoaLumberjackSwift
import JetpackStatsWidgetsCore
import BuildSettingsKit

Expand All @@ -6,9 +8,7 @@ import BuildSettingsKit
extension HomeWidgetData {

static func read(from cache: HomeWidgetCache<Self>? = nil) -> [Int: Self]? {

let cache = cache ?? HomeWidgetCache<Self>(fileName: Self.filename,
appGroup: BuildSettings.current.appGroupName)
let cache = cache ?? makeCache()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated this for simplicity. It's just convenience wrappers – I don't think it hurts. It's better than creating yet another module just to reuse two methods.

do {
return try cache.read()
} catch {
Expand All @@ -17,37 +17,16 @@ extension HomeWidgetData {
}
}

static func write(items: [Int: Self], to cache: HomeWidgetCache<Self>? = nil) {

let cache = cache ?? HomeWidgetCache<Self>(fileName: Self.filename,
appGroup: BuildSettings.current.appGroupName)

do {
try cache.write(items: items)
} catch {
DDLogError("HomeWidgetToday: Failed writing data: \(error.localizedDescription)")
}
}

static func delete(cache: HomeWidgetCache<Self>? = nil) {
let cache = cache ?? HomeWidgetCache<Self>(fileName: Self.filename,
appGroup: BuildSettings.current.appGroupName)

do {
try cache.delete()
} catch {
DDLogError("HomeWidgetToday: Failed deleting data: \(error.localizedDescription)")
}
}

static func setItem(item: Self, to cache: HomeWidgetCache<Self>? = nil) {
let cache = cache ?? HomeWidgetCache<Self>(fileName: Self.filename,
appGroup: BuildSettings.current.appGroupName)

let cache = cache ?? makeCache()
do {
try cache.setItem(item: item)
} catch {
DDLogError("HomeWidgetToday: Failed writing data item: \(error.localizedDescription)")
}
}

private static func makeCache() -> HomeWidgetCache<Self> {
HomeWidgetCache<Self>(fileName: Self.filename, appGroup: BuildSettings.current.appGroupName)
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Foundation
import CocoaLumberjackSwift
import SFHFKeychainUtils
import BuildSettingsKit
import WordPressKit
Expand Down
2 changes: 2 additions & 0 deletions WordPress/JetpackStatsWidgets/SiteListProvider.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Foundation
import CocoaLumberjackSwift
import WidgetKit
import BuildSettingsKit
import SwiftUI
Expand Down

This file was deleted.

6 changes: 3 additions & 3 deletions WordPress/JetpackStatsWidgets/Views/UnconfiguredView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ struct UnconfiguredView: View {
case .loggedOut(let widgetKind):
switch widgetKind {
case .today:
return AppConfiguration.Widget.Localization.unconfiguredViewTodayTitle
return LocalizableStrings.unconfiguredViewJetpackTodayTitle
case .allTime:
return AppConfiguration.Widget.Localization.unconfiguredViewAllTimeTitle
return LocalizableStrings.unconfiguredViewJetpackAllTimeTitle
case .thisWeek:
return AppConfiguration.Widget.Localization.unconfiguredViewThisWeekTitle
return LocalizableStrings.unconfiguredViewJetpackThisWeekTitle
}
case .noSite(let widgetKind):
switch widgetKind {
Expand Down
Loading