2021-07-27 12:27:59 -07:00
|
|
|
/*
|
|
|
|
Copyright 2021 New Vector Ltd
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
import EventEmitter from "events";
|
|
|
|
|
|
|
|
const CONF_ROOM = "me.robertlong.conf";
|
|
|
|
const CONF_PARTICIPANT = "me.robertlong.conf.participant";
|
2021-07-23 14:50:33 -07:00
|
|
|
const PARTICIPANT_TIMEOUT = 1000 * 5;
|
2021-07-21 23:28:01 -07:00
|
|
|
|
2021-07-27 11:40:19 -07:00
|
|
|
function waitForSync(client) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const onSync = (state) => {
|
|
|
|
if (state === "PREPARED") {
|
|
|
|
resolve();
|
|
|
|
client.removeListener("sync", onSync);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
client.on("sync", onSync);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export class ConferenceCallManager extends EventEmitter {
|
|
|
|
static async restore(homeserverUrl) {
|
|
|
|
try {
|
|
|
|
const authStore = localStorage.getItem("matrix-auth-store");
|
|
|
|
|
|
|
|
if (authStore) {
|
|
|
|
const { user_id, device_id, access_token } = JSON.parse(authStore);
|
|
|
|
|
|
|
|
const client = matrixcs.createClient({
|
|
|
|
baseUrl: homeserverUrl,
|
|
|
|
accessToken: access_token,
|
|
|
|
userId: user_id,
|
|
|
|
deviceId: device_id,
|
|
|
|
});
|
|
|
|
|
|
|
|
const manager = new ConferenceCallManager(client);
|
|
|
|
|
|
|
|
await client.startClient();
|
|
|
|
|
|
|
|
await waitForSync(client);
|
|
|
|
|
|
|
|
return manager;
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
localStorage.removeItem("matrix-auth-store");
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static async login(homeserverUrl, username, password) {
|
|
|
|
try {
|
|
|
|
const registrationClient = matrixcs.createClient(homeserverUrl);
|
|
|
|
|
|
|
|
const { user_id, device_id, access_token } =
|
|
|
|
await registrationClient.loginWithPassword(username, password);
|
|
|
|
|
|
|
|
const client = matrixcs.createClient({
|
|
|
|
baseUrl: homeserverUrl,
|
|
|
|
accessToken: access_token,
|
|
|
|
userId: user_id,
|
|
|
|
deviceId: device_id,
|
|
|
|
});
|
|
|
|
|
|
|
|
localStorage.setItem(
|
|
|
|
"matrix-auth-store",
|
|
|
|
JSON.stringify({ user_id, device_id, access_token })
|
|
|
|
);
|
|
|
|
|
|
|
|
const manager = new ConferenceCallManager(client);
|
|
|
|
|
|
|
|
await client.startClient();
|
|
|
|
|
|
|
|
await waitForSync(client);
|
|
|
|
|
|
|
|
return manager;
|
|
|
|
} catch (err) {
|
|
|
|
localStorage.removeItem("matrix-auth-store");
|
|
|
|
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static async register(homeserverUrl, username, password) {
|
|
|
|
try {
|
|
|
|
const registrationClient = matrixcs.createClient(homeserverUrl);
|
|
|
|
|
|
|
|
const { user_id, device_id, access_token } =
|
|
|
|
await registrationClient.register(username, password, null, {
|
|
|
|
type: "m.login.dummy",
|
|
|
|
});
|
|
|
|
|
|
|
|
const client = matrixcs.createClient({
|
|
|
|
baseUrl: homeserverUrl,
|
|
|
|
accessToken: access_token,
|
|
|
|
userId: user_id,
|
|
|
|
deviceId: device_id,
|
|
|
|
});
|
|
|
|
|
|
|
|
localStorage.setItem(
|
|
|
|
"matrix-auth-store",
|
|
|
|
JSON.stringify({ user_id, device_id, access_token })
|
|
|
|
);
|
|
|
|
|
|
|
|
const manager = new ConferenceCallManager(client);
|
|
|
|
|
|
|
|
await client.startClient();
|
|
|
|
|
|
|
|
await waitForSync(client);
|
|
|
|
|
|
|
|
return manager;
|
|
|
|
} catch (err) {
|
|
|
|
localStorage.removeItem("matrix-auth-store");
|
|
|
|
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(client) {
|
2021-07-21 23:28:01 -07:00
|
|
|
super();
|
|
|
|
this.client = client;
|
2021-07-23 14:50:33 -07:00
|
|
|
this.joined = false;
|
2021-07-26 16:01:13 -07:00
|
|
|
this.room = null;
|
2021-07-21 23:28:01 -07:00
|
|
|
this.localParticipant = {
|
2021-07-23 14:50:33 -07:00
|
|
|
local: true,
|
2021-07-21 23:28:01 -07:00
|
|
|
userId: client.getUserId(),
|
|
|
|
feed: null,
|
|
|
|
call: null,
|
|
|
|
muted: true,
|
|
|
|
};
|
|
|
|
this.participants = [this.localParticipant];
|
2021-07-27 16:27:04 -07:00
|
|
|
this.pendingCalls = [];
|
2021-07-28 16:14:38 -07:00
|
|
|
this.debugState = new Map();
|
|
|
|
this._setDebugState(client.getUserId(), "you");
|
|
|
|
this.client.on("event", this._onEvent);
|
2021-07-22 16:41:57 -07:00
|
|
|
this.client.on("RoomState.members", this._onMemberChanged);
|
|
|
|
this.client.on("Call.incoming", this._onIncomingCall);
|
2021-07-23 14:50:33 -07:00
|
|
|
}
|
2021-07-22 16:41:57 -07:00
|
|
|
|
2021-07-27 11:40:19 -07:00
|
|
|
join(roomId) {
|
2021-07-23 14:50:33 -07:00
|
|
|
this.joined = true;
|
2021-07-22 16:41:57 -07:00
|
|
|
|
2021-07-28 16:14:38 -07:00
|
|
|
this._addDebugEvent(this.client.getUserId(), "joined call");
|
|
|
|
|
2021-07-27 11:40:19 -07:00
|
|
|
this.roomId = roomId;
|
2021-07-26 16:01:13 -07:00
|
|
|
this.room = this.client.getRoom(this.roomId);
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
const activeConf = this.room.currentState
|
|
|
|
.getStateEvents(CONF_ROOM, "")
|
|
|
|
?.getContent()?.active;
|
|
|
|
|
|
|
|
if (!activeConf) {
|
|
|
|
this.client.sendStateEvent(this.roomId, CONF_ROOM, { active: true }, "");
|
|
|
|
}
|
|
|
|
|
2021-07-23 14:52:42 -07:00
|
|
|
this.room
|
|
|
|
.getMembers()
|
|
|
|
.forEach((member) => this._processMember(member.userId));
|
|
|
|
|
2021-07-27 16:27:04 -07:00
|
|
|
for (const { call, onHangup, onReplaced } of this.pendingCalls) {
|
|
|
|
call.removeListener("hangup", onHangup);
|
|
|
|
call.removeListener("replaced", onReplaced);
|
|
|
|
const userId = call.opponentMember.userId;
|
|
|
|
this._addCall(call, userId);
|
|
|
|
call.answer();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.pendingCalls = [];
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
this._updateParticipantState();
|
|
|
|
}
|
|
|
|
|
2021-07-28 16:14:38 -07:00
|
|
|
_onEvent = (event) => {
|
|
|
|
const type = event.getType();
|
|
|
|
|
|
|
|
if (type.startsWith("m.call.") || type.startsWith("me.robertlong.conf")) {
|
|
|
|
const content = event.getContent();
|
2021-07-29 11:24:22 -07:00
|
|
|
const details = { content };
|
2021-07-28 16:14:38 -07:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case "m.call.invite":
|
|
|
|
case "m.call.candidates":
|
|
|
|
case "m.call.answer":
|
|
|
|
case "m.call.hangup":
|
|
|
|
case "m.call.select_answer":
|
|
|
|
details.callId = content.call_id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._addDebugEvent(event.getSender(), type, details);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
_updateParticipantState = () => {
|
|
|
|
const userId = this.client.getUserId();
|
|
|
|
const currentMemberState = this.room.currentState.getStateEvents(
|
|
|
|
"m.room.member",
|
|
|
|
userId
|
|
|
|
);
|
|
|
|
|
|
|
|
this.client.sendStateEvent(
|
|
|
|
this.roomId,
|
|
|
|
"m.room.member",
|
|
|
|
{
|
|
|
|
...currentMemberState.getContent(),
|
|
|
|
[CONF_PARTICIPANT]: new Date().getTime(),
|
|
|
|
},
|
|
|
|
userId
|
|
|
|
);
|
|
|
|
|
|
|
|
this._participantStateTimeout = setTimeout(
|
|
|
|
this._updateParticipantState,
|
|
|
|
PARTICIPANT_TIMEOUT
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
_onMemberChanged = (_event, _state, member) => {
|
|
|
|
this._processMember(member.userId);
|
|
|
|
};
|
|
|
|
|
|
|
|
_processMember(userId) {
|
2021-07-23 14:50:33 -07:00
|
|
|
const localUserId = this.client.getUserId();
|
|
|
|
|
2021-07-23 16:11:42 -07:00
|
|
|
if (userId === localUserId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't process members until we've joined
|
|
|
|
if (!this.joined) {
|
2021-07-21 23:28:01 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const participant = this.participants.find((p) => p.userId === userId);
|
|
|
|
|
2021-07-23 16:11:42 -07:00
|
|
|
if (participant) {
|
|
|
|
// Member has already been processed
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
const memberStateEvent = this.room.currentState.getStateEvents(
|
|
|
|
"m.room.member",
|
|
|
|
userId
|
|
|
|
);
|
|
|
|
const participantTimeout = memberStateEvent.getContent()[CONF_PARTICIPANT];
|
|
|
|
|
|
|
|
if (
|
|
|
|
typeof participantTimeout === "number" &&
|
2021-07-23 14:50:33 -07:00
|
|
|
new Date().getTime() - participantTimeout > PARTICIPANT_TIMEOUT
|
2021-07-21 23:28:01 -07:00
|
|
|
) {
|
2021-07-23 16:11:42 -07:00
|
|
|
// Member is inactive so don't call them.
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugState(userId, "inactive");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only initiate a call with a user who has a userId that is lexicographically
|
|
|
|
// less than your own. Otherwise, that user will call you.
|
|
|
|
if (userId < localUserId) {
|
|
|
|
this._setDebugState(userId, "waiting for invite");
|
2021-07-21 23:28:01 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-23 16:11:42 -07:00
|
|
|
const call = this.client.createCall(this.roomId, userId);
|
|
|
|
this._addCall(call, userId);
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugState(userId, "calling");
|
|
|
|
this._addDebugEvent(this.client.getUserId(), "placeVideoCall", {
|
|
|
|
callId: call.callId,
|
|
|
|
to: userId,
|
|
|
|
});
|
2021-07-23 16:11:42 -07:00
|
|
|
call.placeVideoCall();
|
2021-07-21 23:28:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
_onIncomingCall = (call) => {
|
2021-07-28 16:14:38 -07:00
|
|
|
this._addDebugEvent(call.opponentMember.userId, "incoming call", {
|
|
|
|
callId: call.callId,
|
|
|
|
});
|
|
|
|
|
2021-07-23 14:50:33 -07:00
|
|
|
if (!this.joined) {
|
2021-07-27 16:27:04 -07:00
|
|
|
const onHangup = (call) => {
|
|
|
|
const index = this.pendingCalls.findIndex((p) => p.call === call);
|
|
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
this.pendingCalls.splice(index, 1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const onReplaced = (call, newCall) => {
|
|
|
|
const index = this.pendingCalls.findIndex((p) => p.call === call);
|
|
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
this.pendingCalls.splice(index, 1, {
|
|
|
|
call: newCall,
|
|
|
|
onHangup: () => onHangup(newCall),
|
|
|
|
onReplaced: (nextCall) => onReplaced(newCall, nextCall),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.pendingCalls.push({
|
|
|
|
call,
|
|
|
|
onHangup: () => onHangup(call),
|
|
|
|
onReplaced: (newCall) => onReplaced(call, newCall),
|
|
|
|
});
|
|
|
|
call.on("hangup", onHangup);
|
|
|
|
call.on("replaced", onReplaced);
|
|
|
|
|
2021-07-23 14:50:33 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-28 18:09:04 -07:00
|
|
|
const userId = call.opponentMember.userId;
|
|
|
|
this._addCall(call, userId);
|
|
|
|
this._setDebugState(userId, "answered");
|
|
|
|
this._addDebugEvent(userId, "answer", { callId: call.callId });
|
|
|
|
call.answer();
|
2021-07-21 23:28:01 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
_addCall(call, userId) {
|
2021-07-27 16:27:04 -07:00
|
|
|
if (call.state === "ended") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-22 16:41:57 -07:00
|
|
|
const existingCall = this.participants.find(
|
2021-07-27 13:26:18 -07:00
|
|
|
(p) => !p.local && p.call && p.call.callId === call.callId
|
2021-07-22 16:41:57 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
if (existingCall) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
this.participants.push({
|
2021-07-22 16:41:57 -07:00
|
|
|
userId,
|
2021-07-21 23:28:01 -07:00
|
|
|
feed: null,
|
|
|
|
call,
|
|
|
|
});
|
|
|
|
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(userId, call.callId);
|
|
|
|
this._addDebugEvent(userId, "add participant");
|
2021-07-23 16:11:42 -07:00
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
call.on("feeds_changed", () => this._onCallFeedsChanged(call));
|
|
|
|
call.on("hangup", () => this._onCallHangup(call));
|
2021-07-22 16:41:57 -07:00
|
|
|
|
|
|
|
const onReplaced = (newCall) => {
|
|
|
|
this._onCallReplaced(call, newCall);
|
|
|
|
call.removeListener("replaced", onReplaced);
|
|
|
|
};
|
|
|
|
|
|
|
|
call.on("replaced", onReplaced);
|
2021-07-21 23:28:01 -07:00
|
|
|
this._onCallFeedsChanged(call);
|
|
|
|
|
|
|
|
this.emit("participants_changed");
|
|
|
|
}
|
|
|
|
|
|
|
|
_onCallFeedsChanged = (call) => {
|
|
|
|
const localFeeds = call.getLocalFeeds();
|
|
|
|
|
|
|
|
let participantsChanged = false;
|
|
|
|
|
|
|
|
if (!this.localParticipant.feed && localFeeds.length > 0) {
|
2021-07-27 13:26:18 -07:00
|
|
|
this.localParticipant.call = call;
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(this.localParticipant.userId, call.callId);
|
2021-07-21 23:28:01 -07:00
|
|
|
this.localParticipant.feed = localFeeds[0];
|
|
|
|
participantsChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const remoteFeeds = call.getRemoteFeeds();
|
2021-07-27 13:26:18 -07:00
|
|
|
const remoteParticipant = this.participants.find(
|
|
|
|
(p) => !p.local && p.call === call
|
|
|
|
);
|
2021-07-21 23:28:01 -07:00
|
|
|
|
|
|
|
if (remoteFeeds.length > 0 && remoteParticipant.feed !== remoteFeeds[0]) {
|
|
|
|
remoteParticipant.feed = remoteFeeds[0];
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugState(call.opponentMember.userId, "streaming");
|
2021-07-21 23:28:01 -07:00
|
|
|
participantsChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (participantsChanged) {
|
|
|
|
this.emit("participants_changed");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
_onCallHangup = (call) => {
|
2021-07-28 16:14:38 -07:00
|
|
|
this._addDebugEvent(call.opponentMember.userId, "hangup", {
|
|
|
|
callId: call.callId,
|
|
|
|
reason: call.hangupReason,
|
|
|
|
});
|
2021-07-22 16:41:57 -07:00
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
if (call.hangupReason === "replaced") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugState(call.opponentMember.userId, "hungup");
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
const participantIndex = this.participants.findIndex(
|
2021-07-27 13:26:18 -07:00
|
|
|
(p) => !p.local && p.call === call
|
2021-07-21 23:28:01 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
if (participantIndex === -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.participants.splice(participantIndex, 1);
|
|
|
|
|
2021-07-27 13:26:18 -07:00
|
|
|
if (this.localParticipant.call === call) {
|
|
|
|
const newLocalCallParticipant = this.participants.find(
|
|
|
|
(p) => !p.local && p.call
|
|
|
|
);
|
|
|
|
|
|
|
|
if (newLocalCallParticipant) {
|
|
|
|
const localFeeds = call.getLocalFeeds();
|
|
|
|
|
|
|
|
if (localFeeds.length > 0) {
|
|
|
|
this.localParticipant.call = call;
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(this.localParticipant.userId, call.callId);
|
2021-07-27 13:26:18 -07:00
|
|
|
this.localParticipant.feed = localFeeds[0];
|
|
|
|
} else {
|
|
|
|
this.localParticipant.call = null;
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(this.localParticipant.userId, null);
|
2021-07-27 13:26:18 -07:00
|
|
|
this.localParticipant.feed = null;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.localParticipant.call = null;
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(this.localParticipant.userId, null);
|
2021-07-27 13:26:18 -07:00
|
|
|
this.localParticipant.feed = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-21 23:28:01 -07:00
|
|
|
this.emit("participants_changed");
|
|
|
|
};
|
|
|
|
|
|
|
|
_onCallReplaced = (call, newCall) => {
|
2021-07-28 16:14:38 -07:00
|
|
|
this._addDebugEvent(call.opponentMember.userId, "replaced", {
|
|
|
|
callId: call.callId,
|
|
|
|
newCallId: newCall.callId,
|
|
|
|
});
|
2021-07-21 23:28:01 -07:00
|
|
|
|
2021-07-27 13:26:18 -07:00
|
|
|
const remoteParticipant = this.participants.find(
|
|
|
|
(p) => !p.local && p.call === call
|
|
|
|
);
|
2021-07-21 23:28:01 -07:00
|
|
|
|
|
|
|
remoteParticipant.call = newCall;
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(remoteParticipant.userId, newCall.callId);
|
2021-07-21 23:28:01 -07:00
|
|
|
|
|
|
|
newCall.on("feeds_changed", () => this._onCallFeedsChanged(newCall));
|
|
|
|
newCall.on("hangup", () => this._onCallHangup(newCall));
|
|
|
|
newCall.on("replaced", (nextCall) =>
|
|
|
|
this._onCallReplaced(newCall, nextCall)
|
|
|
|
);
|
|
|
|
this._onCallFeedsChanged(newCall);
|
|
|
|
|
|
|
|
this.emit("participants_changed");
|
|
|
|
};
|
2021-07-27 13:26:18 -07:00
|
|
|
|
|
|
|
leaveCall() {
|
2021-07-27 15:49:00 -07:00
|
|
|
const userId = this.client.getUserId();
|
|
|
|
const currentMemberState = this.room.currentState.getStateEvents(
|
|
|
|
"m.room.member",
|
|
|
|
userId
|
|
|
|
);
|
|
|
|
|
|
|
|
this.client.sendStateEvent(
|
|
|
|
this.roomId,
|
|
|
|
"m.room.member",
|
|
|
|
{
|
|
|
|
...currentMemberState.getContent(),
|
|
|
|
[CONF_PARTICIPANT]: null,
|
|
|
|
},
|
|
|
|
userId
|
|
|
|
);
|
|
|
|
|
2021-07-27 13:26:18 -07:00
|
|
|
for (const participant of this.participants) {
|
|
|
|
if (!participant.local && participant.call) {
|
|
|
|
participant.call.hangup("user_hangup", false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.joined = false;
|
|
|
|
this.participants = [this.localParticipant];
|
|
|
|
this.localParticipant.feed = null;
|
|
|
|
this.localParticipant.call = null;
|
2021-07-28 16:14:38 -07:00
|
|
|
this._setDebugCallId(this.localParticipant.userId, null);
|
2021-07-27 15:49:00 -07:00
|
|
|
|
2021-07-27 13:26:18 -07:00
|
|
|
this.emit("participants_changed");
|
|
|
|
}
|
2021-07-28 16:14:38 -07:00
|
|
|
|
|
|
|
_addDebugEvent(sender, type, content) {
|
|
|
|
if (!this.debugState.has(sender)) {
|
|
|
|
this.debugState.set(sender, {
|
|
|
|
callId: null,
|
|
|
|
state: "unknown",
|
|
|
|
events: [{ type, ...content }],
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
const { events } = this.debugState.get(sender);
|
|
|
|
events.push({ type, ...content });
|
|
|
|
}
|
|
|
|
|
|
|
|
this.emit("debug");
|
|
|
|
}
|
|
|
|
|
|
|
|
_setDebugState(userId, state) {
|
|
|
|
if (!this.debugState.has(userId)) {
|
|
|
|
this.debugState.set(userId, { state, callId: null, events: [] });
|
|
|
|
} else {
|
|
|
|
const userState = this.debugState.get(userId);
|
|
|
|
userState.state = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.emit("debug");
|
|
|
|
}
|
|
|
|
|
|
|
|
_setDebugCallId(userId, callId) {
|
|
|
|
if (!this.debugState.has(userId)) {
|
|
|
|
this.debugState.set(userId, { state: "unknown", callId, events: [] });
|
|
|
|
} else {
|
|
|
|
const userState = this.debugState.get(userId);
|
|
|
|
userState.callId = callId;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.emit("debug");
|
|
|
|
}
|
2021-07-21 23:28:01 -07:00
|
|
|
}
|