import React, { useEffect, useState } from 'react'; import { contextMenu, Item, Menu } from 'react-contexify'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; import { CallManager, ToastUtils } from '../../session/utils'; import { InputItem } from '../../session/utils/calling/CallManager'; import { setFullScreenCall } from '../../state/ducks/call'; import { getHasOngoingCallWithPubkey } from '../../state/selectors/call'; import { SessionIconButton } from '../icon'; import { DropDownAndToggleButton } from '../icon/DropDownAndToggleButton'; import { SessionContextMenuContainer } from '../SessionContextMenuContainer'; const VideoInputMenu = ({ triggerId, camerasList, }: { triggerId: string; camerasList: Array; }) => { return ( {camerasList.map(m => { return ( { void CallManager.selectCameraByDeviceId(m.deviceId); }} > {m.label.substr(0, 40)} ); })} ); }; const showVideoInputMenu = ( currentConnectedCameras: Array, e: React.MouseEvent ) => { if (currentConnectedCameras.length === 0) { ToastUtils.pushNoCameraFound(); return; } contextMenu.show({ id: videoTriggerId, event: e, }); }; const videoTriggerId = 'video-menu-trigger-id'; const audioTriggerId = 'audio-menu-trigger-id'; const audioOutputTriggerId = 'audio-output-menu-trigger-id'; export const VideoInputButton = ({ currentConnectedCameras, localStreamVideoIsMuted, isFullScreen = false, }: { currentConnectedCameras: Array; localStreamVideoIsMuted: boolean; isFullScreen?: boolean; }) => { return ( <> { void handleCameraToggle(currentConnectedCameras, localStreamVideoIsMuted); }} onArrowClick={e => { showVideoInputMenu(currentConnectedCameras, e); }} isFullScreen={isFullScreen} /> ); }; const AudioInputMenu = ({ triggerId, audioInputsList, }: { triggerId: string; audioInputsList: Array; }) => { return ( {audioInputsList.map(m => { return ( { void CallManager.selectAudioInputByDeviceId(m.deviceId); }} > {m.label.substr(0, 40)} ); })} ); }; const showAudioInputMenu = ( currentConnectedAudioInputs: Array, e: React.MouseEvent ) => { if (currentConnectedAudioInputs.length === 0) { ToastUtils.pushNoAudioInputFound(); return; } contextMenu.show({ id: audioTriggerId, event: e, }); }; export const AudioInputButton = ({ currentConnectedAudioInputs, isAudioMuted, isFullScreen = false, }: { currentConnectedAudioInputs: Array; isAudioMuted: boolean; isFullScreen?: boolean; }) => { return ( <> { void handleMicrophoneToggle(currentConnectedAudioInputs, isAudioMuted); }} onArrowClick={e => { showAudioInputMenu(currentConnectedAudioInputs, e); }} isFullScreen={isFullScreen} /> ); }; const AudioOutputMenu = ({ triggerId, audioOutputsList, }: { triggerId: string; audioOutputsList: Array; }) => { return ( {audioOutputsList.map(m => { return ( { void CallManager.selectAudioOutputByDeviceId(m.deviceId); }} > {m.label.substr(0, 40)} ); })} ); }; const showAudioOutputMenu = ( currentConnectedAudioOutputs: Array, e: React.MouseEvent ) => { if (currentConnectedAudioOutputs.length === 0) { ToastUtils.pushNoAudioOutputFound(); return; } contextMenu.show({ id: audioOutputTriggerId, event: e, }); }; export const AudioOutputButton = ({ currentConnectedAudioOutputs, isAudioOutputMuted, isFullScreen = false, }: { currentConnectedAudioOutputs: Array; isAudioOutputMuted: boolean; isFullScreen?: boolean; }) => { return ( <> { void handleSpeakerToggle(currentConnectedAudioOutputs, isAudioOutputMuted); }} onArrowClick={e => { showAudioOutputMenu(currentConnectedAudioOutputs, e); }} isFullScreen={isFullScreen} /> ); }; const StyledCallActionButton = styled.div<{ isFullScreen: boolean }>` .session-icon-button { background-color: var(--call-buttons-action-background-color); border-radius: 50%; transition-duration: var(--default-duration); ${props => props.isFullScreen && 'opacity: 0.4;'} &:hover { background-color: var(--call-buttons-action-background-hover-color); ${props => props.isFullScreen && 'opacity: 1;'} } } `; const ShowInFullScreenButton = ({ isFullScreen }: { isFullScreen: boolean }) => { const dispatch = useDispatch(); const showInFullScreen = () => { if (isFullScreen) { dispatch(setFullScreenCall(false)); } else { dispatch(setFullScreenCall(true)); } }; return ( ); }; export const HangUpButton = ({ isFullScreen }: { isFullScreen: boolean }) => { const ongoingCallPubkey = useSelector(getHasOngoingCallWithPubkey); const handleEndCall = async () => { // call method to end call connection if (ongoingCallPubkey) { await CallManager.USER_hangup(ongoingCallPubkey); } }; return ( ); }; const handleCameraToggle = async ( currentConnectedCameras: Array, localStreamVideoIsMuted: boolean ) => { if (!currentConnectedCameras.length) { ToastUtils.pushNoCameraFound(); return; } if (localStreamVideoIsMuted) { // select the first one await CallManager.selectCameraByDeviceId(currentConnectedCameras[0].deviceId); } else { await CallManager.selectCameraByDeviceId(CallManager.DEVICE_DISABLED_DEVICE_ID); } }; const handleMicrophoneToggle = async ( currentConnectedAudioInputs: Array, isAudioMuted: boolean ) => { if (!currentConnectedAudioInputs.length) { ToastUtils.pushNoAudioInputFound(); return; } if (isAudioMuted) { // selects the first one await CallManager.selectAudioInputByDeviceId(currentConnectedAudioInputs[0].deviceId); } else { await CallManager.selectAudioInputByDeviceId(CallManager.DEVICE_DISABLED_DEVICE_ID); } }; const handleSpeakerToggle = async ( currentConnectedAudioOutputs: Array, isAudioOutputMuted: boolean ) => { if (!currentConnectedAudioOutputs.length) { ToastUtils.pushNoAudioOutputFound(); return; } if (isAudioOutputMuted) { // selects the first one await CallManager.selectAudioOutputByDeviceId(currentConnectedAudioOutputs[0].deviceId); } else { await CallManager.selectAudioOutputByDeviceId(CallManager.DEVICE_DISABLED_DEVICE_ID); } }; const StyledCallWindowControls = styled.div<{ isFullScreen: boolean; makeVisible: boolean }>` position: absolute; bottom: 0px; width: 100%; height: 100%; align-items: flex-end; padding: 10px; border-radius: 10px; margin-left: auto; margin-right: auto; left: 0; right: 0; transition: all var(--default-duration) ease-in-out; display: flex; justify-content: center; opacity: ${props => (props.makeVisible ? 1 : 0)}; ${props => props.isFullScreen && ` opacity: 0.4; &:hover { opacity: 1; } `} `; export const CallWindowControls = ({ currentConnectedCameras, currentConnectedAudioInputs, currentConnectedAudioOutputs, isAudioMuted, isAudioOutputMuted, remoteStreamVideoIsMuted, localStreamVideoIsMuted, isFullScreen, }: { isAudioMuted: boolean; isAudioOutputMuted: boolean; localStreamVideoIsMuted: boolean; remoteStreamVideoIsMuted: boolean; currentConnectedAudioInputs: Array; currentConnectedAudioOutputs: Array; currentConnectedCameras: Array; isFullScreen: boolean; }) => { const [makeVisible, setMakeVisible] = useState(true); const setMakeVisibleTrue = () => { setMakeVisible(true); }; const setMakeVisibleFalse = () => { setMakeVisible(false); }; useEffect(() => { setMakeVisibleTrue(); document.addEventListener('mouseenter', setMakeVisibleTrue); document.addEventListener('mouseleave', setMakeVisibleFalse); return () => { document.removeEventListener('mouseenter', setMakeVisibleTrue); document.removeEventListener('mouseleave', setMakeVisibleFalse); }; }, [isFullScreen]); return ( {!remoteStreamVideoIsMuted && } ); };