fix: server-deafen now shows amber mute icon across all UI surfaces

When a moderator server-deafens a user, the implied mute is server-imposed
and should display amber (not red) everywhere. Updated VoiceControlBar,
ChannelSidebar, VoiceChannel, and VoiceUser to check isServerDeafened
alongside isServerMuted for amber color and cursor-not-allowed state.

Also includes smart mute/deafen toggle logic (Discord-style coupling),
server-side enforcement of mute/deafen bypass, and cleanup of server
voice state on user departure.
This commit is contained in:
Jannis Braun
2026-03-09 17:12:00 +01:00
parent e2c18ad2b0
commit f6cdfe993f
7 changed files with 129 additions and 76 deletions
+17 -2
View File
@@ -238,8 +238,21 @@ export const useVoiceStore = create<VoiceState>()(
setOutputDevice: (deviceId) => set({ outputDeviceId: deviceId }),
toggleMic: () => set((state) => ({ isMuted: !state.isMuted })),
toggleDeafen: () => set((state) => ({ isDeafened: !state.isDeafened })),
toggleMic: () => set((state) => {
if (state.isMuted && state.isDeafened) {
// Unmuting while deafened → clear both (Discord behavior)
return { isMuted: false, isDeafened: false };
}
return { isMuted: !state.isMuted };
}),
toggleDeafen: () => set((state) => {
if (state.isDeafened) {
// Undeafening → clear both
return { isMuted: false, isDeafened: false };
}
// Deafening → set both
return { isMuted: true, isDeafened: true };
}),
toggleCamera: () => set((state) => ({ isCameraOn: !state.isCameraOn })),
toggleScreenShare: () => set((state) => ({ isScreenSharing: !state.isScreenSharing })),
@@ -345,6 +358,8 @@ export const useVoiceStore = create<VoiceState>()(
streamVolumes: new Map(),
streamMutes: new Map(),
watchingStreams: new Set(),
serverMutedUserIds: new Set(),
serverDeafenedUserIds: new Set(),
voiceUsers,
};
});