feat(voice): redesign voice-message composer UI (LC-499) #461

Merged
longjacksonle merged 4 commits from feat/LC-499-voice-composer-ui into main 2026-06-27 20:33:41 +02:00

What

Polish the voice-message composer UI (LC-499). The feature worked but both states were bare text. Pure frontend - Askama + HTMX + Tailwind + vanilla JS; no server/route/data changes.

Changes

Recording state - a styled card anchored above the input: pulsing red dot, prominent elapsed-time counter, a live mic-level meter driven by a Web Audio AnalyserNode (confirms the mic is actually capturing), and Stop (primary) + Cancel (subtle) as distinct buttons. The mic button itself now shows an obvious recording state (danger tint + ring) instead of just a color change.

Recorded-and-attached state - a playback preview that reuses the timeline .lc-voice player (play/pause + waveform + duration) so the user can listen before sending, plus a labeled Re-record action and a Remove (trash) button replacing the cryptic "x".

Edge states & feedback - styled, actionable: mic-permission denied (with how-to-fix help), unsupported browser, start-failed, empty recording, upload-in-progress (Send disabled + spinner), and upload error (clear message + Retry that re-sends the retained blob, no re-record needed).

Sent voice messages - confirmed the timeline already renders a proper player (partials/attachment.html + the layout voice player); no change needed.

How

  • composer.html voice IIFE rewritten: styled recording card, AnalyserNode level meter, preview via the shared player, progress/error/retry flow; Send held disabled during upload via a new __lcUploadBusy flag in the shared __lcRefreshSend predicate.
  • layout.html exposes window.__lcScanVoice so the composer can init the preview player it injects directly (no htmx swap fires for it).
  • main.css token-driven (light/dark) styles; honors prefers-reduced-motion.
  • New JS i18n strings in __lcI18n (en + es).

Tests

just check (fmt + clippy, both builds), just test, just test-saas all green. This is frontend-only; the authed composer can't be exercised headlessly in CI (SSO-only login), so it was verified by build/check/tests + code review against the reference mockups. just verify builds the release binary clean (boot blocked only by the missing SSO env, as in prior PRs).

## What Polish the voice-message composer UI (LC-499). The feature worked but both states were bare text. Pure frontend - Askama + HTMX + Tailwind + vanilla JS; no server/route/data changes. ## Changes **Recording state** - a styled card anchored above the input: pulsing red dot, prominent elapsed-time counter, a live mic-level meter driven by a Web Audio AnalyserNode (confirms the mic is actually capturing), and Stop (primary) + Cancel (subtle) as distinct buttons. The mic button itself now shows an obvious recording state (danger tint + ring) instead of just a color change. **Recorded-and-attached state** - a playback preview that reuses the timeline `.lc-voice` player (play/pause + waveform + duration) so the user can listen before sending, plus a labeled **Re-record** action and a **Remove** (trash) button replacing the cryptic "x". **Edge states & feedback** - styled, actionable: mic-permission denied (with how-to-fix help), unsupported browser, start-failed, empty recording, upload-in-progress (Send disabled + spinner), and upload error (clear message + Retry that re-sends the retained blob, no re-record needed). **Sent voice messages** - confirmed the timeline already renders a proper player (`partials/attachment.html` + the layout voice player); no change needed. ## How - `composer.html` voice IIFE rewritten: styled recording card, AnalyserNode level meter, preview via the shared player, progress/error/retry flow; Send held disabled during upload via a new `__lcUploadBusy` flag in the shared `__lcRefreshSend` predicate. - `layout.html` exposes `window.__lcScanVoice` so the composer can init the preview player it injects directly (no htmx swap fires for it). - `main.css` token-driven (light/dark) styles; honors `prefers-reduced-motion`. - New JS i18n strings in `__lcI18n` (en + es). ## Tests `just check` (fmt + clippy, both builds), `just test`, `just test-saas` all green. This is frontend-only; the authed composer can't be exercised headlessly in CI (SSO-only login), so it was verified by build/check/tests + code review against the reference mockups. `just verify` builds the release binary clean (boot blocked only by the missing SSO env, as in prior PRs).
New JS strings for the redesigned voice composer: mic-permission help text, re-record / remove / retry / play labels, an uploading label, and reworded recording/start-failed messages. Registered in __lcI18n (en + es).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The voice-player initializer was closed over in an IIFE and only ran on htmx swaps. Expose scan() as window.__lcScanVoice so the composer can wire a playback-preview player it injects directly (no htmx swap fires for it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Token-driven (light/dark) styles for the voice composer: recording card with pulsing dot, live mic-level bars, primary Stop + subtle Cancel; an upload-in-progress spinner variant; the recorded preview row (inline player + re-record/remove); a styled error card with help + retry; and an obvious recording state on the mic button. Honors prefers-reduced-motion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(voice): redesign recording + attached composer states (LC-499)
Some checks failed
check-secrets / Kingfisher (push) Failing after 5s
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 7s
check-secrets / Kingfisher (pull_request) Failing after 9s
check-secrets / TruffleHog (pull_request) Successful in 10s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 3m13s
034ad66c6e
Replace the bare-text voice composer with proper UI: a recording card (pulsing dot, elapsed time, live AnalyserNode level meter, styled Stop/Cancel); a playback preview reusing the timeline .lc-voice player so the user can listen before sending, with Re-record and labeled Remove actions; and styled, actionable edge states (mic-denied with how-to-fix, unsupported, start-failed, empty, upload-in-progress with Send disabled, upload error with Retry that re-sends the retained blob). The mic button now shows an obvious recording state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch feat/LC-499-voice-composer-ui 2026-06-27 20:33:41 +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!461
No description provided.