From 90b6a5ccb625066325b4a45e4ae3fc1c1fb3b026 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Thu, 2 Jun 2022 15:56:23 +0200 Subject: [PATCH] update call member info with room member info --- src/domain/session/room/CallViewModel.ts | 5 +++- src/matrix/calls/CallHandler.ts | 38 ++++++++++++++++-------- src/matrix/calls/group/GroupCall.ts | 19 ++++++++++-- src/matrix/calls/group/Member.ts | 9 +++++- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/domain/session/room/CallViewModel.ts b/src/domain/session/room/CallViewModel.ts index 08bc3691..a770ddbe 100644 --- a/src/domain/session/room/CallViewModel.ts +++ b/src/domain/session/room/CallViewModel.ts @@ -117,7 +117,10 @@ class OwnMemberViewModel extends ViewModel implements IStreamV } } -type MemberOptions = BaseOptions & {member: Member, mediaRepository: MediaRepository}; +type MemberOptions = BaseOptions & { + member: Member, + mediaRepository: MediaRepository +}; export class CallMemberViewModel extends ViewModel implements IStreamViewModel { get stream(): Stream | undefined { diff --git a/src/matrix/calls/CallHandler.ts b/src/matrix/calls/CallHandler.ts index e585bb40..7524200c 100644 --- a/src/matrix/calls/CallHandler.ts +++ b/src/matrix/calls/CallHandler.ts @@ -22,6 +22,7 @@ import {EventType, CallIntent} from "./callEventTypes"; import {GroupCall} from "./group/GroupCall"; import {makeId} from "../common"; import {CALL_LOG_TYPE} from "./common"; +import {EVENT_TYPE as MEMBER_EVENT_TYPE, RoomMember} from "../room/members/RoomMember"; import type {LocalMedia} from "./LocalMedia"; import type {Room} from "../room/Room"; @@ -36,6 +37,7 @@ import type {Transaction} from "../storage/idb/Transaction"; import type {CallEntry} from "../storage/idb/stores/CallStore"; import type {Clock} from "../../platform/web/dom/Clock"; import type {RoomStateHandler} from "../room/state/types"; +import type {MemberSync} from "../room/timeline/persistence/MemberWriter"; export type Options = Omit & { clock: Clock @@ -77,7 +79,7 @@ export class CallHandler implements RoomStateHandler { const names = this.options.storage.storeNames; const txn = await this.options.storage.readTxn([ names.calls, - names.roomState + names.roomState, ]); return txn; } @@ -97,15 +99,17 @@ export class CallHandler implements RoomStateHandler { })); const roomIds = Array.from(new Set(callEntries.map(e => e.roomId))); await Promise.all(roomIds.map(async roomId => { - // const ownCallsMemberEvent = await txn.roomState.get(roomId, EventType.GroupCallMember, this.options.ownUserId); - // if (ownCallsMemberEvent) { - // this.handleCallMemberEvent(ownCallsMemberEvent.event, log); - // } + // TODO: don't load all members until we need them const callsMemberEvents = await txn.roomState.getAllForType(roomId, EventType.GroupCallMember); - for (const entry of callsMemberEvents) { - this.handleCallMemberEvent(entry.event, roomId, log); - } - // TODO: we should be loading the other members as well at some point + await Promise.all(callsMemberEvents.map(async entry => { + const roomMemberState = await txn.roomState.get(roomId, MEMBER_EVENT_TYPE, entry.event.sender); + if (roomMemberState) { + const roomMember = RoomMember.fromMemberEvent(roomMemberState.event); + if (roomMember) { + this.handleCallMemberEvent(entry.event, roomMember, roomId, log); + } + } + })); })); log.set("newSize", this._calls.size); }); @@ -144,12 +148,15 @@ export class CallHandler implements RoomStateHandler { // TODO: check and poll turn server credentials here /** @internal */ - handleRoomState(room: Room, event: StateEvent, txn: Transaction, log: ILogItem) { + async handleRoomState(room: Room, event: StateEvent, memberSync: MemberSync, txn: Transaction, log: ILogItem) { if (event.type === EventType.GroupCall) { this.handleCallEvent(event, room.id, txn, log); } if (event.type === EventType.GroupCallMember) { - this.handleCallMemberEvent(event, room.id, log); + const member: RoomMember | undefined = await memberSync.lookupMemberAtEvent(event.sender, event, txn); + if (member) { // should always have a member? + this.handleCallMemberEvent(event, member, room.id, log); + } } } @@ -157,6 +164,11 @@ export class CallHandler implements RoomStateHandler { updateRoomMembers(room: Room, memberChanges: Map) { // TODO: also have map for roomId to calls, so we can easily update members // we will also need this to get the call for a room + for (const call of this._calls.values()) { + if (call.roomId === room.id) { + call.updateRoomMembers(memberChanges); + } + } } /** @internal */ @@ -193,7 +205,7 @@ export class CallHandler implements RoomStateHandler { } } - private handleCallMemberEvent(event: StateEvent, roomId: string, log: ILogItem) { + private handleCallMemberEvent(event: StateEvent, member: RoomMember, roomId: string, log: ILogItem) { const userId = event.state_key; const roomMemberKey = getRoomMemberKey(roomId, userId) const calls = event.content["m.calls"] ?? []; @@ -201,7 +213,7 @@ export class CallHandler implements RoomStateHandler { 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, member, call, log); }; const newCallIdsMemberOf = new Set(calls.map(call => call["m.call_id"])); let previousCallIdsMemberOf = this.roomMemberToCallIds.get(roomMemberKey); diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index ddc0b517..ebacf844 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -18,7 +18,7 @@ import {ObservableMap} from "../../../observable/map/ObservableMap"; import {Member} from "./Member"; import {LocalMedia} from "../LocalMedia"; import {MuteSettings, CALL_LOG_TYPE} from "../common"; -import {RoomMember} from "../../room/members/RoomMember"; +import {MemberChange, RoomMember} from "../../room/members/RoomMember"; import {EventEmitter} from "../../../utils/EventEmitter"; import {EventType, CallIntent} from "../callEventTypes"; @@ -258,7 +258,20 @@ export class GroupCall extends EventEmitter<{change: never}> { } /** @internal */ - updateMembership(userId: string, callMembership: CallMembership, syncLog: ILogItem) { + updateRoomMembers(memberChanges: Map) { + for (const change of memberChanges.values()) { + const {member} = change; + for (const callMember of this._members.values()) { + // find all call members for a room member (can be multiple, for every device) + if (callMember.userId === member.userId) { + callMember.updateRoomMember(member); + } + } + } + } + + /** @internal */ + updateMembership(userId: string, roomMember: RoomMember, callMembership: CallMembership, syncLog: ILogItem) { syncLog.wrap({l: "update call membership", t: CALL_LOG_TYPE, id: this.id, userId}, log => { const devices = callMembership["m.devices"]; const previousDeviceIds = this.getDeviceIdsForUserId(userId); @@ -290,7 +303,7 @@ export class GroupCall extends EventEmitter<{change: never}> { } log.set("add", true); member = new Member( - RoomMember.fromUserId(this.roomId, userId, "join"), + roomMember, device, this._memberOptions, ); this._members.add(memberKey, member); diff --git a/src/matrix/calls/group/Member.ts b/src/matrix/calls/group/Member.ts index 541cdf13..2a4eefb7 100644 --- a/src/matrix/calls/group/Member.ts +++ b/src/matrix/calls/group/Member.ts @@ -68,7 +68,7 @@ export class Member { private connection?: MemberConnection; constructor( - public readonly member: RoomMember, + public member: RoomMember, private callDeviceMembership: CallDeviceMembership, private readonly options: Options, ) {} @@ -179,6 +179,13 @@ export class Member { this.connection.logItem.refDetached(causeItem); } } + + /** @internal */ + updateRoomMember(roomMember: RoomMember) { + this.member = roomMember; + // TODO: this emits an update during the writeSync phase, which we usually try to avoid + this.options.emitUpdate(this); + } /** @internal */ emitUpdateFromPeerCall = (peerCall: PeerCall, params: any, log: ILogItem): void => {