feat(calls): per-peer connection-quality indicator (LC-410) #424
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/lc-410-connection-quality"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements LC-410 (subtask of the LC-402 call redesign): surface per-participant connection health so a bad link is visible instead of silent audio dropouts.
What
Each remote tile shows a small signal-bars glyph in the name pill, coloured by state:
The self tile has no peer connection, so it shows no indicator.
How
RTCPeerConnection.onconnectionstatechangeupdates the tile immediately:connected-> good,disconnected/connecting/checking-> reconnecting,failed-> failed.getStats()loop refines a connected peer to good vs degraded from the inbound packet-loss ratio (per-interval delta ofpacketsLost/packetsReceived) and the nominated candidate pair'scurrentRoundTripTime(degraded at >3% loss or >350ms RTT).data-quality; CSS recolours the glyph (--success/--warning/--danger) and pulses the reconnecting state (killed underprefers-reduced-motion). A localizedtitle/aria-labelnames the state.Scope
Frontend only:
assets/voice.js(monitor + tile glyph),assets/main.css(glyph styles + reduced-motion),templates/base.html+locales/{en,es}/js.ftl(four state strings). No Rust, route, or schema change.Tests
just check(standalone + saas compile, clippy, fmt),just test,just test-saasall pass.voice.jssyntax-checked;just build-cssregenerated.Each remote participant tile now shows a connection-health glyph (signal bars in the name pill) driven off the peer's RTCPeerConnection: good / degraded / reconnecting / failed. - connectionstatechange updates immediately: connected -> good, disconnected/connecting/checking -> reconnecting (pulsing), failed -> failed. - A 3s getStats loop refines a connected peer to good vs degraded from inbound packet-loss ratio (per-interval delta) and the nominated candidate pair's round-trip time. - The glyph is recoloured by data-quality via CSS (success/warning/danger), reconnecting pulses (killed under prefers-reduced-motion), and carries a localized title/aria-label. Self has no peer connection so its tile shows no indicator. The loop starts/stops with the active-speaker loop on join/leave. Frontend only: voice.js (monitor + tile glyph), main.css (glyph styles), base.html + locales/{en,es}/js.ftl (four state strings). No Rust/schema change. just check, just test, just test-saas all pass; voice.js syntax-checked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>