show input toggles in fullscreen mode too

This commit is contained in:
Audric Ackermann 2021-11-05 14:42:46 +11:00
parent 9951d7947b
commit 3741e96c61
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
3 changed files with 320 additions and 222 deletions

View file

@ -0,0 +1,288 @@
import { SessionIconButton } from '../icon';
import { animation, contextMenu, Item, Menu } from 'react-contexify';
import { InputItem } from '../../../session/utils/CallManager';
import { setFullScreenCall } from '../../../state/ducks/conversations';
import { CallManager, ToastUtils } from '../../../session/utils';
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getHasOngoingCallWithPubkey } from '../../../state/selectors/conversations';
import { DropDownAndToggleButton } from '../icon/DropDownAndToggleButton';
import styled from 'styled-components';
const videoTriggerId = 'video-menu-trigger-id';
const audioTriggerId = 'audio-menu-trigger-id';
export const VideoInputButton = ({
currentConnectedCameras,
localStreamVideoIsMuted,
hideArrowIcon = false,
}: {
currentConnectedCameras: Array<InputItem>;
localStreamVideoIsMuted: boolean;
hideArrowIcon?: boolean;
}) => {
return (
<>
<DropDownAndToggleButton
iconType="camera"
isMuted={localStreamVideoIsMuted}
onMainButtonClick={() => {
void handleCameraToggle(currentConnectedCameras, localStreamVideoIsMuted);
}}
onArrowClick={e => {
showVideoInputMenu(currentConnectedCameras, e);
}}
hidePopoverArrow={hideArrowIcon}
/>
<VideoInputMenu triggerId={videoTriggerId} camerasList={currentConnectedCameras} />
</>
);
};
export const AudioInputButton = ({
currentConnectedAudioInputs,
isAudioMuted,
hideArrowIcon = false,
}: {
currentConnectedAudioInputs: Array<InputItem>;
isAudioMuted: boolean;
hideArrowIcon?: boolean;
}) => {
return (
<>
<DropDownAndToggleButton
iconType="microphone"
isMuted={isAudioMuted}
onMainButtonClick={() => {
void handleMicrophoneToggle(currentConnectedAudioInputs, isAudioMuted);
}}
onArrowClick={e => {
showAudioInputMenu(currentConnectedAudioInputs, e);
}}
hidePopoverArrow={hideArrowIcon}
/>
<AudioInputMenu triggerId={audioTriggerId} audioInputsList={currentConnectedAudioInputs} />
</>
);
};
const VideoInputMenu = ({
triggerId,
camerasList,
}: {
triggerId: string;
camerasList: Array<InputItem>;
}) => {
return (
<Menu id={triggerId} animation={animation.fade}>
{camerasList.map(m => {
return (
<Item
key={m.deviceId}
onClick={() => {
void CallManager.selectCameraByDeviceId(m.deviceId);
}}
>
{m.label.substr(0, 40)}
</Item>
);
})}
</Menu>
);
};
const AudioInputMenu = ({
triggerId,
audioInputsList,
}: {
triggerId: string;
audioInputsList: Array<InputItem>;
}) => {
return (
<Menu id={triggerId} animation={animation.fade}>
{audioInputsList.map(m => {
return (
<Item
key={m.deviceId}
onClick={() => {
void CallManager.selectAudioInputByDeviceId(m.deviceId);
}}
>
{m.label.substr(0, 40)}
</Item>
);
})}
</Menu>
);
};
export const ShowInFullScreenButton = ({ isFullScreen }: { isFullScreen: boolean }) => {
const dispatch = useDispatch();
const showInFullScreen = () => {
if (isFullScreen) {
dispatch(setFullScreenCall(false));
} else {
dispatch(setFullScreenCall(true));
}
};
return (
<SessionIconButton
iconSize={60}
iconPadding="20px"
iconType="fullscreen"
backgroundColor="white"
borderRadius="50%"
onClick={showInFullScreen}
iconColor="black"
margin="10px"
/>
);
};
export const HangUpButton = () => {
const ongoingCallPubkey = useSelector(getHasOngoingCallWithPubkey);
const handleEndCall = async () => {
// call method to end call connection
if (ongoingCallPubkey) {
await CallManager.USER_hangup(ongoingCallPubkey);
}
};
return (
<SessionIconButton
iconSize={60}
iconPadding="20px"
iconType="hangup"
backgroundColor="white"
borderRadius="50%"
onClick={handleEndCall}
iconColor="red"
margin="10px"
/>
);
};
const showAudioInputMenu = (
currentConnectedAudioInputs: Array<any>,
e: React.MouseEvent<HTMLDivElement>
) => {
if (currentConnectedAudioInputs.length === 0) {
ToastUtils.pushNoAudioInputFound();
return;
}
contextMenu.show({
id: audioTriggerId,
event: e,
});
};
const showVideoInputMenu = (
currentConnectedCameras: Array<InputItem>,
e: React.MouseEvent<HTMLDivElement>
) => {
if (currentConnectedCameras.length === 0) {
ToastUtils.pushNoCameraFound();
return;
}
contextMenu.show({
id: videoTriggerId,
event: e,
});
};
const handleCameraToggle = async (
currentConnectedCameras: Array<InputItem>,
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.INPUT_DISABLED_DEVICE_ID);
}
};
const handleMicrophoneToggle = async (
currentConnectedAudioInputs: Array<InputItem>,
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.INPUT_DISABLED_DEVICE_ID);
}
};
const StyledCallWindowControls = styled.div`
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 0.25s ease-in-out;
display: flex;
justify-content: center;
opacity: 0;
&:hover {
opacity: 1;
}
`;
export const CallWindowControls = ({
currentConnectedCameras,
currentConnectedAudioInputs,
isAudioMuted,
remoteStreamVideoIsMuted,
localStreamVideoIsMuted,
isFullScreen,
}: {
isAudioMuted: boolean;
localStreamVideoIsMuted: boolean;
remoteStreamVideoIsMuted: boolean;
currentConnectedAudioInputs: Array<InputItem>;
currentConnectedCameras: Array<InputItem>;
isFullScreen: boolean;
}) => {
return (
<StyledCallWindowControls>
<HangUpButton />
<VideoInputButton
currentConnectedCameras={currentConnectedCameras}
localStreamVideoIsMuted={localStreamVideoIsMuted}
hideArrowIcon={isFullScreen}
/>
<AudioInputButton
currentConnectedAudioInputs={currentConnectedAudioInputs}
isAudioMuted={isAudioMuted}
hideArrowIcon={isFullScreen}
/>
{!remoteStreamVideoIsMuted && <ShowInFullScreenButton isFullScreen={isFullScreen} />}
</StyledCallWindowControls>
);
};

View file

@ -9,6 +9,7 @@ import {
getCallIsInFullScreen,
getHasOngoingCallWithFocusedConvo,
} from '../../../state/selectors/conversations';
import { CallWindowControls } from './CallButtons';
import { StyledVideoElement } from './DraggableCallContainer';
const CallInFullScreenVisible = styled.div`
@ -30,10 +31,14 @@ export const CallInFullScreenContainer = () => {
const ongoingCallWithFocused = useSelector(getHasOngoingCallWithFocusedConvo);
const hasOngoingCallFullScreen = useSelector(getCallIsInFullScreen);
const { remoteStream, remoteStreamVideoIsMuted } = useVideoCallEventsListener(
'CallInFullScreenContainer',
true
);
const {
remoteStream,
remoteStreamVideoIsMuted,
currentConnectedAudioInputs,
currentConnectedCameras,
isAudioMuted,
localStreamVideoIsMuted,
} = useVideoCallEventsListener('CallInFullScreenContainer', true);
const videoRefRemote = React.useRef<HTMLVideoElement>(null);
@ -57,7 +62,9 @@ export const CallInFullScreenContainer = () => {
}
if (videoRefRemote?.current) {
videoRefRemote.current.srcObject = remoteStream;
if (videoRefRemote.current.srcObject !== remoteStream) {
videoRefRemote.current.srcObject = remoteStream;
}
}
return (
@ -67,6 +74,14 @@ export const CallInFullScreenContainer = () => {
autoPlay={true}
isVideoMuted={remoteStreamVideoIsMuted}
/>
<CallWindowControls
currentConnectedAudioInputs={currentConnectedAudioInputs}
currentConnectedCameras={currentConnectedCameras}
isAudioMuted={isAudioMuted}
localStreamVideoIsMuted={localStreamVideoIsMuted}
remoteStreamVideoIsMuted={remoteStreamVideoIsMuted}
isFullScreen={true}
/>
</CallInFullScreenVisible>
);
};

View file

@ -1,9 +1,9 @@
import React, { useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useSelector } from 'react-redux';
import styled from 'styled-components';
import _ from 'underscore';
import { CallManager, ToastUtils, UserUtils } from '../../../session/utils';
import { UserUtils } from '../../../session/utils';
import {
getHasOngoingCallWith,
getHasOngoingCallWithFocusedConvo,
@ -11,13 +11,9 @@ import {
getHasOngoingCallWithFocusedConvosIsConnecting,
getHasOngoingCallWithPubkey,
} from '../../../state/selectors/conversations';
import { SessionIconButton } from '../icon';
import { animation, contextMenu, Item, Menu } from 'react-contexify';
import { InputItem } from '../../../session/utils/CallManager';
import { DropDownAndToggleButton } from '../icon/DropDownAndToggleButton';
import { StyledVideoElement } from './DraggableCallContainer';
import { Avatar, AvatarSize } from '../../Avatar';
import { setFullScreenCall } from '../../../state/ducks/conversations';
import { useVideoCallEventsListener } from '../../../hooks/useVideoEventListener';
import {
useAvatarPath,
@ -25,6 +21,7 @@ import {
useOurConversationUsername,
} from '../../../hooks/useParamSelector';
import { useModuloWithTripleDots } from '../../../hooks/useModuloWithTripleDots';
import { CallWindowControls } from './CallButtons';
const VideoContainer = styled.div`
height: 100%;
@ -43,30 +40,6 @@ const InConvoCallWindow = styled.div`
flex-grow: 1;
`;
const InConvoCallWindowControls = styled.div`
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 0.25s ease-in-out;
display: flex;
justify-content: center;
opacity: 0;
&:hover {
opacity: 1;
}
`;
const RelativeCallWindow = styled.div`
position: relative;
height: 100%;
@ -74,56 +47,6 @@ const RelativeCallWindow = styled.div`
flex-grow: 1;
`;
const VideoInputMenu = ({
triggerId,
camerasList,
}: {
triggerId: string;
camerasList: Array<InputItem>;
}) => {
return (
<Menu id={triggerId} animation={animation.fade}>
{camerasList.map(m => {
return (
<Item
key={m.deviceId}
onClick={() => {
void CallManager.selectCameraByDeviceId(m.deviceId);
}}
>
{m.label.substr(0, 40)}
</Item>
);
})}
</Menu>
);
};
const AudioInputMenu = ({
triggerId,
audioInputsList,
}: {
triggerId: string;
audioInputsList: Array<InputItem>;
}) => {
return (
<Menu id={triggerId} animation={animation.fade}>
{audioInputsList.map(m => {
return (
<Item
key={m.deviceId}
onClick={() => {
void CallManager.selectAudioInputByDeviceId(m.deviceId);
}}
>
{m.label.substr(0, 40)}
</Item>
);
})}
</Menu>
);
};
const CenteredAvatarInConversation = styled.div`
top: -50%;
transform: translateY(-50%);
@ -137,116 +60,6 @@ const CenteredAvatarInConversation = styled.div`
align-items: center;
`;
const videoTriggerId = 'video-menu-trigger-id';
const audioTriggerId = 'audio-menu-trigger-id';
const ShowInFullScreenButton = () => {
const dispatch = useDispatch();
const showInFullScreen = () => {
dispatch(setFullScreenCall(true));
};
return (
<SessionIconButton
iconSize={60}
iconPadding="20px"
iconType="fullscreen"
backgroundColor="white"
borderRadius="50%"
onClick={showInFullScreen}
iconColor="black"
margin="10px"
/>
);
};
const HangUpButton = () => {
const ongoingCallPubkey = useSelector(getHasOngoingCallWithPubkey);
const handleEndCall = async () => {
// call method to end call connection
if (ongoingCallPubkey) {
await CallManager.USER_hangup(ongoingCallPubkey);
}
};
return (
<SessionIconButton
iconSize={60}
iconPadding="20px"
iconType="hangup"
backgroundColor="white"
borderRadius="50%"
onClick={handleEndCall}
iconColor="red"
margin="10px"
/>
);
};
const showAudioInputMenu = (
currentConnectedAudioInputs: Array<any>,
e: React.MouseEvent<HTMLDivElement>
) => {
if (currentConnectedAudioInputs.length === 0) {
ToastUtils.pushNoAudioInputFound();
return;
}
contextMenu.show({
id: audioTriggerId,
event: e,
});
};
const showVideoInputMenu = (
currentConnectedCameras: Array<any>,
e: React.MouseEvent<HTMLDivElement>
) => {
if (currentConnectedCameras.length === 0) {
ToastUtils.pushNoCameraFound();
return;
}
contextMenu.show({
id: videoTriggerId,
event: e,
});
};
const handleCameraToggle = async (
currentConnectedCameras: Array<InputItem>,
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.INPUT_DISABLED_DEVICE_ID);
}
};
const handleMicrophoneToggle = async (
currentConnectedAudioInputs: Array<InputItem>,
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.INPUT_DISABLED_DEVICE_ID);
}
};
const StyledCenteredLabel = styled.div`
position: absolute;
left: 50%;
@ -362,32 +175,14 @@ export const InConversationCallContainer = () => {
)}
</VideoContainer>
<InConvoCallWindowControls>
<HangUpButton />
<DropDownAndToggleButton
iconType="camera"
isMuted={localStreamVideoIsMuted}
onMainButtonClick={() => {
void handleCameraToggle(currentConnectedCameras, localStreamVideoIsMuted);
}}
onArrowClick={e => {
showVideoInputMenu(currentConnectedCameras, e);
}}
/>
<DropDownAndToggleButton
iconType="microphone"
isMuted={isAudioMuted}
onMainButtonClick={() => {
void handleMicrophoneToggle(currentConnectedAudioInputs, isAudioMuted);
}}
onArrowClick={e => {
showAudioInputMenu(currentConnectedAudioInputs, e);
}}
/>
{!remoteStreamVideoIsMuted && <ShowInFullScreenButton />}
</InConvoCallWindowControls>
<VideoInputMenu triggerId={videoTriggerId} camerasList={currentConnectedCameras} />
<AudioInputMenu triggerId={audioTriggerId} audioInputsList={currentConnectedAudioInputs} />
<CallWindowControls
currentConnectedAudioInputs={currentConnectedAudioInputs}
currentConnectedCameras={currentConnectedCameras}
isAudioMuted={isAudioMuted}
localStreamVideoIsMuted={localStreamVideoIsMuted}
remoteStreamVideoIsMuted={remoteStreamVideoIsMuted}
isFullScreen={false}
/>
</RelativeCallWindow>
</InConvoCallWindow>
);