Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 72e7df0

Browse files
authored
Acknowledge DeviceMute widget actions (#12790)
* acknowledge DeviceMute widget actions (to prevent sending the default error response to the widget) * rephrase comment * test for widget action ack
1 parent 6e9fc55 commit 72e7df0

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

src/models/Call.ts

+4
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,10 @@ export class ElementCall extends Call {
892892
this.messaging!.on(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
893893
this.messaging!.on(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
894894
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
895+
this.messaging!.on(`action:${ElementWidgetActions.DeviceMute}`, async (ev) => {
896+
ev.preventDefault();
897+
await this.messaging!.transport.reply(ev.detail, {}); // ack
898+
});
895899

896900
if (!this.widget.data?.skipLobby) {
897901
// If we do not skip the lobby we need to wait until the widget has

src/stores/widgets/ElementWidgetActions.ts

+18-5
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,35 @@ export enum ElementWidgetActions {
2121
JoinCall = "io.element.join",
2222
HangupCall = "im.vector.hangup",
2323
CallParticipants = "io.element.participants",
24-
MuteAudio = "io.element.mute_audio",
25-
UnmuteAudio = "io.element.unmute_audio",
26-
MuteVideo = "io.element.mute_video",
27-
UnmuteVideo = "io.element.unmute_video",
2824
StartLiveStream = "im.vector.start_live_stream",
2925

3026
// Actions for switching layouts
3127
TileLayout = "io.element.tile_layout",
3228
SpotlightLayout = "io.element.spotlight_layout",
3329

3430
OpenIntegrationManager = "integration_manager_open",
35-
3631
/**
3732
* @deprecated Use MSC2931 instead
3833
*/
3934
ViewRoom = "io.element.view_room",
35+
36+
// This action type is used as a `fromWidget` and a `toWidget` action.
37+
// fromWidget: updates the client about the current device mute state
38+
// toWidget: the client requests a specific device mute configuration
39+
// The reply will always be the resulting configuration
40+
// It is possible to sent an empty configuration to retrieve the current values or
41+
// just one of the fields to update that particular value
42+
// An undefined field means that EC will keep the mute state as is.
43+
// -> this will allow the client to only get the current state
44+
//
45+
// The data of the widget action request and the response are:
46+
// {
47+
// audio_enabled?: boolean,
48+
// video_enabled?: boolean
49+
// }
50+
// NOTE: this is currently unused. Its only here to make EW aware
51+
// of this action so it does not throw errors.
52+
DeviceMute = "io.element.device_mute",
4053
}
4154

4255
export interface IHangupCallApiRequest extends IWidgetApiRequest {

test/models/Call-test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,18 @@ describe("ElementCall", () => {
965965
expect(messaging.transport.send).toHaveBeenCalledWith(ElementWidgetActions.TileLayout, {});
966966
});
967967

968+
it("acknowledges mute_device widget action", async () => {
969+
await callConnectProcedure(call);
970+
const preventDefault = jest.fn();
971+
const mockEv = {
972+
preventDefault,
973+
detail: { video_enabled: false },
974+
};
975+
messaging.emit(`action:${ElementWidgetActions.DeviceMute}`, mockEv);
976+
expect(messaging.transport.reply).toHaveBeenCalledWith({ video_enabled: false }, {});
977+
expect(preventDefault).toHaveBeenCalled();
978+
});
979+
968980
it("emits events when connection state changes", async () => {
969981
// const wait = jest.spyOn(CallModule, "waitForEvent");
970982
const onConnectionState = jest.fn();

0 commit comments

Comments
 (0)