Skip to content

Commit 9a93135

Browse files
crazytonylikeanwpmobilebot
authored
Merge/release 26.8 into trunk (#25427)
* Fix background color for Leave Comment button (#25412) * Fix scrolling to selected comment (#25389) * Stats: Final Touches (#25418) * Adjust spacing in Today card * Use orange for map * Fix ChartCardHeaderView disabling comparision (regression) * Add a way to promote subrange to range * Fix data point mapping on long-press or pan * Slightly reduce spacing for collision detection * Add Stats announcemnet (#25411) Co-authored-by: Tony Li <tony.li@automattic.com> * Merge release_notes/26.8 into release/26.8 (#25426) * Add editorialized release notes for version 26.8 * Update metadata strings * Update metadata strings --------- Co-authored-by: Tony Li <tony.li@automattic.com> --------- Co-authored-by: Alex Grebenyuk <alex.grebenyuk@automattic.com> Co-authored-by: WordPress Mobile Bot Account <mobile+wpmobilebot@automattic.com>
1 parent 5f71cd8 commit 9a93135

26 files changed

Lines changed: 507 additions & 191 deletions

Modules/Sources/JetpackStats/Cards/ChartCard.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct ChartCard: View {
8282
trend: viewModel.selectedBarTrend ?? .make(data, context: .regular),
8383
metricTitle: metric.localizedTitle,
8484
period: context.formatters.dateRange.string(from: viewModel.dateRange.subrange ?? viewModel.dateRange.range),
85-
showComparison: dateRange.comparison != .off
85+
showDisclosureIndicator: viewModel.dateRange.subrange != nil
8686
)
8787
}
8888

@@ -93,6 +93,9 @@ struct ChartCard: View {
9393
.padding(.trailing, Constants.step3 + Constants.step0_5)
9494
.accessibilityElement(children: .combine)
9595
.accessibilityLabel(Strings.Accessibility.cardTitle(metric.localizedTitle))
96+
.simultaneousGesture(TapGesture().onEnded {
97+
viewModel.promoteSubrangeToMainRange()
98+
})
9699
}
97100

98101
@ViewBuilder
@@ -314,7 +317,8 @@ struct ChartCardHeaderView: View {
314317
let trend: TrendViewModel
315318
let metricTitle: String
316319
let period: String
317-
let showComparison: Bool
320+
var showComparison: Bool = true
321+
var showDisclosureIndicator: Bool = false
318322
}
319323

320324
let viewModel: ViewModel
@@ -332,9 +336,17 @@ struct ChartCardHeaderView: View {
332336
.font(.caption.weight(.medium))
333337
.foregroundColor(.secondary)
334338
}
335-
Text(viewModel.period)
336-
.font(.system(.caption, design: .rounded, weight: .medium))
337-
.foregroundStyle(Color.secondary)
339+
HStack(spacing: 2) {
340+
Text(viewModel.period)
341+
.font(.system(.caption, design: .rounded, weight: .medium))
342+
.foregroundStyle(Color.secondary)
343+
if viewModel.showDisclosureIndicator {
344+
Image(systemName: "chevron.forward")
345+
.font(.system(.caption2, weight: .semibold))
346+
.scaleEffect(0.8)
347+
.foregroundStyle(Color.secondary)
348+
}
349+
}
338350
if viewModel.showComparison {
339351
Text("\(viewModel.trend.formattedChange) \(viewModel.trend.iconSign) \(viewModel.trend.formattedPercentage)")
340352
.font(.caption.weight(.semibold))

Modules/Sources/JetpackStats/Cards/ChartCardViewModel.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ final class ChartCardViewModel: ObservableObject, TrafficCardViewModel {
3232
}
3333

3434
weak var configurationDelegate: CardConfigurationDelegate?
35+
var onDateRangeChanged: ((StatsDateRangeSelection) -> Void)?
3536

3637
var dateRange: StatsDateRangeSelection {
3738
didSet {
@@ -221,6 +222,11 @@ final class ChartCardViewModel: ObservableObject, TrafficCardViewModel {
221222
return output
222223
}
223224

225+
func promoteSubrangeToMainRange() {
226+
guard let subrange = dateRange.subrange else { return }
227+
onDateRangeChanged?(StatsDateRangeSelection(range: subrange))
228+
}
229+
224230
var selectedBarTrend: TrendViewModel? {
225231
guard let selectedBarDate,
226232
let data = chartData[selectedMetric],

Modules/Sources/JetpackStats/Cards/TodayCard.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ struct TodayCard: View {
9292
}
9393

9494
private func makeMetricsView(with metrics: SiteMetricsSet) -> some View {
95-
HStack(alignment: .bottom, spacing: 16) {
95+
HStack(alignment: .bottom, spacing: 20) {
9696
ForEach(viewModel.configuration.metrics) { metric in
9797
if metric == .views {
9898
TodayCardProminentMetricView(value: metrics[metric], metric: metric)
@@ -130,7 +130,7 @@ struct TodayCard: View {
130130
.frame(maxWidth: .infinity)
131131
.padding(.trailing, 32)
132132
.padding(.vertical, 2)
133-
.offset(y: -9)
133+
.offset(y: -3)
134134
.transition(.opacity.combined(with: .scale(scale: 0.97)))
135135
}
136136

Modules/Sources/JetpackStats/Cards/TopListCard.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ struct TopListCard: View {
108108
private var mapView: some View {
109109
CountriesMapView(
110110
data: viewModel.countriesMapData ?? .init(metric: viewModel.selection.metric, locations: []),
111-
primaryColor: Constants.Colors.uiColorBlue
111+
primaryColor: Constants.Colors.uiColorOrange
112112
)
113113
}
114114

Modules/Sources/JetpackStats/Charts/BarChartView.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,9 @@ struct BarChartView: View {
324324
return nil
325325
}
326326

327-
let origin = geometry[frame].origin
328-
let location = CGPoint(
329-
x: location.x - origin.x,
330-
y: location.y - origin.y
331-
)
332-
guard let date: Date = proxy.value(atX: location.x) else {
327+
let plotFrame = geometry[frame]
328+
let adjustedX = max(0, min(location.x - plotFrame.origin.x, plotFrame.width))
329+
guard let date: Date = proxy.value(atX: adjustedX) else {
333330
return nil
334331
}
335332
// `proxy.value(atX:)` returns a precise date at the tap location.

Modules/Sources/JetpackStats/Charts/Helpers/ChartHelper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct ChartHelper {
6767
} else {
6868
AxisMarks(values: .stride(by: granularity.component, count: 1, calendar: calendar)) { value in
6969
if let date = value.as(Date.self) {
70-
AxisValueLabel(centered: true, collisionResolution: .greedy(minimumSpacing: 6)) {
70+
AxisValueLabel(centered: true, collisionResolution: .greedy(minimumSpacing: 5)) {
7171
ChartAxisDateLabel(date: date, granularity: granularity)
7272
}
7373
}

Modules/Sources/JetpackStats/Constants.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public enum Constants {
4343
static let celadon = Color(palette: CSColor.Celadon.self)
4444

4545
static let uiColorBlue = UIColor(palette: CSColor.Blue.self)
46+
static let uiColorOrange = UIColor(palette: CSColor.Orange.self)
4647

4748
static let jetpack = Color(palette: CSColor.JetpackGreen.self)
4849

Modules/Sources/JetpackStats/StatsViewModel.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,16 @@ final class StatsViewModel: ObservableObject, CardConfigurationDelegate {
183183
context: context
184184
)
185185
case .chart(let configuration):
186-
viewModel = ChartCardViewModel(
186+
let chartVM = ChartCardViewModel(
187187
configuration: configuration,
188188
dateRange: effectiveDateRange,
189189
service: context.service,
190190
tracker: context.tracker
191191
)
192+
chartVM.onDateRangeChanged = { [weak self] newRange in
193+
self?.dateRange = newRange
194+
}
195+
viewModel = chartVM
192196
case .topList(let configuration):
193197
viewModel = TopListViewModel(
194198
configuration: configuration,

Modules/Sources/JetpackStats/Utilities/SelectedDataPoints.swift

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,21 @@ struct SelectedDataPoints {
1313
mappedPreviousSeries: [DataPoint]
1414
) -> SelectedDataPoints? {
1515
guard let date else { return nil }
16-
17-
// Since mappedPreviousData has the same dates as currentData,
18-
// we only need to find the closest date in the current series
1916
guard !currentSeries.isEmpty else { return nil }
2017

21-
// Find the closest data point in the current series
22-
guard let closestPoint = findClosestDataPoint(to: date, in: currentSeries + mappedPreviousSeries) else {
23-
return nil
24-
}
18+
// Find the index of the closest point in currentSeries.
19+
// Using index-based lookup so that the corresponding previous point is
20+
// retrieved by position, not by exact Date equality — the mapped dates
21+
// may differ slightly (e.g. across DST boundaries).
22+
guard let closestIndex = currentSeries.indices.min(by: {
23+
abs(currentSeries[$0].date.timeIntervalSince(date)) <
24+
abs(currentSeries[$1].date.timeIntervalSince(date))
25+
}) else { return nil }
2526

26-
// Find the closest date value
27-
let closestDate = closestPoint.date
27+
let currentPoint = currentSeries[closestIndex]
28+
let previousPoint = mappedPreviousSeries.indices.contains(closestIndex) ? mappedPreviousSeries[closestIndex] : nil
29+
let unmappedPrevious = previousSeries.indices.contains(closestIndex) ? previousSeries[closestIndex] : nil
2830

29-
// Find points with this exact date in both series
30-
let currentPoint = currentSeries.first { $0.date == closestDate }
31-
let previousPointIndex = mappedPreviousSeries.firstIndex { $0.date == closestDate }
32-
var previousPoint: DataPoint? {
33-
guard let previousPointIndex, mappedPreviousSeries.indices.contains(previousPointIndex) else { return nil }
34-
return mappedPreviousSeries[previousPointIndex]
35-
}
36-
// We need this just to display the data in the tooltip.
37-
var unmappedPrevious: DataPoint? {
38-
guard let previousPointIndex, previousSeries.indices.contains(previousPointIndex) else { return nil }
39-
return previousSeries[previousPointIndex]
40-
}
4131
return SelectedDataPoints(current: currentPoint, previous: previousPoint, unmappedPrevious: unmappedPrevious)
4232
}
4333

@@ -50,13 +40,4 @@ struct SelectedDataPoints {
5040
)
5141
}
5242

53-
// Helper method to find the closest data point to a given date
54-
private static func findClosestDataPoint(to date: Date, in points: [DataPoint]) -> DataPoint? {
55-
guard !points.isEmpty else { return nil }
56-
57-
// Find the point with minimum time difference
58-
return points.min { point1, point2 in
59-
abs(point1.date.timeIntervalSince(date)) < abs(point2.date.timeIntervalSince(date))
60-
}
61-
}
6243
}

Modules/Sources/JetpackStats/Views/ChartValueTooltipView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ struct ChartValueTooltipView: View {
7575
// Summary view
7676
if let trend {
7777
ChartValuesSummaryView(trend: trend, style: .compact)
78-
} else if let previousValue = previousPoint?.value {
79-
Text(StatsValueFormatter(metric: metric).format(value: previousValue, context: .regular))
78+
} else if let value = currentPoint?.value ?? previousPoint?.value {
79+
Text(StatsValueFormatter(metric: metric).format(value: value, context: .regular))
8080
.font(.subheadline.weight(.medium))
8181
}
8282

0 commit comments

Comments
 (0)