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>
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								};
							 |