Android: interactive charts, Sleep overhaul, Explore redesign, axis labels, battery/streak strip, live-HR notification sparkline#210
Android: interactive charts, Sleep overhaul, Explore redesign, axis labels, battery/streak strip, live-HR notification sparkline#210ujix wants to merge 8 commits into
Conversation
…ication sparkline Enables chart tap/swipe interaction on three more screens, replaces the unbounded Intelligence day list with a windowed range picker, and draws a real-time HR line into the foreground-service notification. - Enable selectionEnabled on LineChart in TodayScreen (HeartRateTrendCard), StressScreen (StressTrendSection), and TrendsExploreScreen (HeroChartCard) so users can tap/drag to read exact values — matching the existing Trends behaviour - Add W / M / 3M / 6M / 1Y / ALL SegmentedPillControl to Intelligence "By Day" section; list is filtered to the chosen window (defaults to M), with a day-count footnote and an empty-window nudge card - Accumulate rolling 60-sample HR history in WhoopConnectionService and render it as a Bitmap sparkline (800×200, accent fill + stroke on dark background) attached via NotificationCompat.BigPictureStyle so the expanded notification shows an HR trend instead of just a number Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…charts Adds morning journal prompt, sleep-time editing, two new sleep analytics cards, an improved day selector, battery/streak status strip, HR chart axes, and a dropdown metric picker in Explore. - Sleep: pen icon below the night clock label opens sequential bedtime → wake TimePickerDialogs; times are persisted via delete+upsert so the Room PK constraint is preserved (WhoopDao.deleteSleepSession + repo updateSleepSessionTimes + AppViewModel method) - Sleep: morning journal prompt — ModalBottomSheet fires once per day when the latest sleep session ended within 12 hours; tapping "Open Journal" navigates to InsightsScreen (gated by NoopPrefs key KEY_LAST_JOURNAL_PROMPT so it never re-fires the same day) - Sleep: new "Hours vs Needed" card — score %, trend arrow, gradient progress bar, stacked Healthy-Min/Strain/Debt component bar, footer with slept/needed/debt values - Sleep: new "Sleep Consistency" card — score % from bedtime+waketime SD across the last 14 nights; Canvas-drawn vertical bar chart with Y-axis time labels (20:00/00:00/04:00/08:00/12:00), X-axis day labels, and dashed typical bed/wake overlay lines - Today: ThreeDaySelectorBar replaced by DayNavBar (StrandComponents) — left/right chevron + calendar icon that opens DatePickerDialog for any past date, accent-tinted center block - Today: HR chart now shows Y-axis min/max labels and an X-axis time row - Today: compact status strip (top-right of content) shows live strap battery % and total-nights streak with a fire icon (red ≥2 consecutive, gray otherwise) - Explore: horizontal chip row replaced by a grouped dropdown (ExposedDropdownMenuBox) with category headers and accent dot per metric
…design Refines data visualization and navigation across Today, Sleep, Explore, Trends, and Vital Signs pages to improve readability, consistency, and interactivity. - Today / DayNavBar: remove calendar icon; tapping the accent center block opens the date picker instead - Today / HeartRateTrendCard: fix X-axis time labels (correct HH:MM format, midpoint interpolated); add avg as middle Y-axis label - Sleep / NightNavHeader: redesign to match DayNavBar style — accent center block hosts night label, sleep/wake times, and inline edit pen; tapping opens date picker - Sleep / MetricGrid: make all SparkTile cards clickable; each opens a new SleepMetricDetailScreen - Sleep / SleepMetricDetailScreen: new screen mirroring VitalDetailScreen — W/M/3M/6M/1Y/ALL range filter, Y-axis (max/avg/min), X-axis date labels, min/avg/max footer - Sleep / SleepConsistencyCard: redesign header (overline + title + subtitle + score); extend Y range to 14 h; clamp bar coordinates to prevent overflow; add SCORE / TYPICAL / NIGHTS footer stats - Explore / MetricDropdown: full redesign using ExposedDropdownMenuBox — category headers with accent dot, selected-item checkmark, dividers between groups - Explore + Trends + Vital Signs: add Y-axis (max/avg/min) and X-axis (date labels) to all line charts
…etric bottom sheet Refines the Sleep page's night navigation, sleep schedule chart, and metric detail UX. - NightNavHeader: move sleep/wake time + edit pen below the accent nav block (cleaner, less crowded center block) - SleepConsistencyCard: flip chart Y-axis so bedtime is at the top and wake time progresses downward, matching natural sleep-night flow - SleepConsistencyCard: fix consistency score — now counts nights where both bed and wake time are within 45 min of typical (was always 0% due to strict SD threshold) - Night detail tiles: tapping any SparkTile now slides up a ModalBottomSheet with the metric history chart, range selector, and min/avg/max footer instead of navigating to a separate screen
…ime edit, live update
- NightNavHeader: split clock label — date ("Wed 4 Jun") shown inside the accent center block below the night label; only the time range ("22:50–06:48") shown below with the edit icon
- Time edit: replaced the sequential auto-open Bedtime→Wake-up pickers with a Strand-styled AlertDialog letting the user choose which time to edit (Bedtime or Wake-up); each opens its own TimePickerDialog independently
- Immediate reflection: `onUpdateTimes` now does an optimistic in-memory update of the `sleeps` list so the header clock re-renders instantly without waiting for a DB round-trip
- Fix navigation reset: nightOffset no longer snaps to 0 on every optimistic update (LaunchedEffect key moved from sleeps to days), so the user stays on the edited night - Fix stale/duplicate data: reload sleeps from DB after the write completes, eliminating any computed sessions overlapping the edited night - updateSleepSessionTimes is now suspend so the reload waits for the write before querying (removes race condition) - Stage breakdown in-bed duration now derives from session endTs-startTs so it reflects edits immediately - Time-edit dialog: 14dp/16dp padding, headline-size time text, surfaceOverlay background for comfortable touch targets
After editing sleep/wake times the sleeps list was reloaded from DB and re-sorted by startTs. If the new startTs sorted the session to a different index, nightOffset (unchanged) pointed to the wrong session; if that session had no DailyMetric data the entire night appeared to vanish. The reload was added to prevent phantom computed sessions, but there are no actual duplicates: the repository delete+upsert is correct. The original navigation bug (old data on previous day) was already fixed by moving the nightOffset reset into LaunchedEffect(days). The reload was unnecessary, so remove it and keep only optimistic update + fire-and-forget.
buildSleepModel now derives a sessionDurationMin from the session's endTs-startTs whenever the session matches the selected night. A metricsWindow replaces that night's totalSleepMin with the session-based value so performance, hoursVsNeeded, sleepDebt, and the trend chart all reflect the edited window immediately after an optimistic update. typicalTotalMin intentionally keeps the unmodified windowDays so the personal baseline mean is not skewed by a single edited night.
|
Beautiful work, @ujix — this is a lot of thoughtful Android polish. I've taken the chart-axis subset into v2.8.0 (the Today + Trends time/value axis labels, reimplemented under the project identity, credited to you). The bigger pieces — the Sleep night-browsing overhaul, the Explore dropdown redesign, the battery/streak strip and the interactive-drag charts — are each substantial enough that I'd rather land them deliberately than fold them into a mixed release. If you're up for it, a focused follow-up PR on (say) just the Sleep overhaul would be very welcome and I'll prioritise reviewing it. Thank you — genuinely strong contribution. 🙏 |
|
Thanks so much for the kind words and for landing the axis-label work — really appreciate it! We've gone ahead and split everything into dedicated focused PRs as you suggested:
Each one is a single-concern commit rebased onto current main, green on |
|
Thank you — this is exactly the right way to split it, and it made the review dramatically cleaner. I've gone through every one of the focused PRs:
One thing from this PR's title I didn't see carried into the split: the live-HR notification sparkline. If you'd like that considered, a focused PR for it would be welcome. On mechanics: we re-land contributions under the project account (keeps commit authorship uniform and lands the iOS/macOS hand-ports in lockstep), so you'll see adopted PRs close as "adopted" with credit rather than via merge — the work absolutely ships either way. Really appreciate both the volume and the quality here. |
Android: interactive charts, Sleep overhaul, Explore redesign, axis labels, battery/streak strip, live-HR notification sparkline
What this PR does
Executive summary: A broad Android UX pass covering interactive chart inspection across all screens, a fully redesigned Sleep page with night-by-night browsing and in-app time editing, Y/X axis labels on every line chart, a redesigned Explore metric picker, a live HR sparkline in the foreground notification, and a battery/streak status strip on Today.
Details:
Charts & data visualization
selectionEnabledon everyLineChartacross Today (HeartRateTrendCard), Sleep (metric detail), Stress (StressTrendSection), Trends (HeroChartCard), Explore, and Vital Signs — users can tap or smoothly drag to read exact values on any trendHeartRateTrendCardX-axis: labels now show correctHH:mmwall-clock times with an interpolated midpoint; Y-axis shows avg as the middle labelToday screen
ThreeDaySelectorBarreplaced withDayNavBar— left/right chevrons flanking an accent-tinted center block; tapping the block opens aDatePickerDialogfor any past dateSleep screen — night browsing
◀ / ▶chevron navigation walks every recorded sleep block (including naps); aDatePickerDialogjumps to any night by calendar dateDayNavBarstyle — accent center block shows the night label ("Last night") and the date ("Wed 4 Jun"); the time range ("22:50–06:48") sits below with an edit iconnightOffsetno longer resets to 0 on optimistic state updates — it only resets on a real sync or import (LaunchedEffect(days)), so the user stays on the night they navigated toSleep screen — time editing
AlertDialogwith two rows (Bedtime / Wake-up), each showing the current time and an accent edit icon; choosing one opens its own independentTimePickerDialogsleepsupdate; no DB round-trip waitsession.endTs − session.startTsso it reflects the edited window instantlybuildSleepModelnow builds ametricsWindowthat substitutessessionDurationMinfor the selected night'stotalSleepMin, while keepingtypicalTotalMinfrom the unmodified historical windowSleep screen — analytics cards
Sleep screen — metric detail
ModalBottomSheet(W/M/3M/6M/1Y/ALL range selector, Y-axis, line chart, X-axis dates, min/avg/max footer) instead of pushing a new screenExplore screen
ExposedDropdownMenuBoxwith category headers, accent dot per metric, selected-item checkmark, and dividers between groups — replaces the horizontal chip rowNotification
Bitmapsparkline (800×200, accent fill + stroke on dark background) attached viaNotificationCompat.BigPictureStyle; expanded notification shows an HR trend instead of just a numberIntelligence screen
SegmentedPillControlto the "By Day" section; list is filtered to the chosen window (defaults to M) with a day-count footnote and an empty-window nudge cardBug fixes
String?vsStringcompile errors inHealthScreen.ktandTrendsScreen.ktx-axis date label paths (.getOrNull()returningString?passed toLocalDate.parse(String))SleepConsistencyCard—typicalBed/typicalWakedeclared after the block that referenced them; moved before theconsistentNightscountValidation:
:app:assembleFullDebug,testFullDebugUnitTest, andtestDemoDebugUnitTestall green after every commit.Type of change
How it was tested
Android 16. Real Samsung device. WHOOP 4.0. Tested: night navigation and date-jump picker, time editing (bed and wake independently), navigation position preservation after editing, metric tile bottom sheets, consistency card with real multi-night data, HR sparkline in expanded notification, all chart drag interactions, Explore dropdown, Intelligence range filter, Today battery/streak strip.
Checklist
swift testinPackages/<name>)android/(./gradlew testFullDebugUnitTest)StrandDesigntokens — no hardcoded colors, fonts, or spacingdocs/CONTRIBUTING.mdStrand.xcodeproj/) or any secrets/keystoresRelated issues