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", "messageDeletedPlaceholder": "This message has been deleted",
"messageDeleted": "Message deleted", "messageDeleted": "Message deleted",
"surveyTitle": "Take our Session Survey", "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": "^17.0.2",
"react-contexify": "5.0.0", "react-contexify": "5.0.0",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-draggable": "^4.4.4",
"react-emoji": "^0.5.0", "react-emoji": "^0.5.0",
"react-emoji-render": "^1.2.4", "react-emoji-render": "^1.2.4",
"react-h5-audio-player": "^3.2.0", "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 { 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 styled from 'styled-components';
import _ from 'underscore'; import _ from 'underscore';
import { CallManager } from '../../../session/utils'; import { CallManager } from '../../../session/utils';
@ -15,12 +19,14 @@ import { SessionWrapperModal } from '../SessionWrapperModal';
export const CallWindow = styled.div` export const CallWindow = styled.div`
position: absolute; position: absolute;
z-index: 9; z-index: 9;
padding: 2rem; padding: 1rem;
top: 50vh; top: 50vh;
left: 50vw; left: 50vw;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background-color: var(--color-modal-background);
border: var(--session-border);
`; `;
// similar styling to modal header // similar styling to modal header
@ -28,7 +34,7 @@ const CallWindowHeader = styled.div`
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-self: center;
padding: $session-margin-lg; padding: $session-margin-lg;
@ -39,30 +45,29 @@ const CallWindowHeader = styled.div`
font-weight: 700; font-weight: 700;
`; `;
// TODO: Add proper styling for this const VideoContainer = styled.div`
const VideoContainer = styled.video` position: relative;
width: 200px; max-height: 60vh;
height: 200px; `;
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` const CallWindowInner = styled.div`
position: relative;
background-color: pink;
border: 1px solid #d3d3d3;
text-align: center; text-align: center;
padding: 2rem; padding: 1rem;
display: flex;
flex-direction: column;
`; `;
const CallWindowControls = styled.div` const CallWindowControls = styled.div`
position: absolute;
top: 100%;
left: 0;
width: 100%;
/* background: green; */
padding: 5px; padding: 5px;
transform: translateY(-100%);
`; `;
// TODO: // TODO:
@ -77,6 +82,24 @@ export const CallContainer = () => {
const hasOngoingCall = useSelector(getHasOngoingCall); const hasOngoingCall = useSelector(getHasOngoingCall);
const ongoingOrIncomingPubkey = ongoingCallProps?.id || incomingCallProps?.id; 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 //#region input handlers
const handleAcceptIncomingCall = async () => { const handleAcceptIncomingCall = async () => {
@ -107,26 +130,31 @@ export const CallContainer = () => {
if (hasOngoingCall && ongoingCallProps) { if (hasOngoingCall && ongoingCallProps) {
return ( return (
<CallWindow> <Draggable handle=".dragHandle">
<CallWindowInner> <CallWindow className="dragHandle">
<CallWindowHeader>{ongoingCallProps.name}</CallWindowHeader> <CallWindowHeader>Call with: {ongoingCallProps.name}</CallWindowHeader>
<VideoContainer autoPlay={true} id="video-remote" />
<VideoContainer autoPlay={true} id="video-local" /> <CallWindowInner>
<VideoContainer>
<VideoContainerRemote ref={videoRefRemote} autoPlay={true} />
<VideoContainerLocal ref={videoRefLocal} autoPlay={true} />
</VideoContainer>
</CallWindowInner>
<CallWindowControls> <CallWindowControls>
<SessionButton text={'end call'} onClick={handleEndCall} /> <SessionButton text={window.i18n('endCall')} onClick={handleEndCall} />
</CallWindowControls> </CallWindowControls>
</CallWindowInner> </CallWindow>
</CallWindow> </Draggable>
); );
} }
if (hasIncomingCall) { if (hasIncomingCall) {
return ( return (
<SessionWrapperModal title={'incoming call'}> <SessionWrapperModal title={window.i18n('incomingCall')}>
<div className="session-modal__button-group"> <div className="session-modal__button-group">
<SessionButton text={'decline'} onClick={handleDeclineIncomingCall} /> <SessionButton text={window.i18n('decline')} onClick={handleDeclineIncomingCall} />
<SessionButton <SessionButton
text={'accept'} text={window.i18n('accept')}
onClick={handleAcceptIncomingCall} onClick={handleAcceptIncomingCall}
buttonColor={SessionButtonColor.Green} buttonColor={SessionButtonColor.Green}
/> />

@ -12,6 +12,15 @@ import { ed25519Str } from '../onions/onionPath';
import { getMessageQueue } from '../sending'; import { getMessageQueue } from '../sending';
import { PubKey } from '../types'; 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. * 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); void iceSenderDebouncer(recipient);
} }
}); });
const remoteStream = new MediaStream();
const localVideo = document.querySelector('#video-local') as any; if (videoEventsListener) {
if (localVideo) { videoEventsListener(mediaDevices, remoteStream);
localVideo.srcObject = mediaDevices;
} }
const remoteStream = new MediaStream();
peerConnection.addEventListener('track', event => { peerConnection.addEventListener('track', event => {
const remoteVideo = document.querySelector('#video-remote') as any; if (videoEventsListener) {
if (remoteVideo) { videoEventsListener(mediaDevices, remoteStream);
remoteVideo.srcObject = remoteStream;
} }
remoteStream.addTrack(event.track); remoteStream.addTrack(event.track);
}); });
@ -190,18 +197,15 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
// window.log.info('USER_acceptIncomingCallRequest adding track ', track); // window.log.info('USER_acceptIncomingCallRequest adding track ', track);
peerConnection?.addTrack(track, mediaDevices); peerConnection?.addTrack(track, mediaDevices);
}); });
const remoteStream = new MediaStream();
const localVideo = document.querySelector('#video-local') as any; if (videoEventsListener) {
if (localVideo) { videoEventsListener(mediaDevices, remoteStream);
localVideo.srcObject = mediaDevices;
} }
const remoteStream = new MediaStream();
peerConnection.addEventListener('track', event => { peerConnection.addEventListener('track', event => {
const remoteVideo = document.querySelector('#video-remote') as any; if (videoEventsListener) {
if (remoteVideo) { videoEventsListener(mediaDevices, remoteStream);
remoteVideo.srcObject = remoteStream;
} }
remoteStream.addTrack(event.track); remoteStream.addTrack(event.track);
}); });
@ -280,13 +284,8 @@ export async function USER_rejectIncomingCallRequest(fromSender: string) {
export function handleEndCallMessage(sender: string) { export function handleEndCallMessage(sender: string) {
callCache.delete(sender); callCache.delete(sender);
const remoteVideo = document.querySelector('#video-remote') as any; if (videoEventsListener) {
if (remoteVideo) { videoEventsListener(null, null);
remoteVideo.srcObject = null;
}
const localVideo = document.querySelector('#video-local') as any;
if (localVideo) {
localVideo.srcObject = null;
} }
// //
// FIXME audric trigger UI cleanup // FIXME audric trigger UI cleanup

@ -7237,6 +7237,14 @@ react-dom@^17.0.2:
object-assign "^4.1.1" object-assign "^4.1.1"
scheduler "^0.20.2" 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: react-emoji-render@^1.2.4:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/react-emoji-render/-/react-emoji-render-1.2.4.tgz#fa3542a692e1eed3236f0f12b8e3a61b2818e2c2" resolved "https://registry.yarnpkg.com/react-emoji-render/-/react-emoji-render-1.2.4.tgz#fa3542a692e1eed3236f0f12b8e3a61b2818e2c2"

Loading…
Cancel
Save