Skip to content

Commit 50bce64

Browse files
authored
Merge pull request matrix-org#5366 from matrix-org/dbkr/call_hold
Implement call hold
2 parents a67da01 + cf2d8d2 commit 50bce64

File tree

14 files changed

+293
-292
lines changed

14 files changed

+293
-292
lines changed

res/css/_components.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,4 @@
229229
@import "./views/verification/_VerificationShowSas.scss";
230230
@import "./views/voip/_CallContainer.scss";
231231
@import "./views/voip/_CallView.scss";
232-
@import "./views/voip/_VideoView.scss";
232+
@import "./views/voip/_VideoFeed.scss";

res/css/views/voip/_CallContainer.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ limitations under the License.
3333
pointer-events: initial; // restore pointer events so the user can leave/interact
3434
cursor: pointer;
3535

36-
.mx_VideoView {
36+
.mx_CallView_video {
3737
width: 350px;
3838
}
3939

40-
.mx_VideoView_localVideoFeed {
40+
.mx_VideoFeed_local {
4141
border-radius: 8px;
4242
overflow: hidden;
4343
}

res/css/views/voip/_CallView.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,10 @@ limitations under the License.
9292
background-color: $primary-fg-color;
9393
}
9494
}
95+
96+
.mx_CallView_video {
97+
width: 100%;
98+
position: relative;
99+
z-index: 30;
100+
}
101+
Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2015, 2016 OpenMarket Ltd
2+
Copyright 2015, 2016, 2020 The Matrix.org Foundation C.I.C.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -14,23 +14,17 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
.mx_VideoView {
17+
.mx_VideoFeed video {
1818
width: 100%;
19-
position: relative;
20-
z-index: 30;
2119
}
2220

23-
.mx_VideoView video {
24-
width: 100%;
25-
}
26-
27-
.mx_VideoView_remoteVideoFeed {
21+
.mx_VideoFeed_remote {
2822
width: 100%;
2923
background-color: #000;
3024
z-index: 50;
3125
}
3226

33-
.mx_VideoView_localVideoFeed {
27+
.mx_VideoFeed_local {
3428
width: 25%;
3529
height: 25%;
3630
position: absolute;
@@ -39,11 +33,11 @@ limitations under the License.
3933
z-index: 100;
4034
}
4135

42-
.mx_VideoView_localVideoFeed video {
36+
.mx_VideoFeed_local video {
4337
width: auto;
4438
height: 100%;
4539
}
4640

47-
.mx_VideoView_localVideoFeed.mx_VideoView_localVideoFeed_flipped video {
41+
.mx_VideoFeed_mirror video {
4842
transform: scale(-1, 1);
4943
}

src/@types/global.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ declare global {
6969
interface Document {
7070
// https://developer.mozilla.org/en-US/docs/Web/API/Document/hasStorageAccess
7171
hasStorageAccess?: () => Promise<boolean>;
72+
73+
// Safari & IE11 only have this prefixed: we used prefixed versions
74+
// previously so let's continue to support them for now
75+
webkitExitFullscreen(): Promise<void>;
76+
msExitFullscreen(): Promise<void>;
77+
readonly webkitFullscreenElement: Element | null;
78+
readonly msFullscreenElement: Element | null;
7279
}
7380

7481
interface Navigator {
@@ -99,6 +106,13 @@ declare global {
99106
type?: string;
100107
}
101108

109+
interface Element {
110+
// Safari & IE11 only have this prefixed: we used prefixed versions
111+
// previously so let's continue to support them for now
112+
webkitRequestFullScreen(options?: FullscreenOptions): Promise<void>;
113+
msRequestFullscreen(options?: FullscreenOptions): Promise<void>;
114+
}
115+
102116
interface Error {
103117
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/fileName
104118
fileName?: string;

src/CallHandler.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ import {MatrixClientPeg} from './MatrixClientPeg';
5959
import PlatformPeg from './PlatformPeg';
6060
import Modal from './Modal';
6161
import { _t } from './languageHandler';
62-
// @ts-ignore - XXX: tsc doesn't like this: our js-sdk imports are complex so this isn't surprising
63-
import Matrix from 'matrix-js-sdk';
62+
import { createNewMatrixCall } from 'matrix-js-sdk/src/webrtc/call';
6463
import dis from './dispatcher/dispatcher';
6564
import WidgetUtils from './utils/WidgetUtils';
6665
import WidgetEchoStore from './stores/WidgetEchoStore';
@@ -77,7 +76,7 @@ import ErrorDialog from "./components/views/dialogs/ErrorDialog";
7776
import WidgetStore from "./stores/WidgetStore";
7877
import { WidgetMessagingStore } from "./stores/widgets/WidgetMessagingStore";
7978
import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions";
80-
import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty, CallType } from "matrix-js-sdk/lib/webrtc/call";
79+
import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty, CallType } from "matrix-js-sdk/src/webrtc/call";
8180
import Analytics from './Analytics';
8281
import CountlyAnalytics from "./CountlyAnalytics";
8382

@@ -98,6 +97,21 @@ export enum PlaceCallType {
9897
ScreenSharing = 'screensharing',
9998
}
10099

100+
function getRemoteAudioElement(): HTMLAudioElement {
101+
// this needs to be somewhere at the top of the DOM which
102+
// always exists to avoid audio interruptions.
103+
// Might as well just use DOM.
104+
const remoteAudioElement = document.getElementById("remoteAudio") as HTMLAudioElement;
105+
if (!remoteAudioElement) {
106+
console.error(
107+
"Failed to find remoteAudio element - cannot play audio!" +
108+
"You need to add an <audio/> to the DOM.",
109+
);
110+
return null;
111+
}
112+
return remoteAudioElement;
113+
}
114+
101115
export default class CallHandler {
102116
private calls = new Map<string, MatrixCall>();
103117
private audioPromises = new Map<AudioID, Promise<void>>();
@@ -291,6 +305,11 @@ export default class CallHandler {
291305
});
292306
}
293307

308+
private setCallAudioElement(call: MatrixCall) {
309+
const audioElement = getRemoteAudioElement();
310+
if (audioElement) call.setRemoteAudioElement(audioElement);
311+
}
312+
294313
private setCallState(call: MatrixCall, status: CallState) {
295314
console.log(
296315
`Call state in ${call.roomId} changed to ${status}`,
@@ -343,9 +362,11 @@ export default class CallHandler {
343362
) {
344363
Analytics.trackEvent('voip', 'placeCall', 'type', type);
345364
CountlyAnalytics.instance.trackStartCall(roomId, type === PlaceCallType.Video, false);
346-
const call = Matrix.createNewMatrixCall(MatrixClientPeg.get(), roomId);
365+
const call = createNewMatrixCall(MatrixClientPeg.get(), roomId);
347366
this.calls.set(roomId, call);
348367
this.setCallListeners(call);
368+
this.setCallAudioElement(call);
369+
349370
if (type === PlaceCallType.Voice) {
350371
call.placeVoiceCall();
351372
} else if (type === 'video') {
@@ -451,6 +472,7 @@ export default class CallHandler {
451472
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
452473
this.calls.set(call.roomId, call)
453474
this.setCallListeners(call);
475+
this.setCallAudioElement(call);
454476
}
455477
break;
456478
case 'hangup':

src/SlashCommands.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from
4646
import SdkConfig from "./SdkConfig";
4747
import SettingsStore from "./settings/SettingsStore";
4848
import {UIFeature} from "./settings/UIFeature";
49+
import CallHandler from "./CallHandler";
4950

5051
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
5152
interface HTMLInputEvent extends Event {
@@ -1057,6 +1058,32 @@ export const Commands = [
10571058
},
10581059
category: CommandCategories.actions,
10591060
}),
1061+
new Command({
1062+
command: "holdcall",
1063+
description: _td("Places the call in the current room on hold"),
1064+
category: CommandCategories.other,
1065+
runFn: function(roomId, args) {
1066+
const call = CallHandler.sharedInstance().getCallForRoom(roomId);
1067+
if (!call) {
1068+
return reject("No active call in this room");
1069+
}
1070+
call.setRemoteOnHold(true);
1071+
return success();
1072+
},
1073+
}),
1074+
new Command({
1075+
command: "unholdcall",
1076+
description: _td("Takes the call in the current room off hold"),
1077+
category: CommandCategories.other,
1078+
runFn: function(roomId, args) {
1079+
const call = CallHandler.sharedInstance().getCallForRoom(roomId);
1080+
if (!call) {
1081+
return reject("No active call in this room");
1082+
}
1083+
call.setRemoteOnHold(false);
1084+
return success();
1085+
},
1086+
}),
10601087

10611088
// Command definitions for autocompletion ONLY:
10621089
// /me is special because its not handled by SlashCommands.js and is instead done inside the Composer classes

src/components/structures/RoomView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ import RoomHeader from "../views/rooms/RoomHeader";
7171
import TintableSvg from "../views/elements/TintableSvg";
7272
import {XOR} from "../../@types/common";
7373
import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
74-
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/lib/webrtc/call";
74+
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
7575
import WidgetStore from "../../stores/WidgetStore";
7676
import {UPDATE_EVENT} from "../../stores/AsyncStore";
7777
import Notifier from "../../Notifier";

src/components/views/voip/CallPreview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import dis from '../../../dispatcher/dispatcher';
2424
import { ActionPayload } from '../../../dispatcher/payloads';
2525
import PersistentApp from "../elements/PersistentApp";
2626
import SettingsStore from "../../../settings/SettingsStore";
27-
import { CallState, MatrixCall } from 'matrix-js-sdk/lib/webrtc/call';
27+
import { CallState, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
2828

2929
interface IProps {
3030
}

0 commit comments

Comments
 (0)