You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Today: Latest Workouts shows a different window, cap, and header claim on each platform #1702
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
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.
Which cap? 4 or 6 — cosmetic once the window agrees.
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.
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.
Activity
today: open a session's detail from the Latest Workouts feed (#1701)
today: window the iOS Latest Workouts feed to the same 14 days as And…
ryanbr commentedon Aug 28, 2026
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 —
recentUnionfor the feed, separate all-time queries for the Data Sources counts. iOS has oneworkoutsarray 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
workoutsat 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.