135 lines
7.8 KiB
TypeScript
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>
|
|
)
|
|
} |