refactor(calls): drop the deafen iframe-DOM fallback now that the fork owns it (#209)
CallControl.setSound()/applyScreenshareAudioMuted() no longer poke <audio>.muted inside the EC frame, and the per-membership re-apply (useCallMemberSoundSync) is gone: with the pin at 0.25.0-lotus.4 the fork applies deafen and the screenshare-audio mute through its own renderer, including for late joiners. Verified headless: deafen set before a second participant joins mutes their track on arrival; deafen/undeafen leaves the screenshare-audio mute in place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -34,7 +34,6 @@ import {
|
||||
useCallHangupEvent,
|
||||
useCallJoined,
|
||||
useCallThemeSync,
|
||||
useCallMemberSoundSync,
|
||||
useCallStart,
|
||||
} from '../hooks/useCallEmbed';
|
||||
import { callChatAtom, callEmbedAtom } from '../state/callEmbed';
|
||||
@@ -673,7 +672,6 @@ function CallUtils({ embed, joined }: { embed: CallEmbed; joined: boolean }) {
|
||||
// the mobile in-call chat. Both are gated on `joined`.
|
||||
useCallHotkeys(embed, joined);
|
||||
useAfkAutoMute(joined ? embed : undefined);
|
||||
useCallMemberSoundSync(embed);
|
||||
useCallJoinLeaveSounds(embed);
|
||||
useCallThemeSync(embed);
|
||||
useCallQuality(embed);
|
||||
|
||||
@@ -13,7 +13,6 @@ import { ThemeKind, useTheme } from './useTheme';
|
||||
import { callEmbedAtom } from '../state/callEmbed';
|
||||
import { useResizeObserver } from './useResizeObserver';
|
||||
import { CallControlState } from '../plugins/call/CallControlState';
|
||||
import { useCallMembersChange, useCallSession } from './useCall';
|
||||
import { CallPreferences } from '../state/callPreferences';
|
||||
import { useSetting } from '../state/hooks/settings';
|
||||
import { NoiseSuppressionMode, settingsAtom } from '../state/settings';
|
||||
@@ -184,14 +183,6 @@ export const useCallHangupEvent = (embed: CallEmbed, callback: () => void) => {
|
||||
useClientWidgetApiEvent(embed.call, ElementWidgetActions.Close, callback);
|
||||
};
|
||||
|
||||
export const useCallMemberSoundSync = (embed: CallEmbed) => {
|
||||
const callSession = useCallSession(embed.room);
|
||||
useCallMembersChange(
|
||||
callSession,
|
||||
useCallback(() => embed.control.applySound(), [embed]),
|
||||
);
|
||||
};
|
||||
|
||||
export const useCallThemeSync = (embed: CallEmbed) => {
|
||||
const theme = useTheme();
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
audio_enabled: this.microphone,
|
||||
video_enabled: this.video,
|
||||
});
|
||||
this.setSound(this.sound);
|
||||
this.setSound();
|
||||
this.emitStateUpdate();
|
||||
}
|
||||
|
||||
@@ -251,10 +251,6 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
this.onControlMutation();
|
||||
}
|
||||
|
||||
public applySound() {
|
||||
this.setSound(this.sound);
|
||||
}
|
||||
|
||||
private async setMediaState(state: ElementMediaStatePayload) {
|
||||
// transport.send resolves once EC has ACK'd the command, which is enough to
|
||||
// consider the mute applied. We deliberately do NOT gate completion on a
|
||||
@@ -265,33 +261,22 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
return this.call.transport.send(ElementWidgetActions.DeviceMute, state);
|
||||
}
|
||||
|
||||
private setSound(sound: boolean): void {
|
||||
const callDocument = getCallDocument(this.iframe);
|
||||
if (callDocument) {
|
||||
callDocument.querySelectorAll('audio').forEach((el) => {
|
||||
const isScreenshareAudio = el.getAttribute('data-lk-source') === 'screen_share_audio';
|
||||
el.muted = !sound || (isScreenshareAudio && this.screenshareAudioMuted);
|
||||
});
|
||||
}
|
||||
// [Gitea #209] Deafen is applied by the fork (io.lotus.set_deafen). The
|
||||
// iframe-DOM `.muted` fallback that used to live here (plus the per-member
|
||||
// re-apply in useCallMemberSoundSync) fought EC's audio renderer and is gone
|
||||
// now that the pin is ≥ 0.25.0-lotus.2 — late joiners are the fork's job.
|
||||
private setSound(): void {
|
||||
this.sendDeafenState();
|
||||
}
|
||||
|
||||
private applyScreenshareAudioMuted(): void {
|
||||
if (!this.sound) return;
|
||||
const callDocument = getCallDocument(this.iframe);
|
||||
if (callDocument) {
|
||||
callDocument
|
||||
.querySelectorAll<HTMLAudioElement>('audio[data-lk-source="screen_share_audio"]')
|
||||
.forEach((el) => {
|
||||
el.muted = this.screenshareAudioMuted;
|
||||
});
|
||||
}
|
||||
this.sendDeafenState();
|
||||
}
|
||||
|
||||
// P6-2: send deafen state to the fork (io.lotus.set_deafen). The DOM .muted
|
||||
// code above is a transitional fallback — remove once the fork ships & the
|
||||
// pin is bumped.
|
||||
// P6-2: send deafen state to the fork (io.lotus.set_deafen). Join-gated: the
|
||||
// fork's handler only exists once joined; onCallJoined() re-sends the current
|
||||
// state so a pre-join deafen is not lost.
|
||||
private sendDeafenState(): void {
|
||||
if (!this.joined) return;
|
||||
this.call.transport
|
||||
@@ -398,7 +383,7 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
);
|
||||
this.state = state;
|
||||
|
||||
this.setSound(sound);
|
||||
this.setSound();
|
||||
// After un-deafening, re-apply screenshare audio mute if active
|
||||
if (sound) this.applyScreenshareAudioMuted();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user