From 589fd38fd807138c95e60641910e67af4a0cc189 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Fri, 14 Aug 2026 12:35:44 +0700 Subject: [PATCH] fix(voice): separate Mic and Listen state (were both bound to listen) - MicControl now uses useMicTransmit + local micActive/micVolume (was wrongly wired to listen.active/listen.toggle) - ListenControl keeps useVoiceListen + handleListenVolume (tsc clean, next build green) --- .../src/app/(dashboard)/voice/view.tsx | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/services/frontend/src/app/(dashboard)/voice/view.tsx b/services/frontend/src/app/(dashboard)/voice/view.tsx index abfd24b..7b93704 100644 --- a/services/frontend/src/app/(dashboard)/voice/view.tsx +++ b/services/frontend/src/app/(dashboard)/voice/view.tsx @@ -16,6 +16,7 @@ import { MicControl } from "@/components/voice/mic-control"; import { ListenControl } from "@/components/voice/listen-control"; import { useGuilds, + useMicTransmit, useSpeakers, useVoiceChannels, useVoiceConnect, @@ -41,6 +42,9 @@ export default function VoiceView({ initialStatus }: { initialStatus?: VoiceStat const connect = useVoiceConnect(); const disconnect = useVoiceDisconnect(); const listen = useVoiceListen(ws); + const mic = useMicTransmit(ws); + const [micActive, setMicActive] = useState(false); + const [micVolume, setMicVolume] = useState(75); useEffect(() => { const unsub = subscribe(ws); @@ -50,6 +54,33 @@ export default function VoiceView({ initialStatus }: { initialStatus?: VoiceStat const active = speakers.filter((s) => s.speaking); const connected = status?.connected ?? false; + const handleMicToggle = async (on: boolean) => { + if (on) { + try { + await mic.mutateAsync(true); + setMicActive(true); + } catch { + setMicActive(false); + } + } else { + setMicActive(false); + try { + await mic.mutateAsync(false); + } catch { + // Stop already tore down — ignore remote error + } + } + }; + + const handleMicVolume = (v: number) => { + setMicVolume(v); + mic.setVolume(v); + }; + + const handleListenVolume = (v: number) => { + listen.setVolume(v); + }; + const handleGuildChange = (e: React.ChangeEvent) => { const g = e.target.value; setSelectedGuild(g); @@ -165,8 +196,8 @@ export default function VoiceView({ initialStatus }: { initialStatus?: VoiceStat listen.toggle(on)} + micOn={micActive} + onToggle={handleMicToggle} levels={listen.levels} /> @@ -175,7 +206,7 @@ export default function VoiceView({ initialStatus }: { initialStatus?: VoiceStat listening={listen.active} onToggle={(on) => listen.toggle(on)} volume={75} - onVolume={listen.setVolume} + onVolume={handleListenVolume} />