blob: 16c1ccc339c6baf08561e4fd562ea67d9803c0c7 [file] [log] [blame]
simon26e79f72022-10-05 22:16:08 -04001/*
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 */
simon07b4eb02022-09-29 17:50:26 -040018import { Box, ListItem, ListItemAvatar, ListItemText, Stack, Typography } from '@mui/material';
simon20076982022-10-11 15:04:13 -040019import { Conversation } from 'jami-web-common';
simond47ef9e2022-09-28 22:24:28 -040020import { QRCodeCanvas } from 'qrcode.react';
simon07b4eb02022-09-29 17:50:26 -040021import { useState } from 'react';
22import Modal from 'react-modal';
23import { useNavigate, useParams } from 'react-router-dom';
24
simon07b4eb02022-09-29 17:50:26 -040025import authManager from '../AuthManager';
simond8ca2f22022-10-11 23:30:55 -040026import { setRefreshFromSlice } from '../redux/appSlice';
27import { useAppDispatch } from '../redux/hooks';
simon07b4eb02022-09-29 17:50:26 -040028import ConversationAvatar from './ConversationAvatar';
simon35378692022-10-02 23:25:57 -040029import { RemoveContactIcon, VideoCallIcon } from './SvgIcon.tsx';
30import { AudioCallIcon, BlockContactIcon, ContactDetailsIcon, CrossIcon, MessageIcon } from './SvgIcon.tsx';
ervinanoh34eb9472022-09-13 04:20:28 -040031
idillon531b6f22022-09-16 14:02:00 -040032const customStyles = {
33 content: {
ervinanoh8e918042022-09-06 10:30:59 -040034 // right: "auto",
35 // bottom: "auto",
36 // // marginRight: "-50%",
37 // transform: "translate(-50%, -50%)",
ervinanoh8e918042022-09-06 10:30:59 -040038 // padding: "16px"
39
40 // top: "1364px",
simond47ef9e2022-09-28 22:24:28 -040041 left: '94px',
42 width: '180px',
43 height: '262px',
44 background: '#FFFFFF 0% 0% no-repeat padding-box',
45 boxShadow: '3px 3px 7px #00000029',
46 borderRadius: '5px 20px 20px 20px',
47 opacity: '1',
ervinanoh8e918042022-09-06 10:30:59 -040048
simond47ef9e2022-09-28 22:24:28 -040049 textAlign: 'left',
50 font: 'normal normal normal 12px/26px Ubuntu',
51 letterSpacing: '0px',
52 color: '#000000',
ervinanohb81c3912022-09-08 04:13:24 -040053 },
54};
55
56const cancelStyles = {
57 content: {
simond47ef9e2022-09-28 22:24:28 -040058 left: '94px',
59 width: '300px',
60 height: '220px',
61 background: '#FFFFFF 0% 0% no-repeat padding-box',
62 boxShadow: '3px 3px 7px #00000029',
63 borderRadius: '20px',
64 opacity: '1',
ervinanohb81c3912022-09-08 04:13:24 -040065
simond47ef9e2022-09-28 22:24:28 -040066 textAlign: 'left',
67 font: 'normal normal normal 12px/26px Ubuntu',
68 letterSpacing: '0px',
69 color: '#000000',
ervinanohb81c3912022-09-08 04:13:24 -040070 },
71};
72
73const contactDetailsStyles = {
74 content: {
simond47ef9e2022-09-28 22:24:28 -040075 left: '94px',
76 width: '450px',
77 height: '450px',
78 background: '#FFFFFF 0% 0% no-repeat padding-box',
79 boxShadow: '3px 3px 7px #00000029',
80 borderRadius: '20px',
81 opacity: '1',
ervinanohb81c3912022-09-08 04:13:24 -040082
simond47ef9e2022-09-28 22:24:28 -040083 textAlign: 'left',
84 font: 'normal normal normal 12px/26px Ubuntu',
85 letterSpacing: '0px',
86 color: '#000000',
idillon531b6f22022-09-16 14:02:00 -040087 },
88};
Adrien Béraud995e8022021-04-08 13:46:51 -040089
ervinanoh8e918042022-09-06 10:30:59 -040090const stackStyles = {
simond47ef9e2022-09-28 22:24:28 -040091 flexDirection: 'row',
92 marginBottom: '4px',
93 spacing: '40px',
ervinanoh8e918042022-09-06 10:30:59 -040094 flex: 1,
simond47ef9e2022-09-28 22:24:28 -040095 alignItems: 'center',
ervinanoh8e918042022-09-06 10:30:59 -040096};
97
ervinanohb81c3912022-09-08 04:13:24 -040098const iconTextStyle = {
simond47ef9e2022-09-28 22:24:28 -040099 marginRight: '10px',
ervinanohb81c3912022-09-08 04:13:24 -0400100};
101
simond47ef9e2022-09-28 22:24:28 -0400102const iconColor = '#005699';
ervinanohb81c3912022-09-08 04:13:24 -0400103
Adrien Béraudaf09a462021-04-15 18:02:29 -0400104export default function ConversationListItem(props) {
idillon531b6f22022-09-16 14:02:00 -0400105 const { conversationId, contactId } = useParams();
ervinanoh34eb9472022-09-13 04:20:28 -0400106 const dispatch = useAppDispatch();
107
idillon531b6f22022-09-16 14:02:00 -0400108 const conversation = props.conversation;
Adrien Béraud995e8022021-04-08 13:46:51 -0400109
idillon531b6f22022-09-16 14:02:00 -0400110 const pathId = conversationId || contactId;
111 const isSelected = conversation.getDisplayUri() === pathId;
112 const navigate = useNavigate();
113
idillon531b6f22022-09-16 14:02:00 -0400114 const [modalIsOpen, setIsOpen] = useState(false);
115 const [modalDetailsIsOpen, setModalDetailsIsOpen] = useState(false);
116 const [modalDeleteIsOpen, setModalDeleteIsOpen] = useState(false);
ervinanohb81c3912022-09-08 04:13:24 -0400117 const [blockOrRemove, setBlockOrRemove] = useState(true);
simond47ef9e2022-09-28 22:24:28 -0400118 const [userId, setUserId] = useState(conversation?.getFirstMember()?.contact.getUri());
119 const [isSwarm, setIsSwarm] = useState('true');
idillon531b6f22022-09-16 14:02:00 -0400120
ervinanohb81c3912022-09-08 04:13:24 -0400121 const openModal = (e) => {
122 e.preventDefault();
123 console.log(e);
124 setIsOpen(true);
125 };
idillon531b6f22022-09-16 14:02:00 -0400126 const openModalDetails = () => setModalDetailsIsOpen(true);
127 const openModalDelete = () => setModalDeleteIsOpen(true);
idillon531b6f22022-09-16 14:02:00 -0400128 const closeModal = () => setIsOpen(false);
idillon531b6f22022-09-16 14:02:00 -0400129 const closeModalDetails = () => setModalDetailsIsOpen(false);
130 const closeModalDelete = () => setModalDeleteIsOpen(false);
131
ervinanohb81c3912022-09-08 04:13:24 -0400132 let subtitle;
idillon531b6f22022-09-16 14:02:00 -0400133 function afterOpenModal() {
134 // references are now sync'd and can be accessed.
simond47ef9e2022-09-28 22:24:28 -0400135 subtitle.style.color = '#f00';
idillon531b6f22022-09-16 14:02:00 -0400136 }
137
ervinanohb81c3912022-09-08 04:13:24 -0400138 const getContactDetails = () => {
idillon531b6f22022-09-16 14:02:00 -0400139 const controller = new AbortController();
140 authManager
simond47ef9e2022-09-28 22:24:28 -0400141 .fetch(`/api/accounts/${conversation.getAccountId()}/contacts/details/${userId}`, {
142 signal: controller.signal,
143 })
ervinanohb81c3912022-09-08 04:13:24 -0400144 .then((res) => res.json())
idillon531b6f22022-09-16 14:02:00 -0400145 .then((result) => {
simond47ef9e2022-09-28 22:24:28 -0400146 console.log('CONTACT LIST - DETAILS: ', result);
idillon531b6f22022-09-16 14:02:00 -0400147 })
simond47ef9e2022-09-28 22:24:28 -0400148 .catch((e) => console.log('ERROR GET CONTACT DETAILS: ', e));
idillon531b6f22022-09-16 14:02:00 -0400149 };
150
ervinanohb81c3912022-09-08 04:13:24 -0400151 const removeOrBlock = (typeOfRemove) => {
152 console.log(typeOfRemove);
153 setBlockOrRemove(false);
154
simond47ef9e2022-09-28 22:24:28 -0400155 console.log('EEEH', typeOfRemove, conversation.getAccountId(), userId);
ervinanohb81c3912022-09-08 04:13:24 -0400156
157 const controller = new AbortController();
158 authManager
simond47ef9e2022-09-28 22:24:28 -0400159 .fetch(`/api/accounts/${conversation.getAccountId()}/contacts/${typeOfRemove}/${userId}`, {
160 signal: controller.signal,
161 method: 'DELETE',
162 })
ervinanohb81c3912022-09-08 04:13:24 -0400163 .then((res) => res.json())
ervinanoh34eb9472022-09-13 04:20:28 -0400164 .then((result) => {
simond47ef9e2022-09-28 22:24:28 -0400165 console.log('propre');
ervinanoh34eb9472022-09-13 04:20:28 -0400166 dispatch(setRefreshFromSlice());
167 })
168 .catch((e) => {
169 console.log(`ERROR ${typeOfRemove}ing CONTACT : `, e);
170 dispatch(setRefreshFromSlice());
171 });
ervinanohb81c3912022-09-08 04:13:24 -0400172 closeModalDelete();
ervinanohb81c3912022-09-08 04:13:24 -0400173 };
ervinanohb81c3912022-09-08 04:13:24 -0400174
simond47ef9e2022-09-28 22:24:28 -0400175 const uri = conversation.getId() ? `conversation/${conversation.getId()}` : `addContact/${userId}`;
idillon531b6f22022-09-16 14:02:00 -0400176 if (conversation instanceof Conversation) {
177 return (
ervinanohb81c3912022-09-08 04:13:24 -0400178 <div onContextMenu={openModal}>
179 <div name="Modal conversation">
180 <Modal
181 isOpen={modalIsOpen}
182 // onAfterOpen={afterOpenModal}
183 onRequestClose={closeModal}
184 style={customStyles}
185 contentLabel="Example Modal"
idillon531b6f22022-09-16 14:02:00 -0400186 >
ervinanohb81c3912022-09-08 04:13:24 -0400187 <Stack
188 onClick={() => {
189 navigate(`/account/${conversation.getAccountId()}/${uri}`);
190 closeModal();
191 }}
192 {...stackStyles}
193 >
194 <div style={{ ...iconTextStyle }}>
195 <MessageIcon style={{ color: iconColor }} />
196 </div>
197 Message
198 </Stack>
199 <Stack {...stackStyles}>
200 <div style={{ ...iconTextStyle }}>
201 <AudioCallIcon style={{ color: iconColor }} />
202 </div>
203 Démarrer appel audio
204 </Stack>
205
206 <Stack {...stackStyles}>
207 <div style={{ ...iconTextStyle }}>
208 <VideoCallIcon style={{ color: iconColor }} />
209 </div>
210 Démarrer appel vidéo
211 </Stack>
212
213 <Stack
214 {...stackStyles}
215 onClick={() => {
216 navigate(`/account/${conversation.getAccountId()}/`);
217 closeModal();
ervinanoh8e918042022-09-06 10:30:59 -0400218 }}
219 >
ervinanohb81c3912022-09-08 04:13:24 -0400220 <div style={{ ...iconTextStyle }}>
221 <CrossIcon style={{ color: iconColor }} />
222 </div>
223 Fermer la conversation
224 </Stack>
225
226 <Stack
227 onClick={() => {
simond47ef9e2022-09-28 22:24:28 -0400228 console.log('open details contact for: ');
ervinanohb81c3912022-09-08 04:13:24 -0400229 closeModal();
230 openModalDetails();
231 getContactDetails();
232 }}
233 {...stackStyles}
234 >
235 <div style={{ ...iconTextStyle }}>
236 <ContactDetailsIcon style={{ color: iconColor }} />
237 </div>
238 Détails de la conversation
239 </Stack>
240
241 <Stack
242 onClick={() => {
243 setBlockOrRemove(true);
244 closeModal();
245 openModalDelete();
246 }}
247 {...stackStyles}
248 >
249 <div style={{ ...iconTextStyle }}>
250 <BlockContactIcon style={{ color: iconColor }} />
251 </div>
252 Bloquer le contact
253 </Stack>
254
255 <Stack
256 onClick={() => {
257 setBlockOrRemove(false);
258 closeModal();
259 openModalDelete();
260 }}
261 {...stackStyles}
262 >
263 <div style={{ ...iconTextStyle }}>
264 <RemoveContactIcon style={{ color: iconColor }} />
265 </div>
266 Supprimer contact
267 </Stack>
268 </Modal>
269 </div>
270
271 <div name="Contact details">
272 <Modal
273 isOpen={modalDetailsIsOpen}
274 onRequestClose={closeModalDetails}
275 style={contactDetailsStyles}
276 contentLabel="Détails contact"
277 >
simond47ef9e2022-09-28 22:24:28 -0400278 <Stack direction={'row'} alignContent="flex-end">
279 <Stack direction={'column'}>
280 <div style={{ height: '100px' }}>
281 <ConversationAvatar displayName={conversation.getDisplayNameNoFallback()} />
ervinanohb81c3912022-09-08 04:13:24 -0400282 </div>
283
284 <div
285 style={{
simond47ef9e2022-09-28 22:24:28 -0400286 fontSize: '20px',
287 marginBottom: '20px',
288 height: '20px',
ervinanohb81c3912022-09-08 04:13:24 -0400289 }}
290 >
291 Informations
292 </div>
293
simon80b7b3b2022-09-28 17:50:10 -0400294 <Typography variant="caption">Nom d&apos;utilisateur</Typography>
simond47ef9e2022-09-28 22:24:28 -0400295 <div style={{ height: '20px' }} />
ervinanohb81c3912022-09-08 04:13:24 -0400296 <Typography variant="caption">Identifiant </Typography>
simond47ef9e2022-09-28 22:24:28 -0400297 <div style={{ height: '20px' }} />
ervinanohb81c3912022-09-08 04:13:24 -0400298
299 <div
300 style={{
301 flex: 1,
simond47ef9e2022-09-28 22:24:28 -0400302 height: '150px',
303 direction: 'column',
304 flexDirection: 'column',
ervinanohb81c3912022-09-08 04:13:24 -0400305 // alignSelf: "flex-end",
306 }}
307 >
308 <Typography variant="caption">Code QR</Typography>
309 </div>
310
311 <Typography variant="caption">est un swarm </Typography>
312 </Stack>
313
simond47ef9e2022-09-28 22:24:28 -0400314 <Stack direction={'column'}>
ervinanohb81c3912022-09-08 04:13:24 -0400315 <div
316 style={{
simond47ef9e2022-09-28 22:24:28 -0400317 fontWeight: 'bold',
318 fontSize: '20px',
319 height: '100px',
ervinanohb81c3912022-09-08 04:13:24 -0400320 }}
321 >
simond47ef9e2022-09-28 22:24:28 -0400322 {conversation.getDisplayNameNoFallback() + '(resolved name)'}
ervinanohb81c3912022-09-08 04:13:24 -0400323 </div>
324
325 <div
326 style={{
simond47ef9e2022-09-28 22:24:28 -0400327 height: '40px',
ervinanohb81c3912022-09-08 04:13:24 -0400328 }}
329 />
330 <Typography variant="caption">
simond47ef9e2022-09-28 22:24:28 -0400331 <div style={{ fontWeight: 'bold' }}>{conversation.getDisplayNameNoFallback()}</div>
ervinanohb81c3912022-09-08 04:13:24 -0400332 </Typography>
333
simond47ef9e2022-09-28 22:24:28 -0400334 <div style={{ height: '20px' }} />
ervinanohb81c3912022-09-08 04:13:24 -0400335
336 <Typography variant="caption">
simond47ef9e2022-09-28 22:24:28 -0400337 <div style={{ fontWeight: 'bold' }}> {userId}</div>
ervinanohb81c3912022-09-08 04:13:24 -0400338 </Typography>
339
simond47ef9e2022-09-28 22:24:28 -0400340 <div style={{ height: '20px' }} />
ervinanohb81c3912022-09-08 04:13:24 -0400341
simond47ef9e2022-09-28 22:24:28 -0400342 <div height={'40px'}>
ervinanohb81c3912022-09-08 04:13:24 -0400343 <QRCodeCanvas value={`${userId}`} />
344 </div>
345
346 <Typography variant="caption">
simond47ef9e2022-09-28 22:24:28 -0400347 <div style={{ fontWeight: 'bold' }}> {isSwarm}</div>
ervinanohb81c3912022-09-08 04:13:24 -0400348 </Typography>
349 </Stack>
350 </Stack>
351 <div
352 onClick={closeModalDetails}
353 style={{
simond47ef9e2022-09-28 22:24:28 -0400354 width: '100px',
355 borderStyle: 'solid',
356 textAlign: 'center',
357 borderRadius: '5px',
358 marginLeft: '150px',
359 marginTop: '10px',
ervinanohb81c3912022-09-08 04:13:24 -0400360 }}
361 >
362 <Typography variant="caption">Fermer</Typography>
ervinanoh8e918042022-09-06 10:30:59 -0400363 </div>
ervinanohb81c3912022-09-08 04:13:24 -0400364 </Modal>
365 </div>
idillon531b6f22022-09-16 14:02:00 -0400366
ervinanohb81c3912022-09-08 04:13:24 -0400367 <div name="Remove or block details">
368 <Modal
369 isOpen={modalDeleteIsOpen}
370 onRequestClose={closeModalDelete}
371 style={cancelStyles}
372 contentLabel="Merci de confirmer"
idillon531b6f22022-09-16 14:02:00 -0400373 >
ervinanohb81c3912022-09-08 04:13:24 -0400374 <Typography variant="h4">Merci de confirmer</Typography>
simond47ef9e2022-09-28 22:24:28 -0400375 <Stack direction={'column'} justifyContent="space-around" spacing={'75px'}>
376 <div style={{ textAlign: 'center', marginTop: '10%' }}>
ervinanohb81c3912022-09-08 04:13:24 -0400377 <Typography variant="body2">
simond47ef9e2022-09-28 22:24:28 -0400378 Voulez vous vraiment {blockOrRemove ? 'bloquer' : 'supprimer'} ce contact?
ervinanohb81c3912022-09-08 04:13:24 -0400379 </Typography>
380 </div>
ervinanoh8e918042022-09-06 10:30:59 -0400381
simond47ef9e2022-09-28 22:24:28 -0400382 <Stack direction={'row'} top={'25px'} alignSelf="center" spacing={1}>
ervinanohb81c3912022-09-08 04:13:24 -0400383 <Box
384 onClick={() => {
simond47ef9e2022-09-28 22:24:28 -0400385 if (blockOrRemove) removeOrBlock('block');
386 else removeOrBlock('remove');
ervinanohb81c3912022-09-08 04:13:24 -0400387 }}
388 style={{
simond47ef9e2022-09-28 22:24:28 -0400389 width: '100px',
390 textAlign: 'center',
391 borderStyle: 'solid',
392 borderColor: 'red',
393 borderRadius: '10px',
394 color: 'red',
ervinanohb81c3912022-09-08 04:13:24 -0400395 }}
396 >
simond47ef9e2022-09-28 22:24:28 -0400397 {blockOrRemove ? 'Bloquer' : 'Supprimer'}
ervinanohb81c3912022-09-08 04:13:24 -0400398 </Box>
399 <Box
400 onClick={closeModalDelete}
401 style={{
simond47ef9e2022-09-28 22:24:28 -0400402 width: '100px',
403 textAlign: 'center',
404 paddingLeft: '12px',
405 paddingRight: '12px',
406 borderStyle: 'solid',
407 borderRadius: '10px',
ervinanohb81c3912022-09-08 04:13:24 -0400408 }}
409 >
410 Annuler
411 </Box>
412 </Stack>
413 </Stack>
414 </Modal>
415 </div>
idillon531b6f22022-09-16 14:02:00 -0400416
417 <ListItem
418 button
419 alignItems="flex-start"
420 selected={isSelected}
simond47ef9e2022-09-28 22:24:28 -0400421 onClick={() => navigate(`/account/${conversation.getAccountId()}/${uri}`)}
idillon531b6f22022-09-16 14:02:00 -0400422 >
423 <ListItemAvatar>
simond47ef9e2022-09-28 22:24:28 -0400424 <ConversationAvatar displayName={conversation.getDisplayNameNoFallback()} />
idillon531b6f22022-09-16 14:02:00 -0400425 </ListItemAvatar>
simond47ef9e2022-09-28 22:24:28 -0400426 <ListItemText primary={conversation.getDisplayName()} secondary={conversation.getDisplayUri()} />
idillon531b6f22022-09-16 14:02:00 -0400427 </ListItem>
428 </div>
429 );
430 } else return null;
Adrien Béraud995e8022021-04-08 13:46:51 -0400431}