|  |  | @ -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"> | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         <CallWindow className="dragHandle"> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           <CallWindowHeader>Call with: {ongoingCallProps.name}</CallWindowHeader> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           <CallWindowInner> |  |  |  |           <CallWindowInner> | 
			
		
	
		
		
			
				
					
					|  |  |  |           <CallWindowHeader>{ongoingCallProps.name}</CallWindowHeader> |  |  |  |             <VideoContainer> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           <VideoContainer autoPlay={true} id="video-remote" /> |  |  |  |               <VideoContainerRemote ref={videoRefRemote} autoPlay={true} /> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           <VideoContainer autoPlay={true} id="video-local" /> |  |  |  |               <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} | 
			
		
	
		
		
			
				
					
					|  |  |  |           /> |  |  |  |           /> | 
			
		
	
	
		
		
			
				
					|  |  | 
 |