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

Commit

Permalink
Acknowledge DeviceMute widget actions (#12790)
Browse files Browse the repository at this point in the history
* acknowledge DeviceMute widget actions (to prevent sending the  default error response to the widget)

* rephrase comment

* test for widget action ack
  • Loading branch information
toger5 authored Jul 25, 2024
1 parent 6e9fc55 commit 72e7df0
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/models/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,10 @@ export class ElementCall extends Call {
this.messaging!.on(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
this.messaging!.on(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
this.messaging!.on(`action:${ElementWidgetActions.DeviceMute}`, async (ev) => {
ev.preventDefault();
await this.messaging!.transport.reply(ev.detail, {}); // ack
});

if (!this.widget.data?.skipLobby) {
// If we do not skip the lobby we need to wait until the widget has
Expand Down
23 changes: 18 additions & 5 deletions src/stores/widgets/ElementWidgetActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,35 @@ export enum ElementWidgetActions {
JoinCall = "io.element.join",
HangupCall = "im.vector.hangup",
CallParticipants = "io.element.participants",
MuteAudio = "io.element.mute_audio",
UnmuteAudio = "io.element.unmute_audio",
MuteVideo = "io.element.mute_video",
UnmuteVideo = "io.element.unmute_video",
StartLiveStream = "im.vector.start_live_stream",

// Actions for switching layouts
TileLayout = "io.element.tile_layout",
SpotlightLayout = "io.element.spotlight_layout",

OpenIntegrationManager = "integration_manager_open",

/**
* @deprecated Use MSC2931 instead
*/
ViewRoom = "io.element.view_room",

// This action type is used as a `fromWidget` and a `toWidget` action.
// fromWidget: updates the client about the current device mute state
// toWidget: the client requests a specific device mute configuration
// The reply will always be the resulting configuration
// It is possible to sent an empty configuration to retrieve the current values or
// just one of the fields to update that particular value
// An undefined field means that EC will keep the mute state as is.
// -> this will allow the client to only get the current state
//
// The data of the widget action request and the response are:
// {
// audio_enabled?: boolean,
// video_enabled?: boolean
// }
// NOTE: this is currently unused. Its only here to make EW aware
// of this action so it does not throw errors.
DeviceMute = "io.element.device_mute",
}

export interface IHangupCallApiRequest extends IWidgetApiRequest {
Expand Down
12 changes: 12 additions & 0 deletions test/models/Call-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,18 @@ describe("ElementCall", () => {
expect(messaging.transport.send).toHaveBeenCalledWith(ElementWidgetActions.TileLayout, {});
});

it("acknowledges mute_device widget action", async () => {
await callConnectProcedure(call);
const preventDefault = jest.fn();
const mockEv = {
preventDefault,
detail: { video_enabled: false },
};
messaging.emit(`action:${ElementWidgetActions.DeviceMute}`, mockEv);
expect(messaging.transport.reply).toHaveBeenCalledWith({ video_enabled: false }, {});
expect(preventDefault).toHaveBeenCalled();
});

it("emits events when connection state changes", async () => {
// const wait = jest.spyOn(CallModule, "waitForEvent");
const onConnectionState = jest.fn();
Expand Down

0 comments on commit 72e7df0

Please sign in to comment.