feat(app): declutter Home — Activity bell, pending row in Today, On the Way page

Merged
GI
2d ago
+3974-936

What changed and why

Home was cluttered: an empty "Recent Changes" row and a full-width sync pipeline card sat above the fold, and a big backlog read as alarming. This PR keeps Home to what matters:

  • Activity bell in the Home header, always present. Its dot lights only for delight: a daily recap newer than the last visit. Chores never light it. Opening or leaving Activity marks everything seen; there is no "mark all read".
  • Activity page (mobile counterpart of desktop's Activity): recaps and the changes Omi made on its own (Recent Changes), newest first and grouped by day, with links to the full Recent Changes and, for its cohort, Dream Report. Questions stay in Review and are not shown here.
  • Review card on Home shows only when questions are waiting. With none, it draws nothing (it used to be a "Recent Changes" row).
  • Pending row in Today replaces the Offline Sync pipeline card (ConversationProcessingCard, removed). It reads "Conversations on the way", or "Catching up on earlier audio" once 30+ minutes are pending, with the current step as a subtitle and no amounts. It opens On the Way: pending recordings grouped by how close they are to done, plus a Sync details row to the existing Offline Sync page. Refused recordings ("N need attention") moved there, off Home.

Eight new strings, added through scripts/l10n.py in all 49 locales.

Product invariants affected

none (check_product_invariants.py --suggest on this diff)

How it was verified

  • flutter analyze on the touched dirs: no issues.

  • flutter test test/pages/activity test/widgets/home_pending_row_test.dart test/pages/review test/visual_audit: all pass, including the visual-audit smoke test, which pumps every registered scenario.

  • Real renders via the visual-audit harness (production widgets, synthetic data; Android platform; a temporary Roboto font patch so null-family text renders, reverted). See UI evidence below.

  • Codex Luna (gpt-6-luna, read-only) reviewed the first commit: no P0 or P1 findings. All five P2s are fixed in the second commit (empty-first-load bell baseline, date filter excluding today, partial-failure retry, screen-reader tap actions, single-pass backlog check).

  • The Codex GitHub review left one P1 and five P2s, all fixed in a later commit: On the Way never claims "all synced" while recordings need attention, a source-neutral Activity error, per-source rows kept on partial refresh, recap deletion propagated from Activity to Home, "New" announced to screen readers, and a header device pill that compacts on narrow screens.

Tests

  • app/test/widgets/home_pending_row_test.dart (replaces conversation_processing_card_test.dart) covers visibility rules (terminal-only and local-only recordings hide the row), catching-up copy with no amount, live step, post-sync fetch, cooldown copy, the Today header in a sliver mount, the date filter, semantics tap action, routing to On the Way, stage grouping, device-twin dedupe, fragment grouping, the attention line, the Sync Details route, and the storage-less v2 gate.
  • app/test/pages/activity/activity_test.dart covers the bell baseline (including an empty first load), lighting and clearing the dot, ordering, the new-dot only on delight, auto-seen on open, 404 vs real failure, the empty state, and semantics.
  • app/test/pages/review/review_widgets_test.dart: the entry card hides when caught up.
  • Visual audit: home-offline-processing, home-offline-processing-ready, on-the-way, activity.

UI evidence

Home pending row
Home catching up, bell dot
On the Way
Activity

The ā–Æ glyphs are emoji the test renderer has no font for, and the spinner is a frozen frame.

Failure class (fixes)

Failure-Class: none

šŸ¤– Generated with Claude Code