You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/components/session/calling/CallContainer.tsx

168 lines
4.6 KiB
TypeScript

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';
import {
getHasIncomingCall,
getHasIncomingCallFrom,
getHasOngoingCall,
getHasOngoingCallWith,
} from '../../../state/selectors/conversations';
import { SessionButton, SessionButtonColor } from '../SessionButton';
import { SessionWrapperModal } from '../SessionWrapperModal';
export const CallWindow = styled.div`
position: absolute;
z-index: 9;
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
const CallWindowHeader = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-self: center;
padding: $session-margin-lg;
font-family: $session-font-default;
text-align: center;
line-height: 18px;
font-size: $session-font-md;
font-weight: 700;
`;
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`
text-align: center;
padding: 1rem;
`;
const CallWindowControls = styled.div`
padding: 5px;
`;
// TODO:
/**
* Add mute input, deafen, end call, possibly add person to call
* duration - look at how duration calculated for recording.
*/
export const CallContainer = () => {
const hasIncomingCall = useSelector(getHasIncomingCall);
const incomingCallProps = useSelector(getHasIncomingCallFrom);
const ongoingCallProps = useSelector(getHasOngoingCallWith);
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 () => {
if (incomingCallProps?.id) {
await CallManager.USER_acceptIncomingCallRequest(incomingCallProps.id);
}
};
const handleDeclineIncomingCall = async () => {
// close the modal
if (incomingCallProps?.id) {
await CallManager.USER_rejectIncomingCallRequest(incomingCallProps.id);
}
};
const handleEndCall = async () => {
// call method to end call connection
if (ongoingOrIncomingPubkey) {
await CallManager.USER_rejectIncomingCallRequest(ongoingOrIncomingPubkey);
}
};
//#endregion
if (!hasOngoingCall && !hasIncomingCall) {
return null;
}
if (hasOngoingCall && ongoingCallProps) {
return (
<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={window.i18n('endCall')} onClick={handleEndCall} />
</CallWindowControls>
</CallWindow>
</Draggable>
);
}
if (hasIncomingCall) {
return (
<SessionWrapperModal title={window.i18n('incomingCall')}>
<div className="session-modal__button-group">
<SessionButton text={window.i18n('decline')} onClick={handleDeclineIncomingCall} />
<SessionButton
text={window.i18n('accept')}
onClick={handleAcceptIncomingCall}
buttonColor={SessionButtonColor.Green}
/>
</div>
</SessionWrapperModal>
);
}
// display spinner while connecting
return null;
};