From 9fefd149443fe6592171d26265ed84d4c9b41998 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Fri, 18 Sep 2026 21:58:39 -0400 Subject: [PATCH] fix(calls): undeafen restores the microphone it muted (#173) Deafen muted the mic (correct) but undeafen left you muted, so every deafen cycle silently turned into a mute. Remember whether the mic was on when deafening and turn it back on when undeafening (Discord semantics). Verified in a real two-party LiveKit call on the local stack. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA --- src/app/plugins/call/CallControl.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/plugins/call/CallControl.ts b/src/app/plugins/call/CallControl.ts index cbf2ff894..9108c240d 100644 --- a/src/app/plugins/call/CallControl.ts +++ b/src/app/plugins/call/CallControl.ts @@ -50,6 +50,11 @@ export class CallControl extends EventEmitter implements CallControlState { // user-initiated unmute that auto-undeafens the user. public pttActive = false; + // Deafen mutes the mic; undeafen should give it back ONLY if it was on + // before (Discord semantics — verified against the real client, Gitea #173: + // undeafen used to leave you muted). Cleared by any manual mic toggle. + private micOnBeforeDeafen = false; + // P6-2: mirrors CallEmbed.joined. Set true from forceState(), which CallEmbed // invokes only from onCallJoined(). Gates io.lotus.set_deafen so we never send // before the fork's widget handler mounts (pre-join sends pend to a 10s @@ -398,7 +403,11 @@ export class CallControl extends EventEmitter implements CallControlState { this.emitStateUpdate(); - if (!this.sound && this.microphone) { + if (!sound) { + this.micOnBeforeDeafen = this.microphone; + if (this.microphone) this.toggleMicrophone(); + } else if (this.micOnBeforeDeafen && !this.microphone) { + this.micOnBeforeDeafen = false; this.toggleMicrophone(); } }