Files
desktop/app/components/Call/Call.tsx

135 lines
7.8 KiB
TypeScript

import { useRosettaColors } from "@/app/hooks/useRosettaColors";
import { useAvatars } from "@/app/providers/AvatarProvider/useAvatars";
import { CallContextValue, CallState } from "@/app/providers/CallProvider/CallProvider";
import { translateDurationToTime } from "@/app/providers/CallProvider/translateDurationTime";
import { useUserInformation } from "@/app/providers/InformationProvider/useUserInformation";
import { Avatar, Box, Flex, Popover, Text, useMantineTheme } from "@mantine/core";
import { IconChevronLeft, IconMicrophone, IconMicrophoneOff, IconPhone, IconPhoneX, IconQrcode, IconVolume, IconVolumeOff, IconX } from "@tabler/icons-react";
import { KeyImage } from "../KeyImage/KeyImage";
export interface CallProps {
context: CallContextValue;
}
export function Call(props: CallProps) {
const {
activeCall,
duration,
callState,
close,
sound,
setSound,
setMuted,
setShowCallView,
muted,
getKeyCast,
accept
} = props.context;
const [userInfo] = useUserInformation(activeCall);
const avatars = useAvatars(activeCall);
const colors = useRosettaColors();
const theme = useMantineTheme();
return (
<Box pos={'absolute'} top={0} left={0} w={'100%'} h={'100vh'} style={{
zIndex: 11,
background: 'linear-gradient(120deg,#141414 0%, #000000 100%)',
}}>
<Flex h={'100%'} w={'100vw'} direction={'column'} gap={'lg'} pt={'xl'}>
<Flex direction={'row'} w={'100%'} gap={'sm'} align={'center'} justify={'space-between'} p={'sm'}>
<Flex style={{
cursor: 'pointer'
}} onClick={() => setShowCallView(false)} justify={'center'} align={'center'}>
<IconChevronLeft size={20}></IconChevronLeft>
<Text fw={500}>Back</Text>
</Flex>
<Flex>
<Popover width={300} withArrow>
<Popover.Target>
<IconQrcode size={24}></IconQrcode>
</Popover.Target>
<Popover.Dropdown p={'xs'}>
<Flex direction={'row'} align={'center'} gap={'xs'}>
<Text maw={300} c={'dimmed'} fz={'xs'}>
This call is secured by 256 bit end-to-end encryption. Only you and the recipient can read or listen to the content of this call.
</Text>
<KeyImage radius={0} colors={[
theme.colors.blue[1],
theme.colors.blue[2],
theme.colors.blue[3],
theme.colors.blue[4],
theme.colors.blue[5]
]} size={80} keyRender={getKeyCast()}></KeyImage>
</Flex>
</Popover.Dropdown>
</Popover>
</Flex>
</Flex>
<Flex direction={'column'} mt={'xl'} style={{
userSelect: 'none'
}} w={'100vw'} gap={'sm'} align={'center'} justify={'center'}>
<Avatar size={128} bg={avatars.length > 0 ? '#fff' : undefined} src={avatars.length > 0 ? avatars[0].avatar : undefined} color={'initials'} name={userInfo.title}></Avatar>
<Text fz={20} fw={'bold'} c={'#FFF'}>{userInfo.title}</Text>
{callState == CallState.ACTIVE && (<Text fz={14} c={'#FFF'}>{translateDurationToTime(duration)}</Text>)}
{callState == CallState.CONNECTING && (<Text fz={14} c={'#FFF'}>Connecting...</Text>)}
{callState == CallState.INCOMING && (<Text fz={14} c={'#FFF'}>Incoming call...</Text>)}
{callState == CallState.KEY_EXCHANGE && (<Text fz={14} c={'#FFF'}>Exchanging encryption keys...</Text>)}
<Flex gap={'xl'} align={'center'} justify={'center'} mt={'xl'}>
{callState == CallState.ACTIVE || callState == CallState.CONNECTING || callState == CallState.KEY_EXCHANGE && (
<>
<Box w={50} onClick={() => setSound(!sound)} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={sound ? colors.chevrons.active : colors.chevrons.disabled}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
{!sound && <IconVolume size={24} color={'#fff'}></IconVolume>}
{sound && <IconVolumeOff size={24} color={'#fff'}></IconVolumeOff>}
</Flex>
</Box>
<Box w={50} onClick={() => setMuted(!muted)} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={!muted ? colors.chevrons.active : colors.chevrons.disabled}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
{muted && <IconMicrophone size={24} color={'#fff'}></IconMicrophone>}
{!muted && <IconMicrophoneOff size={24} color={'#fff'}></IconMicrophoneOff>}
</Flex>
</Box>
<Box w={50} onClick={close} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={colors.error}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
<IconPhoneX size={24} color={'#fff'}></IconPhoneX>
</Flex>
</Box>
</>
)}
{callState == CallState.INCOMING && (
<>
{userInfo.title != "Rosetta" && (
<Box w={50} onClick={close} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={colors.error}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
<IconX size={24} color={'#fff'}></IconX>
</Flex>
</Box>
)}
<Box w={userInfo.title != "Rosetta" ? 50 : 100} onClick={accept} style={{
borderRadius: '50%',
cursor: 'pointer'
}} h={userInfo.title != "Rosetta" ? 50 : 100} bg={colors.success}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
<IconPhone size={24} color={'#fff'}></IconPhone>
</Flex>
</Box>
</>
)}
</Flex>
</Flex>
</Flex>
</Box>
)
}