Skip to content

Commit a2047ac

Browse files
adalpariclaude
andauthored
CMM-2152: Fix Views card stat accuracy and halve its network calls (#23101)
* Align bottom-row and chart previous windows for month-unit periods For Last6Months/Last12Months the chart derived its previous window by whole-month subtraction while the bottom row used an exact day-span mirror, so the header and the bottom row showed contradictory Views % change on the same card. Share the chart's config-based previous-window rule so both fetches compare against identical windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Stop bottom-row stats call from truncating the first bucket The dedicated bottom-stats call passed a mid-bucket startDate, so for month/year units the API truncated the first bucket's views (additive) while leaving visitors (unique) at the full-bucket value. The bottom row's Views therefore under-counted and disagreed with the chart header. Mirror the chart's fetch (unit + quantity + endDate, no startDate) so the API returns full buckets and the totals match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Align Today chart hourly window to the calendar day The hourly window ended at the next day's 00:00, so the API returned 01:00→00:00 buckets — dropping today's 00:00 hour and under-counting the chart total versus the day-level bottom row. End the window at "<day> 23:00:00" instead so its 24 buckets cover 00:00–23:00 of the actual day (and yesterday for the previous window). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fill the Views card bottom row from the chart call for multi-day periods The chart's stats/visits call already returns visitors/likes/comments/posts per bucket, so request those fields and reuse the same response to populate the bottom row instead of a separate dedicated call — halving the card's network calls (2 instead of 4) for every period except single-day ones. Single-day periods (Today, single-day Custom) render an hourly chart whose response only carries views, so they keep fetching the bottom row from a dedicated day-level call, matching what the web app does. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Route Custom periods to the dedicated bottom call for correct visitor de-dup The Views card filled the bottom row from the chart response for every multi-day period. That over-counts unique Visitors for a Custom range beyond two years: the chart uses MONTH buckets, so a visitor active across several months is counted once per month, whereas the bottom row should de-duplicate per year. Views/Likes/Comments/Posts are additive and unaffected. Fill the bottom row from the chart only for the fixed periods (Last7Days/Last30Days/Last6Months/Last12Months), whose chart bucket already matches the unit the bottom row needs. Today and all Custom ranges now fetch the bottom row from the dedicated call, which coarsens to YEAR beyond two years so visitors are de-duplicated per year. This also drops the now-unreachable fixed-period branches from calculateBottomStatsRange (they no longer call it) and replaces isSingleDayPeriod with an exhaustive fillsBottomFromChart predicate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Coarsen the Custom chart to YEAR beyond two years to match the bottom row For a Custom range over two years the chart used MONTH buckets while the bottom-row totals coarsen to YEAR, so the header's Views (chart) and the bottom row's Views (dedicated call) covered different, misaligned windows and could disagree on the same card. Pass allowYear = true for the custom chart window too, so the chart and the bottom row share one unit (YEAR): their Views totals — and their per-year visitor de-duplication — now always agree. Shorter ranges (day/month) are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Count calendar buckets and fix the hourly window for the Today's card Three fixes from review of this branch. unitAndQuantityFor derived its quantity from ChronoUnit.MONTHS/YEARS.between, which count whole units elapsed between the endpoints rather than the calendar buckets the window spans. The API returns `quantity` buckets ending at the bucket holding the end date, so whenever the end's day-of-month fell before the start's, the window's first bucket was silently dropped: Jan 15..Mar 5 elapses one whole month but spans three, so the chart and the bottom row both fetched Feb+Mar and lost January. Count spanned buckets instead. Both the chart and the bottom-row range share this function, so they kept agreeing with each other while under-counting; they now agree on the right total. fetchHourlyViews still applied the "endDate is exclusive for hourly queries" workaround that a9ac20a disproved, leaving the Today's Stats card with the same off-by-one hour the Views card just fixed: it asked for the next day at 00:00, dropping the day's own 00:00 bucket in favour of the following day's. Route it through formatApiEndDate so both callers model the API identically. Finally, fetchBottomStats's KDoc still described the routing as it stood at 80551d5, before 5bd3e0e sent every Custom range to the dedicated call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fill the Views card bottom row from the chart for multi-day Custom ranges fillsBottomFromChart excluded every Custom range on the grounds that a range beyond two years needs yearly visitor de-duplication the chart's monthly buckets can't give. a4dc42f invalidated that: the custom chart window now coarsens to YEAR past two years, so for any multi-day Custom range the chart and the bottom row derive their unit, quantity and windows from the very same rules and issue byte-identical requests. Those periods were paying for two calls that duplicated the chart's own — the exact redundancy this branch set out to remove, on the one period that never got it. Route multi-day Custom through the chart response like the fixed periods, and keep only the single-day periods (Today, a Custom range whose start and end are the same day) on the dedicated call: their chart is hourly, and an hourly response populates `views` alone. This leaves calculateBottomStatsRange's coarser units unreachable from the card, since only single-day windows now reach it. The span-based rule stays anyway, so a caller that does need a standalone total for a longer window gets a correct one rather than a silently wrong bucket; the KDoc records that. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Send start_date for YEAR windows and give each window its own quantity A Custom range over two years renders every number on the Views card wrong -- chart, header total, % change and bottom row alike. For the range 2024-01-01..2026-06-29 the app already computed unit=year, quantity=3 and date=2026-06-29, identical to the web app, but omitted `start_date`: without it the API does not anchor its year buckets to the requested window. YEAR windows now send their own real start, matching web's unit=year&date=<end>&start_date=<start>&quantity=<n>. DAY and MONTH windows still send none. They are correct from unit + quantity + endDate, and a mid-bucket start_date there truncates the first bucket's views (additive) while leaving visitors (a per-bucket unique) at the full-bucket value. That asymmetry no longer splits the header from the bottom row -- both read one response now -- but it is still a reason not to send a start_date where nothing needs one. Sending start_date forces a second fix: a window's quantity and its start_date must describe the same window, and fetchStatsForPeriod sent the *current* window's quantity on the *previous* request. The previous window mirrors the current one's day span, which always resolves to the same unit but not always to the same bucket count -- 2023-12-31.. 2026-01-01 spans four years while its mirror spans three, so the API returned 2020-2023 and folded an extra year into the previous total. PeriodDateRange now carries a quantity per window, derived from that window's own span. Only Custom ranges coarsened to MONTH or YEAR change behaviour; every other period's two windows span equal buckets by construction, and tests pin start_date to null on the fixed periods so the YEAR rule cannot leak into paths that already work. Also drops the now-dead `allowYear` parameter and refreshes the KDocs the change falsified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Label YEAR chart buckets with the year instead of the month A Custom range over two years is charted in YEAR buckets, but its axis labels rendered as "Jan, Jan, Jan" and its legend as "Jan - Jun". The repository already picks StatsUnit.YEAR correctly and then dropped the value at buildPeriodStatsSuccess, so the ViewModel re-derived granularity from a day-count threshold that only distinguishes day from month: anything past 31 days got "MMM". The period string could not disambiguate either, since the API returns a full ISO date for DAY, MONTH and YEAR buckets alike. Carry the unit through PeriodStatsResult.Success so labels and the legend format from the granularity actually requested rather than guessing it a second time. This avoids duplicating the repository's two-year threshold into the ViewModel, which is how the two sides drifted apart to begin with. The period string still decides how to parse a bucket, as the API returns both "yyyy-MM" and "yyyy-MM-dd" shapes. DAY, MONTH and HOUR output is unchanged; only YEAR differs. Adds the first coverage for chart labels, including locale-independent locks that the year pattern cannot leak into the other units. Drill-down still makes the same day-count guess, so tapping a year bar opens that January. Left as a follow-up: it changes an interaction. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Simplify Views stats card cleanup and satisfy detekt Reuse ShimmerBox for the loading placeholders, dedup the previous-window mirror math, collapse the copy-paste bottom-stats aggregate mapping, and drop the redundant type-check in onChartTypeChanged. Convert formatDataPointLabel to an expression body to stay under the ReturnCount limit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 49e53b5 commit a2047ac

5 files changed

Lines changed: 856 additions & 245 deletions

File tree

0 commit comments

Comments
 (0)