blob: fde276edb205863b8547d95173e3289933e8b330 [file] [log] [blame]
simon2d3b6532022-11-08 21:01:57 -05001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
18
simonf929a362022-11-18 16:53:45 -050019import { Box, CircularProgress, Grid, IconButtonProps, Stack, Typography } from '@mui/material';
Gabriel Rochon61f82af2022-11-22 22:28:02 -050020import { ComponentType, ReactNode, useContext, useMemo } from 'react';
simon4e7445c2022-11-16 21:18:46 -050021import { useTranslation } from 'react-i18next';
simon9076a9a2022-11-29 17:13:01 -050022import { useLocation } from 'react-router-dom';
simon2d3b6532022-11-08 21:01:57 -050023
24import {
25 CallingAnswerAudioButton,
26 CallingAnswerVideoButton,
simonf929a362022-11-18 16:53:45 -050027 CallingCancelButton,
simon2d3b6532022-11-08 21:01:57 -050028 CallingRefuseButton,
29} from '../components/CallButtons';
Gabriel Rochon15a5fb22022-11-27 19:25:14 -050030import ConversationAvatar from '../components/ConversationAvatar';
simon9076a9a2022-11-29 17:13:01 -050031import { CallContext, CallStatus } from '../contexts/CallProvider';
Gabriel Rochon61f82af2022-11-22 22:28:02 -050032import { ConversationContext } from '../contexts/ConversationProvider';
simon2d3b6532022-11-08 21:01:57 -050033
simon9076a9a2022-11-29 17:13:01 -050034export const CallPending = () => {
Gabriel Rochon15a5fb22022-11-27 19:25:14 -050035 const { conversation } = useContext(ConversationContext);
simon9076a9a2022-11-29 17:13:01 -050036 const { callRole } = useContext(CallContext);
simon2d3b6532022-11-08 21:01:57 -050037 return (
38 <Stack
39 direction="column"
40 justifyContent="center"
41 alignItems="center"
42 height="100%"
43 spacing={4}
simon9f814a32022-11-22 21:40:53 -050044 flexGrow={1}
simon2d3b6532022-11-08 21:01:57 -050045 sx={{
46 backgroundColor: 'black',
47 }}
48 >
49 <Box
50 sx={{
51 position: 'relative',
52 display: 'flex',
53 alignItems: 'center',
54 justifyContent: 'center',
55 width: '100%',
56 height: '30%',
57 }}
58 >
59 <Box
60 sx={{
61 aspectRatio: '1',
62 height: '100%',
63 position: 'absolute',
64 }}
65 >
66 <CircularProgress
67 disableShrink
68 thickness={1}
69 size="100%"
70 sx={{
71 position: 'absolute',
72 color: 'white',
73 zIndex: 1,
74 }}
75 />
Gabriel Rochon15a5fb22022-11-27 19:25:14 -050076 <ConversationAvatar
simonf929a362022-11-18 16:53:45 -050077 alt="contact profile picture"
Gabriel Rochon15a5fb22022-11-27 19:25:14 -050078 displayName={conversation.getDisplayNameNoFallback()}
simon2d3b6532022-11-08 21:01:57 -050079 style={{
simon2d3b6532022-11-08 21:01:57 -050080 width: '100%',
81 height: '100%',
simon2d3b6532022-11-08 21:01:57 -050082 }}
83 />
84 </Box>
85 </Box>
simon9076a9a2022-11-29 17:13:01 -050086 {callRole === 'caller' ? <CallPendingCallerInterface /> : <CallPendingReceiverInterface />}
simon2d3b6532022-11-08 21:01:57 -050087 </Stack>
88 );
89};
90
simonf929a362022-11-18 16:53:45 -050091const CallPendingDetails = ({
92 title,
93 buttons,
94}: {
95 title: ReactNode;
96 buttons: {
97 ButtonComponent: ComponentType<IconButtonProps>;
98 title: ReactNode;
99 }[];
100}) => {
simon2d3b6532022-11-08 21:01:57 -0500101 return (
simon4e7445c2022-11-16 21:18:46 -0500102 <>
simon2d3b6532022-11-08 21:01:57 -0500103 <Typography variant="h1" color="white">
simonf929a362022-11-18 16:53:45 -0500104 {title}
simon2d3b6532022-11-08 21:01:57 -0500105 </Typography>
simon4e7445c2022-11-16 21:18:46 -0500106 <Box width="50%">
simonf929a362022-11-18 16:53:45 -0500107 <Grid container justifyContent="center">
108 {buttons.map(({ ButtonComponent, title: buttonTitle }, i) => (
109 <Grid item key={i} xs={4}>
110 <Stack direction="column" alignItems="center" spacing={1} sx={{}}>
111 <ButtonComponent color="inherit" size="large" />
112 <Typography variant="body2" color="white" sx={{ opacity: 0.75 }}>
113 {buttonTitle}
114 </Typography>
115 </Stack>
116 </Grid>
117 ))}
118 </Grid>
simon4e7445c2022-11-16 21:18:46 -0500119 </Box>
120 </>
simon2d3b6532022-11-08 21:01:57 -0500121 );
122};
123
simon9076a9a2022-11-29 17:13:01 -0500124export const CallPendingCallerInterface = () => {
125 const { callStatus } = useContext(CallContext);
simon4e7445c2022-11-16 21:18:46 -0500126 const { t } = useTranslation();
Gabriel Rochon61f82af2022-11-22 22:28:02 -0500127 const { conversation } = useContext(ConversationContext);
128 const memberName = useMemo(() => conversation.getFirstMember().contact.getRegisteredName(), [conversation]);
simonf929a362022-11-18 16:53:45 -0500129
simon9076a9a2022-11-29 17:13:01 -0500130 let title = t('loading');
131
132 switch (callStatus) {
133 case CallStatus.Ringing:
134 title = t('calling', {
135 member0: memberName,
136 });
137 break;
138 case CallStatus.Connecting:
139 title = t('connecting');
140 break;
141 }
142
simon2d3b6532022-11-08 21:01:57 -0500143 return (
simonf929a362022-11-18 16:53:45 -0500144 <CallPendingDetails
simon9076a9a2022-11-29 17:13:01 -0500145 title={title}
simonf929a362022-11-18 16:53:45 -0500146 buttons={[
147 {
148 ButtonComponent: CallingCancelButton,
149 title: t('end_call'),
150 },
151 ]}
152 />
153 );
154};
155
simon9076a9a2022-11-29 17:13:01 -0500156export const CallPendingReceiverInterface = () => {
157 const { state } = useLocation();
158 const { callStatus } = useContext(CallContext);
159
simonf929a362022-11-18 16:53:45 -0500160 const { t } = useTranslation();
Gabriel Rochon61f82af2022-11-22 22:28:02 -0500161 const { conversation } = useContext(ConversationContext);
162 const memberName = useMemo(() => conversation.getFirstMember().contact.getRegisteredName(), [conversation]);
simonf929a362022-11-18 16:53:45 -0500163
simon9076a9a2022-11-29 17:13:01 -0500164 let title = t('loading');
165
166 switch (callStatus) {
167 case CallStatus.Ringing:
168 title = t('incoming_call', {
169 context: state?.isVideoOn ? 'video' : 'audio',
170 member0: memberName,
171 });
172 break;
173 case CallStatus.Connecting:
174 title = t('connecting');
175 break;
176 }
177
simonf929a362022-11-18 16:53:45 -0500178 return (
179 <CallPendingDetails
simon9076a9a2022-11-29 17:13:01 -0500180 title={title}
simonf929a362022-11-18 16:53:45 -0500181 buttons={[
182 {
183 ButtonComponent: CallingRefuseButton,
184 title: t('refuse_call'),
185 },
186 {
187 ButtonComponent: CallingAnswerAudioButton,
188 title: t('accept_call_audio'),
189 },
190 {
191 ButtonComponent: CallingAnswerVideoButton,
192 title: t('accept_call_video'),
193 },
194 ]}
195 />
simon2d3b6532022-11-08 21:01:57 -0500196 );
197};