Skip to content

Commit 3334b1f

Browse files
committed
Update a call's type before notifying listeners of the change
If we notify listeners of a change in a call's type before actually making that change, the listeners will be working with glitched state. This would cause the room list to show the wrong call type in certain situations.
1 parent 27a3320 commit 3334b1f

2 files changed

Lines changed: 32 additions & 3 deletions

File tree

apps/web/src/models/Call.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,9 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
114114
}
115115

116116
protected set callType(callType: CallType) {
117-
if (this._callType !== callType) {
118-
this.emit(CallEvent.CallTypeChanged, callType);
119-
}
117+
const prevCallType = this._callType;
120118
this._callType = callType;
119+
if (callType !== prevCallType) this.emit(CallEvent.CallTypeChanged, callType);
121120
}
122121

123122
/**

apps/web/test/unit-tests/models/Call-test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
MatrixRTCSession,
2727
MatrixRTCSessionEvent,
2828
} from "matrix-js-sdk/src/matrixrtc";
29+
import { CallType } from "matrix-js-sdk/src/webrtc/call";
2930

3031
import type { Mocked } from "jest-mock";
3132
import type { ClientWidgetApi } from "matrix-widget-api";
@@ -987,6 +988,35 @@ describe("ElementCall", () => {
987988
call.off(CallEvent.Participants, onParticipants);
988989
});
989990

991+
it("emits events when call type changes", async () => {
992+
const onCallTypeChanged = jest.fn();
993+
call.on(CallEvent.CallTypeChanged, onCallTypeChanged);
994+
// Should default to video when unknown
995+
expect(call.callType).toBe(CallType.Video);
996+
997+
// Change call type to voice
998+
roomSession.memberships = [
999+
{ sender: alice.userId, deviceId: "alices_device", callIntent: "audio" } as Mocked<CallMembership>,
1000+
];
1001+
roomSession.getConsensusCallIntent.mockReturnValue("audio");
1002+
roomSession.emit(MatrixRTCSessionEvent.MembershipsChanged, [], []);
1003+
1004+
expect(call.callType).toBe(CallType.Voice);
1005+
expect(onCallTypeChanged.mock.calls).toEqual([[CallType.Voice]]);
1006+
1007+
// Change call type back to video
1008+
roomSession.memberships = [
1009+
{ sender: alice.userId, deviceId: "alices_device", callIntent: "video" } as Mocked<CallMembership>,
1010+
];
1011+
roomSession.getConsensusCallIntent.mockReturnValue("video");
1012+
roomSession.emit(MatrixRTCSessionEvent.MembershipsChanged, [], []);
1013+
1014+
expect(call.callType).toBe(CallType.Video);
1015+
expect(onCallTypeChanged.mock.calls).toEqual([[CallType.Voice], [CallType.Video]]);
1016+
1017+
call.off(CallEvent.CallTypeChanged, onCallTypeChanged);
1018+
});
1019+
9901020
it("ends the call immediately if the session ended", async () => {
9911021
await connect(call, widgetApi);
9921022
const onDestroy = jest.fn();

0 commit comments

Comments
 (0)