Skip to content

Daily audio lesson: fresh lesson waiting, just listen (Listen redesign)#1149

Merged
mircealungu merged 15 commits into
masterfrom
daily-audio-lesson-delivery
May 27, 2026
Merged

Daily audio lesson: fresh lesson waiting, just listen (Listen redesign)#1149
mircealungu merged 15 commits into
masterfrom
daily-audio-lesson-delivery

Conversation

@mircealungu
Copy link
Copy Markdown
Member

Reworks the Listen tab from a vending machine (pick type + topic + tap Generate every day) into a daily delivery: the user configures a daily lesson once and finds a fresh one waiting each day — they just open and listen. Backend (preference keys + nightly pre-generation) is a separate PR in zeeguu/api.

The Today view (new state machine in TodayAudio.js)

  • Setup CTA — first run, no preference: prompt to choose the daily lesson.
  • Episode card (TodayEpisodeCard) — lesson ready, instant play. Design-B header: TODAY · date, type chip, title, 🎧 4 min · subject · N words, then a "fresh lesson every morning · Change daily topic" footer. Wraps the reused LessonPlaybackView (now takes header/footer props) so the player/words/feedback are unchanged.
  • Auto-generate — configured but no lesson today (first day / cron miss / timezone): kicks off generation reusing the existing streaming-progress UI.
  • Listened — done-for-today messaging + replay.

The inline type picker and the orange Generate Lesson button are gone from the main flow.

Supporting changes

  • DailyLessonSettingsDialog — the type/topic config moved into a dialog opened by Change daily topic. Primary action saves the preference and regenerates today's lesson now (delete + generate); secondary Save for tomorrow persists without regenerating. Also the first-run setup surface.
  • useDailyLessonPreference — per-language preference, server as source of truth (drives the cron + cross-device).
  • SuggestionSelector — now a pure controlled component (localStorage removed).
  • PastLessons — type filter chips (All / Vocabulary / Topic / Situation); shared lessonTypeChip module (extracted from PastLessons).
  • Router: dead setShowTabs plumbing removed.

Notes

  • Depends on zeeguu/api PR (the preference keys). Works fully on demand without the cron.
  • New UI copy is inline English to match the existing dailyAudio/ convention (no definitions.js keys added).
  • vite build passes against master.
  • Open: rollout gating — ship ungated, or gate the new Today render behind the existing userDetails.name === "Mircea" check for first device testing? Not assumed here.

🤖 Generated with Claude Code

Reworks the Listen tab from a vending machine (pick type + topic + tap
Generate every day) into a daily delivery: the user configures a daily
lesson once and finds a fresh one waiting each day.

- TodayAudio: new state machine — setup CTA (no preference) -> episode card
  (lesson ready, instant play) -> auto-generate via the existing streaming
  progress UI (first day / cron miss) -> listened/replay. Removes the inline
  type picker + orange Generate button from the main flow.
- DailyLessonSettingsDialog: type/topic config moved into a dialog opened by
  'Change daily topic'; saves the preference and regenerates today's lesson
  on demand (or 'save for tomorrow').
- TodayEpisodeCard: Design-B header (TODAY . date, type chip, title,
  duration . subject . word count) wrapping the reused LessonPlaybackView
  (now takes header/footer props).
- useDailyLessonPreference: per-language preference, server as source of truth.
- SuggestionSelector: now a pure controlled component (no localStorage).
- PastLessons: type filter chips; shared lessonTypeChip module.

Depends on the backend preference keys in zeeguu/api (separate PR).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented May 27, 2026

Deploy Preview for voluble-nougat-015dd1 ready!

Name Link
🔨 Latest commit 2c4d5a8
🔍 Latest deploy log https://app.netlify.com/projects/voluble-nougat-015dd1/deploys/6a170e292f22b00008389e96
😎 Deploy Preview https://deploy-preview-1149--voluble-nougat-015dd1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

- Onboarding: clearer 'set up once, a new lesson daily, starting today' copy
  on the setup CTA and the settings dialog.
- Episode card: type chip + subject under the title (no headphones, no
  duration — the player shows time); dropped redundant 'Today .' and the
  'See past lessons' link; one check per listen (shared completionChecks,
  bumped live on replay); recurrence promise moved into the dialog.
- Share/Feedback actions now sit below the config pill; 'Change your daily
  lesson type' rendered as a theme-aware config pill (light + dark).
- Dialog reads as a real modal: darker+blurred backdrop, border + shadow,
  orange title, narrower; light-mode safe.
- Notification dot only shows for a ready/generating lesson, not the
  persistent 'available' state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mircealungu
Copy link
Copy Markdown
Member Author

@AnnieeBennie I've started on the idea we talked about yesterday — automatically generating a new lesson for people every day. Instead of tapping Generate each day, you set up your daily lesson once (type + topic) and a fresh one is waiting for you daily: pre-generated overnight, generated on demand the first day / if the cron misses.

This PR is the UX (the new Listen "episode card", setup + change-topic dialog, past-lesson filters). The backend half — per-user preference + the nightly pre-generation job — is in zeeguu/api#641, and the cron schedule in mircealungu/zeeguu-ops#5.

Would love your thoughts on the flow and the copy. 🙂

mircealungu and others added 12 commits May 27, 2026 14:03
…orrow prompt

- Episode card: the type chip now flows inline at the start of the subject
  line instead of sitting on its own row.
- Settings dialog: primary button is now 'Save settings'. Saving a *changed*
  setting while today's lesson already exists asks whether to regenerate
  today's lesson or start from tomorrow; otherwise it just saves (generating
  immediately only when there's no lesson for today yet).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Chip and subject now sit in separate flex columns (no wrap) so the subject
wraps within its own column instead of flowing back under the chip, while
still sharing the first line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rop redundant subtitle

The per-type description in the selector already explains each option.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ies change)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…idth pill

'Settings' over 'type'/'config' — clearest for a non-technical learner. Pill
hugs its content again instead of stretching to a bar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…essons

Subject now lives inside the colored chip (e.g. 'Situation: cafe') like the
past-lessons category headers — consistent, and the subject wraps inside the
pill instead of under it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… type/subject

- Share moved to a centered link directly under the player (like past lessons);
  the faint bottom row is now just Feedback / Delete.
- Settings dialog seeds from the saved preference, falling back to today's
  lesson's type + subject when no preference is stored yet, so the learner's
  current choice is always pre-selected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Extract the history's Share into a shared ShareLessonButton used by both the
  episode card and the past-lessons list. CustomAudioPlayer gains a children
  slot so the card renders Share *inside* the player box (same as history,
  where the card wraps a transparent player + Share).
- Settings dialog: per-type subject so switching pills (or to Vocabulary and
  back) no longer wipes/bleeds Topic vs Situation text.
- Save settings stays disabled until something actually changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Correctness:
- TodayAudio: exhausted polling no longer leaves a permanent 'Preparing…'
  spinner — it marks the attempt done and shows a recoverable error; the
  spinner branch is gated on !autoGenAttemptedRef.
- TodayAudio: language switch mid-generation now tears down the stale
  poll/flag (lang effect resets isGenerating + generationProgress).
- handleConfigured: deleteTodaysLesson failure surfaces an error instead of
  silently regenerating (which returns the old lesson).
- startGeneration: 'not enough words' shows Topic/Situation guidance (restores
  the old feasibility hint the auto-gen path had dropped).
- PastLessons.onLessonCompleted bumps listened_count so replay checkmarks
  update live, matching the today card.
- DailyLessonSettingsDialog: reset confirmRegen when type/subject changes so
  the regenerate-or-tomorrow prompt can't strand or describe a stale choice.

Cleanup:
- Dedup the short-date formatter into audioUtils.formatShortDate (used by the
  card header and past-lessons rows).
- Drop the redundant 'words' prop; LessonPlaybackView derives it from lessonData.
- useDailyLessonPreference reports a failed save to Sentry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When generation is paused (last lesson < 50% listened), the backend returns
that waiting lesson flagged `paused`. The card then drops the date for a
'⏸ Paused' label and adds a one-line 'listen to resume' note.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mircealungu mircealungu merged commit a74bc2e into master May 27, 2026
4 checks passed
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.

1 participant