fix: derive voice sidebar from LiveKit participants to eliminate desync

The channel sidebar voice user list was maintained by a separate
voiceUsers Map (fed by WS events + fragile hydration code) that diverged
from reality after server restarts — users shown in wrong channels,
duplicated across channels. The VoiceGrid was always correct because it
reads LiveKit participants directly.

Now VoiceChannel.tsx derives its user list from LiveKit participants for
the connected channel (single source of truth) and only falls back to
server-provided voiceUsers for channels the user is not connected to.

Removed all hydration band-aids that tried to sync the two systems:
- useLiveKit ParticipantDisconnected → removeVoiceUser
- useLiveKit ConnectionStateChanged → addVoiceUser hydration loop
- useWebSocket ready handler → dynamic import LiveKit hydration

Also includes: voice channel settings gear icon on hover, persist
per-user volume/mute prefs across sessions, default screen share
audio off on Electron (no system audio capture support).
This commit is contained in:
Jannis Braun
2026-03-16 22:10:53 +01:00
parent e809adff3e
commit bfecb41c66
4 changed files with 53 additions and 19 deletions
@@ -1334,6 +1334,8 @@ function ChannelItem({
channelName={channel.name}
onClick={() => canConnect && handleVoiceJoin(channel.id)}
locked={!canConnect}
canManage={canManage}
onSettingsClick={onSettingsClick}
dragState={voiceDragState}
onDragStart={onVoiceDragStart}
onDragEnd={onVoiceDragEnd}