forked from mystiq/hydrogen-web
update call member info with room member info
This commit is contained in:
parent
a52740ed1b
commit
90b6a5ccb6
4 changed files with 53 additions and 18 deletions
|
@ -117,7 +117,10 @@ class OwnMemberViewModel extends ViewModel<OwnMemberOptions> implements IStreamV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type MemberOptions = BaseOptions & {member: Member, mediaRepository: MediaRepository};
|
type MemberOptions = BaseOptions & {
|
||||||
|
member: Member,
|
||||||
|
mediaRepository: MediaRepository
|
||||||
|
};
|
||||||
|
|
||||||
export class CallMemberViewModel extends ViewModel<MemberOptions> implements IStreamViewModel {
|
export class CallMemberViewModel extends ViewModel<MemberOptions> implements IStreamViewModel {
|
||||||
get stream(): Stream | undefined {
|
get stream(): Stream | undefined {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {EventType, CallIntent} from "./callEventTypes";
|
||||||
import {GroupCall} from "./group/GroupCall";
|
import {GroupCall} from "./group/GroupCall";
|
||||||
import {makeId} from "../common";
|
import {makeId} from "../common";
|
||||||
import {CALL_LOG_TYPE} 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 {LocalMedia} from "./LocalMedia";
|
||||||
import type {Room} from "../room/Room";
|
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 {CallEntry} from "../storage/idb/stores/CallStore";
|
||||||
import type {Clock} from "../../platform/web/dom/Clock";
|
import type {Clock} from "../../platform/web/dom/Clock";
|
||||||
import type {RoomStateHandler} from "../room/state/types";
|
import type {RoomStateHandler} from "../room/state/types";
|
||||||
|
import type {MemberSync} from "../room/timeline/persistence/MemberWriter";
|
||||||
|
|
||||||
export type Options = Omit<GroupCallOptions, "emitUpdate" | "createTimeout"> & {
|
export type Options = Omit<GroupCallOptions, "emitUpdate" | "createTimeout"> & {
|
||||||
clock: Clock
|
clock: Clock
|
||||||
|
@ -77,7 +79,7 @@ export class CallHandler implements RoomStateHandler {
|
||||||
const names = this.options.storage.storeNames;
|
const names = this.options.storage.storeNames;
|
||||||
const txn = await this.options.storage.readTxn([
|
const txn = await this.options.storage.readTxn([
|
||||||
names.calls,
|
names.calls,
|
||||||
names.roomState
|
names.roomState,
|
||||||
]);
|
]);
|
||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
@ -97,15 +99,17 @@ export class CallHandler implements RoomStateHandler {
|
||||||
}));
|
}));
|
||||||
const roomIds = Array.from(new Set(callEntries.map(e => e.roomId)));
|
const roomIds = Array.from(new Set(callEntries.map(e => e.roomId)));
|
||||||
await Promise.all(roomIds.map(async roomId => {
|
await Promise.all(roomIds.map(async roomId => {
|
||||||
// const ownCallsMemberEvent = await txn.roomState.get(roomId, EventType.GroupCallMember, this.options.ownUserId);
|
// TODO: don't load all members until we need them
|
||||||
// if (ownCallsMemberEvent) {
|
|
||||||
// this.handleCallMemberEvent(ownCallsMemberEvent.event, log);
|
|
||||||
// }
|
|
||||||
const callsMemberEvents = await txn.roomState.getAllForType(roomId, EventType.GroupCallMember);
|
const callsMemberEvents = await txn.roomState.getAllForType(roomId, EventType.GroupCallMember);
|
||||||
for (const entry of callsMemberEvents) {
|
await Promise.all(callsMemberEvents.map(async entry => {
|
||||||
this.handleCallMemberEvent(entry.event, roomId, log);
|
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);
|
||||||
}
|
}
|
||||||
// TODO: we should be loading the other members as well at some point
|
}
|
||||||
|
}));
|
||||||
}));
|
}));
|
||||||
log.set("newSize", this._calls.size);
|
log.set("newSize", this._calls.size);
|
||||||
});
|
});
|
||||||
|
@ -144,12 +148,15 @@ export class CallHandler implements RoomStateHandler {
|
||||||
// TODO: check and poll turn server credentials here
|
// TODO: check and poll turn server credentials here
|
||||||
|
|
||||||
/** @internal */
|
/** @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) {
|
if (event.type === EventType.GroupCall) {
|
||||||
this.handleCallEvent(event, room.id, txn, log);
|
this.handleCallEvent(event, room.id, txn, log);
|
||||||
}
|
}
|
||||||
if (event.type === EventType.GroupCallMember) {
|
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<string, MemberChange>) {
|
updateRoomMembers(room: Room, memberChanges: Map<string, MemberChange>) {
|
||||||
// TODO: also have map for roomId to calls, so we can easily update members
|
// 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
|
// 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 */
|
/** @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 userId = event.state_key;
|
||||||
const roomMemberKey = getRoomMemberKey(roomId, userId)
|
const roomMemberKey = getRoomMemberKey(roomId, userId)
|
||||||
const calls = event.content["m.calls"] ?? [];
|
const calls = event.content["m.calls"] ?? [];
|
||||||
|
@ -201,7 +213,7 @@ export class CallHandler implements RoomStateHandler {
|
||||||
const callId = call["m.call_id"];
|
const callId = call["m.call_id"];
|
||||||
const groupCall = this._calls.get(callId);
|
const groupCall = this._calls.get(callId);
|
||||||
// TODO: also check the member when receiving the m.call event
|
// 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<string>(calls.map(call => call["m.call_id"]));
|
const newCallIdsMemberOf = new Set<string>(calls.map(call => call["m.call_id"]));
|
||||||
let previousCallIdsMemberOf = this.roomMemberToCallIds.get(roomMemberKey);
|
let previousCallIdsMemberOf = this.roomMemberToCallIds.get(roomMemberKey);
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {ObservableMap} from "../../../observable/map/ObservableMap";
|
||||||
import {Member} from "./Member";
|
import {Member} from "./Member";
|
||||||
import {LocalMedia} from "../LocalMedia";
|
import {LocalMedia} from "../LocalMedia";
|
||||||
import {MuteSettings, CALL_LOG_TYPE} from "../common";
|
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 {EventEmitter} from "../../../utils/EventEmitter";
|
||||||
import {EventType, CallIntent} from "../callEventTypes";
|
import {EventType, CallIntent} from "../callEventTypes";
|
||||||
|
|
||||||
|
@ -258,7 +258,20 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
updateMembership(userId: string, callMembership: CallMembership, syncLog: ILogItem) {
|
updateRoomMembers(memberChanges: Map<string, MemberChange>) {
|
||||||
|
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 => {
|
syncLog.wrap({l: "update call membership", t: CALL_LOG_TYPE, id: this.id, userId}, log => {
|
||||||
const devices = callMembership["m.devices"];
|
const devices = callMembership["m.devices"];
|
||||||
const previousDeviceIds = this.getDeviceIdsForUserId(userId);
|
const previousDeviceIds = this.getDeviceIdsForUserId(userId);
|
||||||
|
@ -290,7 +303,7 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||||
}
|
}
|
||||||
log.set("add", true);
|
log.set("add", true);
|
||||||
member = new Member(
|
member = new Member(
|
||||||
RoomMember.fromUserId(this.roomId, userId, "join"),
|
roomMember,
|
||||||
device, this._memberOptions,
|
device, this._memberOptions,
|
||||||
);
|
);
|
||||||
this._members.add(memberKey, member);
|
this._members.add(memberKey, member);
|
||||||
|
|
|
@ -68,7 +68,7 @@ export class Member {
|
||||||
private connection?: MemberConnection;
|
private connection?: MemberConnection;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly member: RoomMember,
|
public member: RoomMember,
|
||||||
private callDeviceMembership: CallDeviceMembership,
|
private callDeviceMembership: CallDeviceMembership,
|
||||||
private readonly options: Options,
|
private readonly options: Options,
|
||||||
) {}
|
) {}
|
||||||
|
@ -180,6 +180,13 @@ export class Member {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @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 */
|
/** @internal */
|
||||||
emitUpdateFromPeerCall = (peerCall: PeerCall, params: any, log: ILogItem): void => {
|
emitUpdateFromPeerCall = (peerCall: PeerCall, params: any, log: ILogItem): void => {
|
||||||
const connection = this.connection!;
|
const connection = this.connection!;
|
||||||
|
|
Loading…
Reference in a new issue