feat(room): read a message aloud via browser speech synthesis (LC-528) #500

Merged
longjacksonle merged 1 commit from longjacksonle/feat/LC-528-read-aloud-messages into main 2026-07-03 01:54:53 +02:00 AGit

Adds a "Read aloud" item to the message overflow menu that speaks the message's rendered text using the browser SpeechSynthesis API. Entirely client-side: no route, no DB, no LLM. Clicking again (or reading another message) stops; the label toggles to "Stop reading" while speaking. The utterance uses the page's resolved locale as its lang.

The item only renders for messages with a text body, and is CSS-hidden (.lc-no-tts on <html>, set once by live.js) when the browser has no speech synthesis, so it never fails silently on click. A delegated handler in live.js covers live-swapped message fragments, and speech is stopped when the message being read leaves the DOM (delete, room switch, reconnect soft-refresh) or the page is navigated away.

Reuses the existing overflow-menu partial, the live.js delegated-listener pattern, and the CSS ancestor-gate approach used for the LC-486 translate item. New i18n keys room-msg-read-aloud / room-msg-stop-reading added to en + es catalogs.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01NTRhc4n7A2uB2Y5PHV2ewL

Adds a "Read aloud" item to the message overflow menu that speaks the message's rendered text using the browser SpeechSynthesis API. Entirely client-side: no route, no DB, no LLM. Clicking again (or reading another message) stops; the label toggles to "Stop reading" while speaking. The utterance uses the page's resolved locale as its `lang`. The item only renders for messages with a text body, and is CSS-hidden (`.lc-no-tts` on `<html>`, set once by live.js) when the browser has no speech synthesis, so it never fails silently on click. A delegated handler in live.js covers live-swapped message fragments, and speech is stopped when the message being read leaves the DOM (delete, room switch, reconnect soft-refresh) or the page is navigated away. Reuses the existing overflow-menu partial, the live.js delegated-listener pattern, and the CSS ancestor-gate approach used for the LC-486 translate item. New i18n keys room-msg-read-aloud / room-msg-stop-reading added to en + es catalogs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTRhc4n7A2uB2Y5PHV2ewL
feat(room): read a message aloud via browser speech synthesis (LC-528)
All checks were successful
check-secrets / Kingfisher (pull_request) Successful in 9s
check-secrets / Nosey parker (pull_request) Successful in 9s
check-secrets / TruffleHog (pull_request) Successful in 10s
Check / clippy + fmt + tests (pull_request) Successful in 6m26s
Create release / Create release from merged PR (pull_request) Has been skipped
0189663cea
Adds a "Read aloud" item to the message overflow menu that speaks the message's rendered text using the browser SpeechSynthesis API. Entirely client-side: no route, no DB, no LLM. Clicking again (or reading another message) stops; the label toggles to "Stop reading" while speaking. The utterance uses the page's resolved locale as its `lang`.

The item only renders for messages with a text body, and is CSS-hidden (`.lc-no-tts` on `<html>`, set once by live.js) when the browser has no speech synthesis, so it never fails silently on click. A delegated handler in live.js covers live-swapped message fragments, and speech is stopped when the message being read leaves the DOM (delete, room switch, reconnect soft-refresh) or the page is navigated away.

Reuses the existing overflow-menu partial, the live.js delegated-listener pattern, and the CSS ancestor-gate approach used for the LC-486 translate item. New i18n keys room-msg-read-aloud / room-msg-stop-reading added to en + es catalogs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTRhc4n7A2uB2Y5PHV2ewL
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-07-03 01:49:54 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!500
No description provided.