Implement call hold

Currently just by adding /holdcall and /unholdcall slash commands

The only place the hold status of the call is currently represented
is when the call is a voice call and you're viewing a different room:
it's not wired up when you're viewing the room because that currently
uses the room status bar which it won't do with the new UI.

Also convert VideoFeed to typescript, and remove videoview because
it essentially just managed the fullscreen functionality, but we'll
want and 'on hold' representation (and probably chrome for hagnup etc)
in the fullscreen UI too, so let's just make CallView the thing that
gets fullscreened.
This commit is contained in:
David Baker
2020-10-29 17:56:24 +00:00
parent ca4e7202ae
commit f828c6d494
15 changed files with 287 additions and 330 deletions
+22 -3
View File
@@ -59,8 +59,7 @@ import {MatrixClientPeg} from './MatrixClientPeg';
import PlatformPeg from './PlatformPeg';
import Modal from './Modal';
import { _t } from './languageHandler';
// @ts-ignore - XXX: tsc doesn't like this: our js-sdk imports are complex so this isn't surprising
import Matrix from 'matrix-js-sdk';
import Matrix from 'matrix-js-sdk/src/browser-index';
import dis from './dispatcher/dispatcher';
import WidgetUtils from './utils/WidgetUtils';
import WidgetEchoStore from './stores/WidgetEchoStore';
@@ -77,7 +76,7 @@ import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import WidgetStore from "./stores/WidgetStore";
import { WidgetMessagingStore } from "./stores/widgets/WidgetMessagingStore";
import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions";
import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty } from "matrix-js-sdk/lib/webrtc/call";
import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty } from "matrix-js-sdk/src/webrtc/call";
import Analytics from './Analytics';
enum AudioID {
@@ -97,6 +96,18 @@ export enum PlaceCallType {
ScreenSharing = 'screensharing',
}
function getRemoteAudioElement(): HTMLAudioElement {
// this needs to be somewhere at the top of the DOM which
// always exists to avoid audio interruptions.
// Might as well just use DOM.
const remoteAudioElement = document.getElementById("remoteAudio") as HTMLAudioElement;
if (!remoteAudioElement) {
console.error("Failed to find remoteAudio element - cannot play audio!"
+ "You need to add an <audio/> to the DOM.");
}
return remoteAudioElement;
}
export default class CallHandler {
private calls = new Map<string, MatrixCall>();
private audioPromises = new Map<AudioID, Promise<void>>();
@@ -290,6 +301,11 @@ export default class CallHandler {
});
}
private setCallAudioElement(call: MatrixCall) {
const audioElement = getRemoteAudioElement();
if (audioElement) call.setRemoteAudioElement(audioElement);
}
private setCallState(call: MatrixCall, status: CallState) {
console.log(
`Call state in ${call.roomId} changed to ${status}`,
@@ -344,6 +360,8 @@ export default class CallHandler {
const call = Matrix.createNewMatrixCall(MatrixClientPeg.get(), roomId);
this.calls.set(roomId, call);
this.setCallListeners(call);
this.setCallAudioElement(call);
if (type === PlaceCallType.Voice) {
call.placeVoiceCall();
} else if (type === 'video') {
@@ -448,6 +466,7 @@ export default class CallHandler {
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
this.calls.set(call.roomId, call)
this.setCallListeners(call);
this.setCallAudioElement(call);
}
break;
case 'hangup':