add listener for video calls events

pull/1939/head
Audric Ackermann 4 years ago
parent 94bc3da2c7
commit c54f63ab45
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -443,5 +443,9 @@
"messageDeletedPlaceholder": "This message has been deleted",
"messageDeleted": "Message deleted",
"surveyTitle": "Take our Session Survey",
"goToOurSurvey": "Go to our survey"
"goToOurSurvey": "Go to our survey",
"incomingCall": "Incoming call",
"accept": "Accept",
"decline": "Decline",
"endCall": "End call"
}

@ -102,6 +102,7 @@
"react": "^17.0.2",
"react-contexify": "5.0.0",
"react-dom": "^17.0.2",
"react-draggable": "^4.4.4",
"react-emoji": "^0.5.0",
"react-emoji-render": "^1.2.4",
"react-h5-audio-player": "^3.2.0",

@ -1,5 +1,9 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
import Draggable from 'react-draggable';
// tslint:disable-next-line: no-submodule-imports
import useMountedState from 'react-use/lib/useMountedState';
import styled from 'styled-components';
import _ from 'underscore';
import { CallManager } from '../../../session/utils';
@ -15,12 +19,14 @@ import { SessionWrapperModal } from '../SessionWrapperModal';
export const CallWindow = styled.div`
position: absolute;
z-index: 9;
padding: 2rem;
padding: 1rem;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
background-color: var(--color-modal-background);
border: var(--session-border);
`;
// similar styling to modal header
@ -28,7 +34,7 @@ const CallWindowHeader = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
align-self: center;
padding: $session-margin-lg;
@ -39,30 +45,29 @@ const CallWindowHeader = styled.div`
font-weight: 700;
`;
// TODO: Add proper styling for this
const VideoContainer = styled.video`
width: 200px;
height: 200px;
const VideoContainer = styled.div`
position: relative;
max-height: 60vh;
`;
const VideoContainerRemote = styled.video`
max-height: inherit;
`;
const VideoContainerLocal = styled.video`
max-height: 45%;
max-width: 45%;
position: absolute;
bottom: 0;
right: 0;
`;
const CallWindowInner = styled.div`
position: relative;
background-color: pink;
border: 1px solid #d3d3d3;
text-align: center;
padding: 2rem;
display: flex;
flex-direction: column;
padding: 1rem;
`;
const CallWindowControls = styled.div`
position: absolute;
top: 100%;
left: 0;
width: 100%;
/* background: green; */
padding: 5px;
transform: translateY(-100%);
`;
// TODO:
@ -77,6 +82,24 @@ export const CallContainer = () => {
const hasOngoingCall = useSelector(getHasOngoingCall);
const ongoingOrIncomingPubkey = ongoingCallProps?.id || incomingCallProps?.id;
const videoRefRemote = useRef<any>();
const videoRefLocal = useRef<any>();
const mountedState = useMountedState();
useEffect(() => {
CallManager.setVideoEventsListener(
(localStream: MediaStream | null, remoteStream: MediaStream | null) => {
if (mountedState() && videoRefRemote?.current && videoRefLocal?.current) {
videoRefLocal.current.srcObject = localStream;
videoRefRemote.current.srcObject = remoteStream;
}
}
);
return () => {
CallManager.setVideoEventsListener(null);
};
}, []);
//#region input handlers
const handleAcceptIncomingCall = async () => {
@ -107,26 +130,31 @@ export const CallContainer = () => {
if (hasOngoingCall && ongoingCallProps) {
return (
<CallWindow>
<CallWindowInner>
<CallWindowHeader>{ongoingCallProps.name}</CallWindowHeader>
<VideoContainer autoPlay={true} id="video-remote" />
<VideoContainer autoPlay={true} id="video-local" />
<Draggable handle=".dragHandle">
<CallWindow className="dragHandle">
<CallWindowHeader>Call with: {ongoingCallProps.name}</CallWindowHeader>
<CallWindowInner>
<VideoContainer>
<VideoContainerRemote ref={videoRefRemote} autoPlay={true} />
<VideoContainerLocal ref={videoRefLocal} autoPlay={true} />
</VideoContainer>
</CallWindowInner>
<CallWindowControls>
<SessionButton text={'end call'} onClick={handleEndCall} />
<SessionButton text={window.i18n('endCall')} onClick={handleEndCall} />
</CallWindowControls>
</CallWindowInner>
</CallWindow>
</CallWindow>
</Draggable>
);
}
if (hasIncomingCall) {
return (
<SessionWrapperModal title={'incoming call'}>
<SessionWrapperModal title={window.i18n('incomingCall')}>
<div className="session-modal__button-group">
<SessionButton text={'decline'} onClick={handleDeclineIncomingCall} />
<SessionButton text={window.i18n('decline')} onClick={handleDeclineIncomingCall} />
<SessionButton
text={'accept'}
text={window.i18n('accept')}
onClick={handleAcceptIncomingCall}
buttonColor={SessionButtonColor.Green}
/>

@ -12,6 +12,15 @@ import { ed25519Str } from '../onions/onionPath';
import { getMessageQueue } from '../sending';
import { PubKey } from '../types';
type CallManagerListener =
| ((localStream: MediaStream | null, remoteStream: MediaStream | null) => void)
| null;
let videoEventsListener: CallManagerListener;
export function setVideoEventsListener(listener: CallManagerListener) {
videoEventsListener = listener;
}
/**
* This field stores all the details received by a sender about a call in separate messages.
*/
@ -67,17 +76,15 @@ export async function USER_callRecipient(recipient: string) {
void iceSenderDebouncer(recipient);
}
});
const remoteStream = new MediaStream();
const localVideo = document.querySelector('#video-local') as any;
if (localVideo) {
localVideo.srcObject = mediaDevices;
if (videoEventsListener) {
videoEventsListener(mediaDevices, remoteStream);
}
const remoteStream = new MediaStream();
peerConnection.addEventListener('track', event => {
const remoteVideo = document.querySelector('#video-remote') as any;
if (remoteVideo) {
remoteVideo.srcObject = remoteStream;
if (videoEventsListener) {
videoEventsListener(mediaDevices, remoteStream);
}
remoteStream.addTrack(event.track);
});
@ -190,18 +197,15 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
// window.log.info('USER_acceptIncomingCallRequest adding track ', track);
peerConnection?.addTrack(track, mediaDevices);
});
const remoteStream = new MediaStream();
const localVideo = document.querySelector('#video-local') as any;
if (localVideo) {
localVideo.srcObject = mediaDevices;
if (videoEventsListener) {
videoEventsListener(mediaDevices, remoteStream);
}
const remoteStream = new MediaStream();
peerConnection.addEventListener('track', event => {
const remoteVideo = document.querySelector('#video-remote') as any;
if (remoteVideo) {
remoteVideo.srcObject = remoteStream;
if (videoEventsListener) {
videoEventsListener(mediaDevices, remoteStream);
}
remoteStream.addTrack(event.track);
});
@ -280,13 +284,8 @@ export async function USER_rejectIncomingCallRequest(fromSender: string) {
export function handleEndCallMessage(sender: string) {
callCache.delete(sender);
const remoteVideo = document.querySelector('#video-remote') as any;
if (remoteVideo) {
remoteVideo.srcObject = null;
}
const localVideo = document.querySelector('#video-local') as any;
if (localVideo) {
localVideo.srcObject = null;
if (videoEventsListener) {
videoEventsListener(null, null);
}
//
// FIXME audric trigger UI cleanup

@ -7237,6 +7237,14 @@ react-dom@^17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
react-draggable@^4.4.4:
version "4.4.4"
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.4.tgz#5b26d9996be63d32d285a426f41055de87e59b2f"
integrity sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==
dependencies:
clsx "^1.1.1"
prop-types "^15.6.0"
react-emoji-render@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/react-emoji-render/-/react-emoji-render-1.2.4.tgz#fa3542a692e1eed3236f0f12b8e3a61b2818e2c2"

Loading…
Cancel
Save