Skip to content

Android: Sleep screen — Hours vs Needed and Sleep Consistency analytics cards#258

Closed
ujix wants to merge 2 commits into
NoopApp:mainfrom
ujix:android/sleep-analytics-cards
Closed

Android: Sleep screen — Hours vs Needed and Sleep Consistency analytics cards#258
ujix wants to merge 2 commits into
NoopApp:mainfrom
ujix:android/sleep-analytics-cards

Conversation

@ujix

@ujix ujix commented Jun 13, 2026

Copy link
Copy Markdown

What this PR does

Executive summary: Adds two new analytics cards to the Sleep screen — "Hours vs Needed" with a component breakdown bar, and "Sleep Consistency" with a Canvas-drawn nightly bar chart.

Details:

Sleep screen — analytics cards

  • Added: "Hours vs Needed" card — score %, trend arrow, gradient progress bar, stacked Healthy/Strain/Debt component bar, slept/needed/debt footer row
  • Added: "Sleep Consistency" card — Canvas-drawn vertical bar chart with bed-time at top / wake-time at bottom, Y-axis time labels, X-axis day labels, dashed typical overlay lines (typical bed and wake times)
  • Fixed: Consistency score now counts nights where both bed and wake fall within 45 min of the user's typical times; the previous SD-based formula always returned 0 %
  • Fixed: Consistency card Y-axis orientation flipped to match natural night flow (early evening → morning, top-to-bottom)
  • Fixed: typicalBed / typicalWake declared before the consistentNights count block that references them (was a forward-reference compile error)

Validation: :app:assembleFullDebug, testFullDebugUnitTest, and testDemoDebugUnitTest all green.

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • CI / tooling

How it was tested

Android 16. Real Samsung device. WHOOP 4.0. Tested: consistency card with real multi-night data, score correctly increments when within 45-min window, Hours vs Needed bar reflects actual debt/surplus, component bar proportions sum correctly.

Checklist

  • Swift package tests pass for any package I touched (swift test in Packages/<name>)
  • Android unit tests pass if I touched android/ (./gradlew testFullDebugUnitTest)
  • No new build warnings introduced
  • UI changes use only StrandDesign tokens — no hardcoded colors, fonts, or spacing
  • No hardcoded hex frame bytes; protocol facts live in the schema / decoders
  • Follows the conventions in docs/CONTRIBUTING.md
  • I did not commit generated output (Strand.xcodeproj/) or any secrets/keystores

Related issues

…ckerDialog

Redesigns NightNavHeader to match DayNavBar: left/right chevrons flanking
an accent-tinted center block showing the night label and date. The time
range moves to a separate row below. Tapping the block opens a
DatePickerDialog to jump to any recorded night by calendar date.

Also fixes nightOffset reset: moves it into LaunchedEffect(days) so it only
resets on a real sync/import, not on every optimistic sleeps update.
@NoopApp

NoopApp commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Solid analytics cards — the Hours-vs-Needed breakdown and the Consistency bedtime/wake scatter both have correct math. Two things before this could land on its own:

  1. The Consistency chart uses a hardcoded android.graphics.Color.argb(140, 200, 200, 200) Paint (~line 397) — NOOP requires Palette tokens, no hardcoded colors anywhere.
  2. There are ~280 lines of SleepMetricDetailScreen / SleepMetricDetailSheetContent defined but never called — dead code to remove.

More importantly: this is an intermediate rung of your Sleep series — #260 re-adds these same two cards in their final form alongside the bed/wake editing. To avoid reviewing the same cards three times, we're resolving the whole Sleep-screen direction via #260. If we decide we want the cards without the editing, we'll fix-and-ship this one instead. Holding open pending that call — thank you.

… card

HoursVsNeededCard: score %, trend arrow, gradient progress bar, stacked
component bar (Healthy / Strain / Debt), slept/needed/debt footer.

SleepConsistencyCard: Canvas vertical bar chart (bed-time top, wake-time
bottom), dashed typical overlay lines, Y-axis time labels, X-axis day
labels. Score is count-based (nights where both bed and wake are within 45
min of the user's typical); the previous SD formula always returned 0 %.
@ujix ujix force-pushed the android/sleep-analytics-cards branch from 627cf96 to 191fd1e Compare June 13, 2026 14:59
@ujix

ujix commented Jun 13, 2026

Copy link
Copy Markdown
Author

Both issues addressed:

  • Hardcoded color: replaced android.graphics.Color.argb(140, 200, 200, 200) with Palette.textTertiary.toArgb() on the Consistency chart Y-axis labels.
  • Dead code: removed both SleepMetricDetailScreen and SleepMetricDetailSheetContent — neither is called from this PR. SleepMetricDetailSheetContent has been moved to Android: Sleep screen — metric detail ModalBottomSheet #259 where it's actually used.

Branch updated and force-pushed.

@NoopApp

NoopApp commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Thanks — the Palette.textTertiary.toArgb() swap and removing the dead SleepMetricDetailScreen/SheetContent both look right. To set expectations: these two cards land in their final form via #260 (which re-adds them alongside the bed/wake editing), so we're still resolving the whole Sleep-screen direction as one decision on #260 rather than merging the intermediate rungs — your fixes here carry forward into that. Keeping open pending the #260 call.

@NoopApp

NoopApp commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Superseded — the Hours-vs-Needed + Consistency cards shipped in v2.9.0 as part of the combined Sleep update (#260). Thanks @ujix! Closing.

@NoopApp NoopApp closed this Jun 13, 2026
@ujix ujix deleted the android/sleep-analytics-cards branch June 14, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants