Skip to content

Today: Latest Workouts shows a different window, cap, and header claim on each platform #1702

Closed

Description

@ryanbr

Noticed while making the feed's tiles tappable in #1701. That PR deliberately left this alone, because it is a behaviour question rather than a styling one and would have been hidden inside a feature change.

The two platforms render the same "Latest Workouts" section from different data, with different caps, and with trailing headers that make different claims.

Android iOS
Data window last 14 days (recentCutoff = today − 13, TodayScreen.kt) repo.workoutRows() → days: Int = 4000, effectively all-time
Tiles shown 4 (lastWorkoutsFeed(...).take(4)) 6 (workouts.prefix(6))
Trailing header "14 days" — describes the window "\(workouts.count) total" — counts all-time workouts, not what is shown
When nothing is recent section disappears (if (feed.isEmpty()) return) section still shows, listing sessions of any age

Why this is more than a cap difference

Take a user who last trained three months ago.

  • Android shows no Latest Workouts section at all.
  • iOS shows six sessions from three months ago under a heading that says "Latest", with a trailing count of their entire history.

So the same account reads as "no recent activity" on one platform and "here is your recent activity" on the other. Both are defensible in isolation; together they are a parity break, and the iOS trailing count is arguably misleading on its own — "N total" counts every workout ever recorded while the list is capped at six.

What to decide

  1. Which window is right? Android's 14 days matches the section's own header and the word "Latest". iOS's all-time never leaves the user with an empty space. These are genuinely different product calls, which is why this is an issue rather than a patch.
  2. Which cap? 4 or 6 — cosmetic once the window agrees.
  3. What should the trailing text say? It should describe the same thing on both. If the window becomes the contract, "14 days" works on both; if the cap becomes the contract, the count should reflect what the window holds rather than all-time.

Whatever is chosen, lastWorkoutsFeed on Android already has a test (LastWorkoutsFeedTest), so the contract has somewhere to be pinned, and TodayWorkoutTapTest (added in #1701) is the natural place for a cross-platform assertion.

No user has reported this — I found it by reading both sides while implementing #1694, so treat the priority accordingly.

Activity

  1. ryanbr commented on Aug 28, 2026

    @ryanbr
    OwnerAuthor

    Settled in #1703: iOS now windows to the same 14 days as Android, and the trailing header describes the window on both instead of counting every workout ever recorded.

    Two things worth recording from the implementation.

    iOS's all-time behaviour was not a product decision. Android keeps two sets — recentUnion for the feed, separate all-time queries for the Data Sources counts. iOS has one workouts array serving both, and the section simply used what was already there. So there was no intent to reverse, which is why matching Android was the right way round.

    The obvious fix was a trap. Windowing workouts at its source compiles and looks correct, and would have silently shrunk two unrelated numbers on the same screen: the Data Sources "Apple Health · N workouts" count and the HR chart's sport glyphs, both all-time by design. The window is applied at the section instead, and a parity assertion in ordinary CI now checks that count still reads the unwindowed array — guarded, rather than avoided once.

    Tile caps stay 4 (Android) and 6 (iOS) deliberately. That part of this issue is layout, not content: Android is single-column full-width on purpose (the 2×2 grid truncated durations on narrow phones, #332), iOS uses an adaptive grid. Same vertical budget, and unifying it would change one platform's density for no reader benefit. Leaving that as the only remaining difference.

    One behavioural change to be aware of on iOS: the section now disappears when you have not trained in two weeks, as it already did on Android.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions