fix(dashboard): gate the workouts + recovery surfaces by module

The dashboard's recent-workouts and steps tiles painted regardless of
the workouts module state; AND the resolved per-account flag into both
gates (fail-open — only an explicit false hides the tile).

Extend the snapshot module maps to cover the recovery domain: the
cardioRecovery / sixMinuteWalk / stairAscentSpeed / stairDescentSpeed
widgets and their HealthKit measurement types now resolve to the
recovery module, and the per-night breathing-disturbance widget + type
resolve to sleep. A new guard test asserts every toggleable-domain
widget id carries a mapping and every mapped value is a real module
key, so a future device widget cannot leak onto a disabled account.
This commit is contained in:
Marc-André Bombeck committed 2026-06-16 02:05:37 +02:00
1 parent a524cad4c4
commit f966ae884a
3 files changed
+90 -4

No files matched your search

+8 -2
View File
@@ -523,7 +523,11 @@ export default function DashboardPage() {
const showBodyFatTile = isTileVisible("bodyFat") && hasBodyFat;
const showMoodTile = isTileVisible("mood") && hasMood;
const showSleepTile = isTileVisible("sleep") && hasSleep;
const showStepsTile = isTileVisible("steps") && hasSteps;
// v1.18.0 B1 — steps are activity data tied to the workouts module
// surface; AND the resolved module flag (fail-open: only an explicit
// `false` hides it) so a disabled-workouts account drops the tile.
const showStepsTile =
isTileVisible("steps") && hasSteps && user?.modules?.workouts !== false;
const showVo2Tile = isTileVisible("vo2Max") && hasVo2;
const showBpInTargetTile = isTileVisible("bpInTarget") && hasBpInTarget;
@@ -559,7 +563,9 @@ export default function DashboardPage() {
// no data floor, so it would otherwise flash in then retract for a user
// who hid it.
const showRecentWorkoutsTile =
layoutResolved && isChartVisible("recentWorkouts");
layoutResolved &&
isChartVisible("recentWorkouts") &&
user?.modules?.workouts !== false;
// v1.16.0 — shared reveal gate for the chart row. Every data-backed
// chart mounts as soon as its visibility gate flips (so the per-chart