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.
		
		
		
		
		
			
		
			
	
	
		
			238 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			TypeScript
		
	
		
		
			
		
	
	
			238 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			TypeScript
		
	
| 
											4 years ago
										 | import { useSelector } from 'react-redux'; | ||
| 
											4 years ago
										 | import React, { useRef, useState } from 'react'; | ||
| 
											4 years ago
										 | 
 | ||
|  | import styled from 'styled-components'; | ||
| 
											4 years ago
										 | import { CallManager, UserUtils } from '../../session/utils'; | ||
| 
											4 years ago
										 | import { | ||
| 
											4 years ago
										 |   getCallIsInFullScreen, | ||
| 
											4 years ago
										 |   getCallWithFocusedConvoIsOffering, | ||
|  |   getCallWithFocusedConvosIsConnected, | ||
|  |   getCallWithFocusedConvosIsConnecting, | ||
| 
											4 years ago
										 |   getHasOngoingCallWithFocusedConvo, | ||
| 
											4 years ago
										 |   getHasOngoingCallWithPubkey, | ||
| 
											4 years ago
										 | } from '../../state/selectors/call'; | ||
| 
											4 years ago
										 | import { StyledVideoElement } from './DraggableCallContainer'; | ||
| 
											4 years ago
										 | import { Avatar, AvatarSize } from '../avatar/Avatar'; | ||
| 
											4 years ago
										 | 
 | ||
| 
											4 years ago
										 | import { useVideoCallEventsListener } from '../../hooks/useVideoEventListener'; | ||
|  | import { useModuloWithTripleDots } from '../../hooks/useModuloWithTripleDots'; | ||
| 
											4 years ago
										 | import { CallWindowControls } from './CallButtons'; | ||
| 
											4 years ago
										 | import { DEVICE_DISABLED_DEVICE_ID } from '../../session/utils/calling/CallManager'; | ||
| 
											4 years ago
										 | // tslint:disable-next-line: no-submodule-imports
 | ||
|  | import useInterval from 'react-use/lib/useInterval'; | ||
|  | import moment from 'moment'; | ||
| 
											4 years ago
										 | import { SessionSpinner } from '../basic/SessionSpinner'; | ||
| 
											4 years ago
										 | 
 | ||
|  | const VideoContainer = styled.div`
 | ||
|  |   height: 100%; | ||
|  |   width: 50%; | ||
| 
											4 years ago
										 |   z-index: 0; | ||
| 
											4 years ago
										 |   padding-top: 30px; // leave some space at the top for the connecting/duration of the current call
 | ||
| 
											4 years ago
										 | `;
 | ||
|  | 
 | ||
|  | const InConvoCallWindow = styled.div`
 | ||
|  |   padding: 1rem; | ||
|  |   display: flex; | ||
|  | 
 | ||
|  |   background-color: hsl(0, 0%, 15.7%); | ||
|  | 
 | ||
| 
											4 years ago
										 |   flex-shrink: 1; | ||
| 
											4 years ago
										 |   min-height: 80px; | ||
| 
											4 years ago
										 |   align-items: center; | ||
| 
											4 years ago
										 |   flex-grow: 1; | ||
| 
											4 years ago
										 | `;
 | ||
|  | 
 | ||
|  | const RelativeCallWindow = styled.div`
 | ||
|  |   position: relative; | ||
|  |   height: 100%; | ||
|  |   display: flex; | ||
|  |   flex-grow: 1; | ||
|  | `;
 | ||
|  | 
 | ||
| 
											4 years ago
										 | const CenteredAvatarInConversation = styled.div`
 | ||
| 
											4 years ago
										 |   top: -50%; | ||
|  |   transform: translateY(-50%); | ||
|  |   position: relative; | ||
| 
											4 years ago
										 |   bottom: 0; | ||
|  |   left: 0; | ||
|  |   right: 50%; | ||
|  | 
 | ||
|  |   display: flex; | ||
|  |   justify-content: center; | ||
|  |   align-items: center; | ||
|  | `;
 | ||
|  | 
 | ||
| 
											4 years ago
										 | const StyledCenteredLabel = styled.div`
 | ||
|  |   position: absolute; | ||
|  |   left: 50%; | ||
|  |   transform: translateX(-50%); | ||
|  |   height: min-content; | ||
|  |   white-space: nowrap; | ||
|  |   color: white; | ||
|  |   text-shadow: 0px 0px 8px white; | ||
| 
											4 years ago
										 |   z-index: 5; | ||
| 
											4 years ago
										 | `;
 | ||
|  | 
 | ||
|  | const RingingLabel = () => { | ||
| 
											4 years ago
										 |   const ongoingCallWithFocusedIsRinging = useSelector(getCallWithFocusedConvoIsOffering); | ||
| 
											4 years ago
										 | 
 | ||
|  |   const modulatedStr = useModuloWithTripleDots(window.i18n('ringing'), 3, 1000); | ||
| 
											4 years ago
										 |   if (!ongoingCallWithFocusedIsRinging) { | ||
|  |     return null; | ||
|  |   } | ||
| 
											4 years ago
										 |   return <StyledCenteredLabel>{modulatedStr}</StyledCenteredLabel>; | ||
| 
											4 years ago
										 | }; | ||
|  | 
 | ||
|  | const ConnectingLabel = () => { | ||
| 
											4 years ago
										 |   const ongoingCallWithFocusedIsConnecting = useSelector(getCallWithFocusedConvosIsConnecting); | ||
| 
											4 years ago
										 | 
 | ||
|  |   const modulatedStr = useModuloWithTripleDots(window.i18n('establishingConnection'), 3, 1000); | ||
|  | 
 | ||
| 
											4 years ago
										 |   if (!ongoingCallWithFocusedIsConnecting) { | ||
|  |     return null; | ||
|  |   } | ||
| 
											4 years ago
										 | 
 | ||
|  |   return <StyledCenteredLabel>{modulatedStr}</StyledCenteredLabel>; | ||
| 
											4 years ago
										 | }; | ||
|  | 
 | ||
| 
											4 years ago
										 | const DurationLabel = () => { | ||
|  |   const [callDuration, setCallDuration] = useState<undefined | number>(undefined); | ||
|  |   const ongoingCallWithFocusedIsConnected = useSelector(getCallWithFocusedConvosIsConnected); | ||
|  | 
 | ||
|  |   useInterval(() => { | ||
|  |     const duration = CallManager.getCurrentCallDuration(); | ||
|  |     if (duration) { | ||
|  |       setCallDuration(duration); | ||
|  |     } | ||
|  |   }, 100); | ||
|  | 
 | ||
|  |   if (!ongoingCallWithFocusedIsConnected || !callDuration || callDuration < 0) { | ||
|  |     return null; | ||
|  |   } | ||
|  | 
 | ||
|  |   const ms = callDuration * 1000; | ||
|  |   const d = moment.duration(ms); | ||
|  | 
 | ||
|  |   // tslint:disable-next-line: restrict-plus-operands
 | ||
|  |   const dateString = Math.floor(d.asHours()) + moment.utc(ms).format(':mm:ss'); | ||
|  |   return <StyledCenteredLabel>{dateString}</StyledCenteredLabel>; | ||
|  | }; | ||
|  | 
 | ||
| 
											4 years ago
										 | const StyledSpinner = styled.div<{ fullWidth: boolean }>`
 | ||
|  |   height: 100%; | ||
|  |   width: ${props => (props.fullWidth ? '100%' : '50%')}; | ||
|  |   display: flex; | ||
|  |   justify-content: center; | ||
|  |   align-items: center; | ||
|  |   position: absolute; | ||
|  |   z-index: -1; | ||
|  | `;
 | ||
|  | 
 | ||
|  | export const VideoLoadingSpinner = (props: { fullWidth: boolean }) => { | ||
|  |   return ( | ||
|  |     <StyledSpinner fullWidth={props.fullWidth}> | ||
|  |       <SessionSpinner loading={true} /> | ||
|  |     </StyledSpinner> | ||
|  |   ); | ||
|  | }; | ||
|  | 
 | ||
| 
											4 years ago
										 | // tslint:disable-next-line: max-func-body-length
 | ||
|  | export const InConversationCallContainer = () => { | ||
| 
											4 years ago
										 |   const isInFullScreen = useSelector(getCallIsInFullScreen); | ||
|  | 
 | ||
| 
											4 years ago
										 |   const ongoingCallPubkey = useSelector(getHasOngoingCallWithPubkey); | ||
| 
											4 years ago
										 |   const ongoingCallWithFocused = useSelector(getHasOngoingCallWithFocusedConvo); | ||
| 
											4 years ago
										 |   const videoRefRemote = useRef<HTMLVideoElement>(null); | ||
|  |   const videoRefLocal = useRef<HTMLVideoElement>(null); | ||
| 
											4 years ago
										 | 
 | ||
| 
											4 years ago
										 |   const ourPubkey = UserUtils.getOurPubKeyStrFromCache(); | ||
|  | 
 | ||
| 
											4 years ago
										 |   const { | ||
|  |     currentConnectedAudioInputs, | ||
|  |     currentConnectedCameras, | ||
| 
											4 years ago
										 |     currentConnectedAudioOutputs, | ||
| 
											4 years ago
										 |     currentSelectedAudioOutput, | ||
| 
											4 years ago
										 |     localStream, | ||
|  |     localStreamVideoIsMuted, | ||
|  |     remoteStream, | ||
|  |     remoteStreamVideoIsMuted, | ||
|  |     isAudioMuted, | ||
| 
											4 years ago
										 |     isAudioOutputMuted, | ||
| 
											4 years ago
										 |   } = useVideoCallEventsListener('InConversationCallContainer', true); | ||
| 
											4 years ago
										 | 
 | ||
|  |   if (videoRefRemote?.current && videoRefLocal?.current) { | ||
| 
											4 years ago
										 |     if (videoRefRemote.current.srcObject !== remoteStream) { | ||
|  |       videoRefRemote.current.srcObject = remoteStream; | ||
|  |     } | ||
| 
											4 years ago
										 | 
 | ||
| 
											4 years ago
										 |     if (videoRefLocal.current.srcObject !== localStream) { | ||
|  |       videoRefLocal.current.srcObject = localStream; | ||
|  |     } | ||
| 
											4 years ago
										 | 
 | ||
|  |     if (videoRefRemote.current) { | ||
|  |       if (currentSelectedAudioOutput === DEVICE_DISABLED_DEVICE_ID) { | ||
| 
											4 years ago
										 |         videoRefRemote.current.muted = true; | ||
| 
											4 years ago
										 |       } else { | ||
| 
											4 years ago
										 |         void (videoRefRemote.current as any)?.setSinkId(currentSelectedAudioOutput); | ||
| 
											4 years ago
										 |         videoRefRemote.current.muted = false; | ||
| 
											4 years ago
										 |       } | ||
|  |     } | ||
| 
											4 years ago
										 |   } | ||
| 
											4 years ago
										 | 
 | ||
| 
											4 years ago
										 |   if (isInFullScreen && videoRefRemote.current) { | ||
|  |     // disable this video element so the one in fullscreen is the only one playing audio
 | ||
|  |     videoRefRemote.current.muted = true; | ||
|  |   } | ||
|  | 
 | ||
| 
											4 years ago
										 |   if (!ongoingCallWithFocused || !ongoingCallPubkey) { | ||
| 
											4 years ago
										 |     return null; | ||
|  |   } | ||
|  | 
 | ||
|  |   return ( | ||
|  |     <InConvoCallWindow> | ||
|  |       <RelativeCallWindow> | ||
| 
											4 years ago
										 |         <RingingLabel /> | ||
|  |         <ConnectingLabel /> | ||
| 
											4 years ago
										 |         <DurationLabel /> | ||
| 
											4 years ago
										 |         <VideoContainer> | ||
| 
											4 years ago
										 |           <VideoLoadingSpinner fullWidth={false} /> | ||
| 
											4 years ago
										 |           <StyledVideoElement | ||
|  |             ref={videoRefRemote} | ||
|  |             autoPlay={true} | ||
| 
											4 years ago
										 |             isVideoMuted={remoteStreamVideoIsMuted} | ||
| 
											4 years ago
										 |           /> | ||
| 
											4 years ago
										 |           {remoteStreamVideoIsMuted && ( | ||
| 
											4 years ago
										 |             <CenteredAvatarInConversation> | ||
| 
											4 years ago
										 |               <Avatar size={AvatarSize.XL} pubkey={ongoingCallPubkey} /> | ||
| 
											4 years ago
										 |             </CenteredAvatarInConversation> | ||
| 
											4 years ago
										 |           )} | ||
| 
											4 years ago
										 |         </VideoContainer> | ||
|  |         <VideoContainer> | ||
| 
											4 years ago
										 |           <StyledVideoElement | ||
|  |             ref={videoRefLocal} | ||
|  |             autoPlay={true} | ||
|  |             muted={true} | ||
| 
											4 years ago
										 |             isVideoMuted={localStreamVideoIsMuted} | ||
| 
											4 years ago
										 |           /> | ||
| 
											4 years ago
										 |           {localStreamVideoIsMuted && ( | ||
| 
											4 years ago
										 |             <CenteredAvatarInConversation> | ||
| 
											4 years ago
										 |               <Avatar size={AvatarSize.XL} pubkey={ourPubkey} /> | ||
| 
											4 years ago
										 |             </CenteredAvatarInConversation> | ||
|  |           )} | ||
| 
											4 years ago
										 |         </VideoContainer> | ||
|  | 
 | ||
| 
											4 years ago
										 |         <CallWindowControls | ||
|  |           currentConnectedAudioInputs={currentConnectedAudioInputs} | ||
|  |           currentConnectedCameras={currentConnectedCameras} | ||
|  |           isAudioMuted={isAudioMuted} | ||
| 
											4 years ago
										 |           currentConnectedAudioOutputs={currentConnectedAudioOutputs} | ||
|  |           isAudioOutputMuted={isAudioOutputMuted} | ||
| 
											4 years ago
										 |           localStreamVideoIsMuted={localStreamVideoIsMuted} | ||
|  |           remoteStreamVideoIsMuted={remoteStreamVideoIsMuted} | ||
|  |           isFullScreen={false} | ||
|  |         /> | ||
| 
											4 years ago
										 |       </RelativeCallWindow> | ||
|  |     </InConvoCallWindow> | ||
|  |   ); | ||
|  | }; |