feat(call): send io.lotus.set_deafen to the fork (P6-2 phase 1)
CallControl now sends the new io.lotus.set_deafen action (join-gated via forceState) on every deafen / screenshare-audio-mute toggle + on join, ALONGSIDE the retained iframe-DOM .muted hack (transitional). Against the current pinned bundle the action is immediately error-replied + swallowed by .catch — inert, no timeout. Reordered toggleSound() to commit state before setSound() so the sent deafen value isn't inverted. Phase 2 (after the fork is published): bump the pin lotus.1 -> lotus.2 and delete the DOM hack. Docs: HANDOFF §12.4, LOTUS_TODO P6-2, LOTUS_BUGS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,12 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
|
||||
private _pipMode = 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
|
||||
// timeout — HANDOFF_ELEMENT_CALL_FORK.md §12.1 F1).
|
||||
private joined = false;
|
||||
|
||||
private get document(): Document | undefined {
|
||||
return this.iframe.contentDocument ?? this.iframe.contentWindow?.document;
|
||||
}
|
||||
@@ -141,6 +147,12 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
this.spotlight,
|
||||
);
|
||||
await this.applyState();
|
||||
// P6-2: CallEmbed calls forceState() only from onCallJoined(), so this is
|
||||
// the join transition. Flip the gate open, then push the current deafen
|
||||
// state to the fork's freshly-mounted handler. (setSound() above ran while
|
||||
// this.joined was still false, so it was gated — this is the first send.)
|
||||
this.joined = true;
|
||||
this.sendDeafenState();
|
||||
}
|
||||
|
||||
public startObserving() {
|
||||
@@ -209,6 +221,7 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
el.muted = !sound || (isScreenshareAudio && this.screenshareAudioMuted);
|
||||
});
|
||||
}
|
||||
this.sendDeafenState();
|
||||
}
|
||||
|
||||
private applyScreenshareAudioMuted(): void {
|
||||
@@ -221,6 +234,20 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
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.
|
||||
private sendDeafenState(): void {
|
||||
if (!this.joined) return;
|
||||
this.call.transport
|
||||
.send('io.lotus.set_deafen', {
|
||||
deafened: !this.sound,
|
||||
screenshareAudioMuted: this.screenshareAudioMuted,
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
|
||||
public onMediaState(evt: CustomEvent<ElementMediaStateDetail>) {
|
||||
@@ -286,10 +313,8 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
public toggleSound() {
|
||||
const sound = !this.sound;
|
||||
|
||||
this.setSound(sound);
|
||||
// After un-deafening, re-apply screenshare audio mute if active
|
||||
if (sound) this.applyScreenshareAudioMuted();
|
||||
|
||||
// P6-2: commit state before setSound()/applyScreenshareAudioMuted() so
|
||||
// sendDeafenState() (which reads this.sound) reports the new value.
|
||||
const state = new CallControlState(
|
||||
this.microphone,
|
||||
this.video,
|
||||
@@ -299,6 +324,11 @@ export class CallControl extends EventEmitter implements CallControlState {
|
||||
this.screenshareAudioMuted,
|
||||
);
|
||||
this.state = state;
|
||||
|
||||
this.setSound(sound);
|
||||
// After un-deafening, re-apply screenshare audio mute if active
|
||||
if (sound) this.applyScreenshareAudioMuted();
|
||||
|
||||
this.emitStateUpdate();
|
||||
|
||||
if (!this.sound && this.microphone) {
|
||||
|
||||
Reference in New Issue
Block a user