From dbdaa1540a9b2e78e45eb6f27347aaf41d67b059 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 26 Oct 2022 17:50:20 -0400 Subject: [PATCH] Let leave requests outlive the window --- spec/unit/webrtc/groupCall.spec.ts | 20 ++++++++++++++++++++ src/client.ts | 4 +++- src/http-api/fetch.ts | 4 +++- src/http-api/interface.ts | 1 + src/webrtc/groupCall.ts | 11 ++++++++--- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/spec/unit/webrtc/groupCall.spec.ts b/spec/unit/webrtc/groupCall.spec.ts index e3c850c70..692fbdbfb 100644 --- a/spec/unit/webrtc/groupCall.spec.ts +++ b/spec/unit/webrtc/groupCall.spec.ts @@ -212,12 +212,32 @@ describe('Group Call', function() { ], }), FAKE_USER_ID_1, + false, ); } finally { groupCall.leave(); } }); + it("sends member state event to room on leave", async () => { + room.currentState.members[FAKE_USER_ID_1] = { + userId: FAKE_USER_ID_1, + } as unknown as RoomMember; + + await groupCall.create(); + await groupCall.enter(); + mockSendState.mockClear(); + + groupCall.leave(); + expect(mockSendState).toHaveBeenCalledWith( + FAKE_ROOM_ID, + EventType.GroupCallMemberPrefix, + expect.objectContaining({ "m.calls": [] }), + FAKE_USER_ID_1, + true, // Request should outlive the window + ); + }); + it("starts with mic unmuted in regular calls", async () => { try { await groupCall.create(); diff --git a/src/client.ts b/src/client.ts index 022fee663..4b814b2f4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -7517,6 +7517,7 @@ export class MatrixClient extends TypedEventEmitter { const pathParams = { $roomId: roomId, @@ -7535,7 +7537,7 @@ export class MatrixClient extends TypedEventEmitter { method: Method, url: URL | string, body?: Body, - opts: Pick = {}, + opts: Pick = {}, ): Promise> { const headers = Object.assign({}, opts.headers || {}); const json = opts.json ?? true; @@ -252,6 +252,7 @@ export class FetchHttpApi { } const timeout = opts.localTimeoutMs ?? this.opts.localTimeoutMs; + const keepAlive = opts.keepAlive ?? false; const signals = [ this.abortController.signal, ]; @@ -284,6 +285,7 @@ export class FetchHttpApi { referrerPolicy: "no-referrer", cache: "no-cache", credentials: "omit", // we send credentials via headers + keepalive: keepAlive, }); } catch (e) { if ((e).name === "AbortError") { diff --git a/src/http-api/interface.ts b/src/http-api/interface.ts index c798bec0d..372179470 100644 --- a/src/http-api/interface.ts +++ b/src/http-api/interface.ts @@ -38,6 +38,7 @@ export interface IRequestOpts { headers?: Record; abortSignal?: AbortSignal; localTimeoutMs?: number; + keepAlive?: boolean; // defaults to false json?: boolean; // defaults to true // Set to true to prevent the request function from emitting a Session.logged_out event. diff --git a/src/webrtc/groupCall.ts b/src/webrtc/groupCall.ts index c2fd3c4fb..071506228 100644 --- a/src/webrtc/groupCall.ts +++ b/src/webrtc/groupCall.ts @@ -726,10 +726,13 @@ export class GroupCall extends TypedEventEmitter< private async removeMemberStateEvent(): Promise { if (this.resendMemberStateTimer !== null) clearInterval(this.resendMemberStateTimer); this.resendMemberStateTimer = null; - return await this.updateMemberCallState(undefined); + return await this.updateMemberCallState(undefined, true); } - private async updateMemberCallState(memberCallState?: IGroupCallRoomMemberCallState): Promise { + private async updateMemberCallState( + memberCallState?: IGroupCallRoomMemberCallState, + keepAlive = false, + ): Promise { const localUserId = this.client.getUserId()!; const memberState = this.getMemberStateEvents(localUserId)?.getContent(); @@ -758,7 +761,9 @@ export class GroupCall extends TypedEventEmitter< "m.expires_ts": Date.now() + CALL_MEMBER_STATE_TIMEOUT, }; - return this.client.sendStateEvent(this.room.roomId, EventType.GroupCallMemberPrefix, content, localUserId); + return this.client.sendStateEvent( + this.room.roomId, EventType.GroupCallMemberPrefix, content, localUserId, keepAlive, + ); } public onMemberStateChanged = async (event: MatrixEvent) => {