feat(phase6): video grid, noise suppression, whisper system

- New VideoGrid component: live camera feeds (local + remote) in VoicePanel
- Camera toggle in VoiceControls: enable/disable video per participant
- Noise suppression toggle in VoiceControls + voice store
- VOICE_WHISPER WS event: backend routes whisper to target user only
- Whisper UI: per-participant whisper button, notification toasts with dismiss
- Fix circular import between voice.ts and ws.ts (use lazy accessor)
This commit is contained in:
2026-06-30 12:21:53 -04:00
parent 3c063d4f56
commit 775bd953b0
8 changed files with 307 additions and 28 deletions
+17
View File
@@ -142,6 +142,23 @@ func (c *Client) readPump() {
switch event.Type {
case EventTypingStart, EventPresenceUpdate:
c.Hub.BroadcastEvent(event)
case EventVoiceWhisper:
// Forward voice whispers only to the target user, not broadcast
var whisperData struct {
TargetUserID string `json:"target_user_id"`
FromUserID string `json:"from_user_id"`
FromUsername string `json:"from_username"`
Message string `json:"message,omitempty"`
}
if raw, ok := event.Data.(json.RawMessage); ok {
if err := json.Unmarshal(raw, &whisperData); err == nil {
whisperData.FromUserID = c.UserID
c.Hub.SendToUser(whisperData.TargetUserID, Event{
Type: EventVoiceWhisper,
Data: whisperData,
})
}
}
default:
c.Hub.logger.Info("received event from client", "type", event.Type, "user_id", c.UserID)
}