diff --git a/src/matrix/calls/CallHandler.ts b/src/matrix/calls/CallHandler.ts index 2ed8bf87..c33f24eb 100644 --- a/src/matrix/calls/CallHandler.ts +++ b/src/matrix/calls/CallHandler.ts @@ -201,11 +201,12 @@ export class CallHandler { private handleCallMemberEvent(event: StateEvent, log: ILogItem) { const userId = event.state_key; const calls = event.content["m.calls"] ?? []; + const eventTimestamp = event.origin_server_ts; for (const call of calls) { const callId = call["m.call_id"]; const groupCall = this._calls.get(callId); // TODO: also check the member when receiving the m.call event - groupCall?.updateMembership(userId, call, log); + groupCall?.updateMembership(userId, call, eventTimestamp, log); }; const newCallIdsMemberOf = new Set(calls.map(call => call["m.call_id"])); let previousCallIdsMemberOf = this.memberToCallIds.get(userId); diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index a05ebe87..dc48a692 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -64,6 +64,9 @@ export class GroupCall extends EventEmitter<{change: never}> { private _memberOptions: MemberOptions; private _state: GroupCallState; + private _deviceIndex?: number; + private _eventTimestamp?: number; + constructor( public readonly id: string, newCall: boolean, @@ -103,6 +106,14 @@ export class GroupCall extends EventEmitter<{change: never}> { return this.callContent?.["m.intent"]; } + get deviceIndex(): number | undefined { + return this._deviceIndex; + } + + get eventTimestamp(): number | undefined { + return this._eventTimestamp; + } + join(localMedia: LocalMedia): Promise { return this.logItem.wrap("join", async log => { if (this._state !== GroupCallState.Created) { @@ -188,16 +199,21 @@ export class GroupCall extends EventEmitter<{change: never}> { } /** @internal */ - updateMembership(userId: string, callMembership: CallMembership, syncLog: ILogItem) { + updateMembership(userId: string, callMembership: CallMembership, eventTimestamp: number, syncLog: ILogItem) { this.logItem.wrap({l: "updateMember", id: userId}, log => { syncLog.refDetached(log); const devices = callMembership["m.devices"]; const previousDeviceIds = this.getDeviceIdsForUserId(userId); - for (const device of devices) { + for (let deviceIndex = 0; deviceIndex < devices.length; deviceIndex++) { + const device = devices[deviceIndex]; const deviceId = device.device_id; const memberKey = getMemberKey(userId, deviceId); log.wrap({l: "update device member", id: memberKey}, log => { if (userId === this.options.ownUserId && deviceId === this.options.ownDeviceId) { + + this._deviceIndex = deviceIndex; + this._eventTimestamp = eventTimestamp; + if (this._state === GroupCallState.Joining) { log.set("update_own", true); this._state = GroupCallState.Joined; @@ -207,14 +223,14 @@ export class GroupCall extends EventEmitter<{change: never}> { let member = this._members.get(memberKey); if (member) { log.set("update", true); - member!.updateCallInfo(device); + member!.updateCallInfo(device, deviceIndex, eventTimestamp); } else { const logItem = this.logItem.child({l: "member", id: memberKey}); log.set("add", true); log.refDetached(logItem); member = new Member( RoomMember.fromUserId(this.roomId, userId, "join"), - device, this._memberOptions, logItem + device, deviceIndex, eventTimestamp, this._memberOptions, logItem ); this._members.add(memberKey, member); if (this._state === GroupCallState.Joining || this._state === GroupCallState.Joined) { @@ -332,6 +348,10 @@ export class GroupCall extends EventEmitter<{change: never}> { ["session_id"]: this.options.sessionId, feeds: [{purpose: "m.usermedia"}] }); + + this._deviceIndex = callInfo["m.devices"].length; + this._eventTimestamp = Date.now(); + return stateContent; } diff --git a/src/matrix/calls/group/Member.ts b/src/matrix/calls/group/Member.ts index 06693030..7e6281aa 100644 --- a/src/matrix/calls/group/Member.ts +++ b/src/matrix/calls/group/Member.ts @@ -55,6 +55,8 @@ export class Member { constructor( public readonly member: RoomMember, private callDeviceMembership: CallDeviceMembership, + private _deviceIndex: number, + private _eventTimestamp: number, private readonly options: Options, private readonly logItem: ILogItem, ) {} @@ -79,6 +81,14 @@ export class Member { return this.peerCall?.dataChannel; } + get deviceIndex(): number { + return this._deviceIndex; + } + + get eventTimestamp(): number { + return this._eventTimestamp; + } + /** @internal */ connect(localMedia: LocalMedia) { this.logItem.wrap("connect", () => { @@ -114,8 +124,10 @@ export class Member { } /** @internal */ - updateCallInfo(callDeviceMembership: CallDeviceMembership) { + updateCallInfo(callDeviceMembership: CallDeviceMembership, deviceIndex: number, eventTimestamp: number) { this.callDeviceMembership = callDeviceMembership; + this._deviceIndex = deviceIndex; + this._eventTimestamp = eventTimestamp; } /** @internal */