You've already forked matrix-react-sdk
mirror of
https://github.com/matrix-org/matrix-react-sdk.git
synced 2025-11-05 23:10:41 +03:00
Line 1 / 2 Support
Support one active call plus one call on hold
This commit is contained in:
@@ -81,6 +81,7 @@ import Analytics from './Analytics';
|
||||
import CountlyAnalytics from "./CountlyAnalytics";
|
||||
import {UIFeature} from "./settings/UIFeature";
|
||||
import { CallError } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { logger } from 'matrix-js-sdk/src/logger';
|
||||
|
||||
enum AudioID {
|
||||
Ring = 'ringAudio',
|
||||
@@ -115,7 +116,7 @@ function getRemoteAudioElement(): HTMLAudioElement {
|
||||
}
|
||||
|
||||
export default class CallHandler {
|
||||
private calls = new Map<string, MatrixCall>();
|
||||
private calls = new Map<string, MatrixCall>(); // roomId -> call
|
||||
private audioPromises = new Map<AudioID, Promise<void>>();
|
||||
|
||||
static sharedInstance() {
|
||||
@@ -175,6 +176,28 @@ export default class CallHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
getAllActiveCalls() {
|
||||
const activeCalls = [];
|
||||
|
||||
for (const call of this.calls.values()) {
|
||||
if (call.state !== CallState.Ended && call.state !== CallState.Ringing) {
|
||||
activeCalls.push(call);
|
||||
}
|
||||
}
|
||||
return activeCalls;
|
||||
}
|
||||
|
||||
getAllActiveCallsNotInRoom(notInThisRoomId) {
|
||||
const callsNotInThatRoom = [];
|
||||
|
||||
for (const [roomId, call] of this.calls.entries()) {
|
||||
if (roomId !== notInThisRoomId && call.state !== CallState.Ended) {
|
||||
callsNotInThatRoom.push(call);
|
||||
}
|
||||
}
|
||||
return callsNotInThatRoom;
|
||||
}
|
||||
|
||||
play(audioId: AudioID) {
|
||||
// TODO: Attach an invisible element for this instead
|
||||
// which listens?
|
||||
@@ -425,6 +448,8 @@ export default class CallHandler {
|
||||
this.setCallListeners(call);
|
||||
this.setCallAudioElement(call);
|
||||
|
||||
this.setActiveCallRoomId(roomId);
|
||||
|
||||
if (type === PlaceCallType.Voice) {
|
||||
call.placeVoiceCall();
|
||||
} else if (type === 'video') {
|
||||
@@ -453,14 +478,6 @@ export default class CallHandler {
|
||||
switch (payload.action) {
|
||||
case 'place_call':
|
||||
{
|
||||
if (this.getAnyActiveCall()) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
|
||||
title: _t('Existing Call'),
|
||||
description: _t('You are already in a call.'),
|
||||
});
|
||||
return; // don't allow >1 call to be placed.
|
||||
}
|
||||
|
||||
// if the runtime env doesn't do VoIP, whine.
|
||||
if (!MatrixClientPeg.get().supportsVoip()) {
|
||||
Modal.createTrackedDialog('Call Handler', 'VoIP is unsupported', ErrorDialog, {
|
||||
@@ -470,6 +487,15 @@ export default class CallHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't allow > 2 calls to be placed.
|
||||
if (this.getAllActiveCalls().length > 1) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
|
||||
title: _t('Too Many Calls'),
|
||||
description: _t("You've reached the maximum number of simultaneous calls."),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const room = MatrixClientPeg.get().getRoom(payload.room_id);
|
||||
if (!room) {
|
||||
console.error("Room %s does not exist.", payload.room_id);
|
||||
@@ -513,24 +539,21 @@ export default class CallHandler {
|
||||
break;
|
||||
case 'incoming_call':
|
||||
{
|
||||
if (this.getAnyActiveCall()) {
|
||||
// ignore multiple incoming calls. in future, we may want a line-1/line-2 setup.
|
||||
// we avoid rejecting with "busy" in case the user wants to answer it on a different device.
|
||||
// in future we could signal a "local busy" as a warning to the caller.
|
||||
// see https://github.com/vector-im/vector-web/issues/1964
|
||||
return;
|
||||
}
|
||||
|
||||
// if the runtime env doesn't do VoIP, stop here.
|
||||
if (!MatrixClientPeg.get().supportsVoip()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const call = payload.call as MatrixCall;
|
||||
|
||||
if (this.getCallForRoom(call.roomId)) {
|
||||
// ignore multiple incoming calls to the same room
|
||||
return;
|
||||
}
|
||||
|
||||
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
|
||||
this.calls.set(call.roomId, call)
|
||||
this.setCallListeners(call);
|
||||
this.setCallAudioElement(call);
|
||||
}
|
||||
break;
|
||||
case 'hangup':
|
||||
@@ -549,8 +572,19 @@ export default class CallHandler {
|
||||
if (!this.calls.has(payload.room_id)) {
|
||||
return; // no call to answer
|
||||
}
|
||||
|
||||
if (this.getAllActiveCalls().length > 1) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
|
||||
title: _t('Too Many Calls'),
|
||||
description: _t("You've reached the maximum number of simultaneous calls."),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const call = this.calls.get(payload.room_id);
|
||||
call.answer();
|
||||
this.setCallAudioElement(call);
|
||||
this.setActiveCallRoomId(payload.room_id);
|
||||
CountlyAnalytics.instance.trackJoinCall(payload.room_id, call.type === CallType.Video, false);
|
||||
dis.dispatch({
|
||||
action: "view_room",
|
||||
@@ -561,6 +595,21 @@ export default class CallHandler {
|
||||
}
|
||||
}
|
||||
|
||||
setActiveCallRoomId(activeCallRoomId: string) {
|
||||
logger.info("Setting call in room " + activeCallRoomId + " active");
|
||||
|
||||
for (const [roomId, call] of this.calls.entries()) {
|
||||
if (call.state === CallState.Ended) continue;
|
||||
|
||||
if (roomId === activeCallRoomId) {
|
||||
call.setRemoteOnHold(false);
|
||||
} else {
|
||||
logger.info("Holding call in room " + roomId + " because another call is being set active");
|
||||
call.setRemoteOnHold(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async startCallApp(roomId: string, type: string) {
|
||||
dis.dispatch({
|
||||
action: 'appsDrawer',
|
||||
|
||||
Reference in New Issue
Block a user