blob: bab36b0b9ba2e199e531cc205519cac245564a7d [file] [log] [blame]
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
import { Box, ListItem, ListItemAvatar, ListItemText, Stack, StackProps, Typography } from '@mui/material';
import { Conversation } from 'jami-web-common';
import { QRCodeCanvas } from 'qrcode.react';
import { MouseEvent, useState } from 'react';
import Modal from 'react-modal';
import { useNavigate, useParams } from 'react-router-dom';
import authManager from '../AuthManager';
import { setRefreshFromSlice } from '../redux/appSlice';
import { useAppDispatch } from '../redux/hooks';
import ConversationAvatar from './ConversationAvatar';
import { RemoveContactIcon, VideoCallIcon } from './SvgIcon';
import { AudioCallIcon, BlockContactIcon, ContactDetailsIcon, CrossIcon, MessageIcon } from './SvgIcon';
const customStyles: Modal.Styles = {
content: {
// right: "auto",
// bottom: "auto",
// // marginRight: "-50%",
// transform: "translate(-50%, -50%)",
// padding: "16px"
// top: "1364px",
left: '94px',
width: '180px',
height: '262px',
background: '#FFFFFF 0% 0% no-repeat padding-box',
boxShadow: '3px 3px 7px #00000029',
borderRadius: '5px 20px 20px 20px',
opacity: '1',
textAlign: 'left',
font: 'normal normal normal 12px/26px Ubuntu',
letterSpacing: '0px',
color: '#000000',
},
};
const cancelStyles: Modal.Styles = {
content: {
left: '94px',
width: '300px',
height: '220px',
background: '#FFFFFF 0% 0% no-repeat padding-box',
boxShadow: '3px 3px 7px #00000029',
borderRadius: '20px',
opacity: '1',
textAlign: 'left',
font: 'normal normal normal 12px/26px Ubuntu',
letterSpacing: '0px',
color: '#000000',
},
};
const contactDetailsStyles: Modal.Styles = {
content: {
left: '94px',
width: '450px',
height: '450px',
background: '#FFFFFF 0% 0% no-repeat padding-box',
boxShadow: '3px 3px 7px #00000029',
borderRadius: '20px',
opacity: '1',
textAlign: 'left',
font: 'normal normal normal 12px/26px Ubuntu',
letterSpacing: '0px',
color: '#000000',
},
};
const stackStyles: StackProps = {
flexDirection: 'row',
marginBottom: '4px',
spacing: '40px',
flex: 1,
alignItems: 'center',
};
const iconTextStyle = {
marginRight: '10px',
};
const iconColor = '#005699';
type ConversationListItemProps = {
conversation: Conversation;
};
export default function ConversationListItem({ conversation }: ConversationListItemProps) {
const { conversationId, contactId } = useParams();
const dispatch = useAppDispatch();
const pathId = conversationId || contactId;
const isSelected = conversation.getDisplayUri() === pathId;
const navigate = useNavigate();
const [modalIsOpen, setIsOpen] = useState(false);
const [modalDetailsIsOpen, setModalDetailsIsOpen] = useState(false);
const [modalDeleteIsOpen, setModalDeleteIsOpen] = useState(false);
const [blockOrRemove, setBlockOrRemove] = useState(true);
const [userId, setUserId] = useState(conversation?.getFirstMember()?.contact.getUri());
const [isSwarm, setIsSwarm] = useState('true');
const openModal = (e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
console.log(e);
setIsOpen(true);
};
const openModalDetails = () => setModalDetailsIsOpen(true);
const openModalDelete = () => setModalDeleteIsOpen(true);
const closeModal = () => setIsOpen(false);
const closeModalDetails = () => setModalDetailsIsOpen(false);
const closeModalDelete = () => setModalDeleteIsOpen(false);
const getContactDetails = () => {
const controller = new AbortController();
authManager
.fetch(`/api/accounts/${conversation.getAccountId()}/contacts/details/${userId}`, {
signal: controller.signal,
})
.then((res) => res.json())
.then((result) => {
console.log('CONTACT LIST - DETAILS: ', result);
})
.catch((e) => console.log('ERROR GET CONTACT DETAILS: ', e));
};
const removeOrBlock = (typeOfRemove: 'block' | 'remove') => {
console.log(typeOfRemove);
setBlockOrRemove(false);
console.log('EEEH', typeOfRemove, conversation.getAccountId(), userId);
const controller = new AbortController();
authManager
.fetch(`/api/accounts/${conversation.getAccountId()}/contacts/${typeOfRemove}/${userId}`, {
signal: controller.signal,
method: 'DELETE',
})
.then((res) => res.json())
.then((result) => {
console.log('propre');
dispatch(setRefreshFromSlice());
})
.catch((e) => {
console.log(`ERROR ${typeOfRemove}ing CONTACT : `, e);
dispatch(setRefreshFromSlice());
});
closeModalDelete();
};
const uri = conversation.getId() ? `conversation/${conversation.getId()}` : `addContact/${userId}`;
return (
<div onContextMenu={openModal}>
<div>
<Modal
isOpen={modalIsOpen}
// onAfterOpen={afterOpenModal}
onRequestClose={closeModal}
style={customStyles}
contentLabel="Example Modal"
>
<Stack
onClick={() => {
navigate(`/account/${conversation.getAccountId()}/${uri}`);
closeModal();
}}
{...stackStyles}
>
<div style={{ ...iconTextStyle }}>
<MessageIcon style={{ color: iconColor }} />
</div>
Message
</Stack>
<Stack {...stackStyles}>
<div style={{ ...iconTextStyle }}>
<AudioCallIcon style={{ color: iconColor }} />
</div>
Démarrer appel audio
</Stack>
<Stack {...stackStyles}>
<div style={{ ...iconTextStyle }}>
<VideoCallIcon style={{ color: iconColor }} />
</div>
Démarrer appel vidéo
</Stack>
<Stack
{...stackStyles}
onClick={() => {
navigate(`/account/${conversation.getAccountId()}/`);
closeModal();
}}
>
<div style={{ ...iconTextStyle }}>
<CrossIcon style={{ color: iconColor }} />
</div>
Fermer la conversation
</Stack>
<Stack
onClick={() => {
console.log('open details contact for: ');
closeModal();
openModalDetails();
getContactDetails();
}}
{...stackStyles}
>
<div style={{ ...iconTextStyle }}>
<ContactDetailsIcon style={{ color: iconColor }} />
</div>
Détails de la conversation
</Stack>
<Stack
onClick={() => {
setBlockOrRemove(true);
closeModal();
openModalDelete();
}}
{...stackStyles}
>
<div style={{ ...iconTextStyle }}>
<BlockContactIcon style={{ color: iconColor }} />
</div>
Bloquer le contact
</Stack>
<Stack
onClick={() => {
setBlockOrRemove(false);
closeModal();
openModalDelete();
}}
{...stackStyles}
>
<div style={{ ...iconTextStyle }}>
<RemoveContactIcon style={{ color: iconColor }} />
</div>
Supprimer contact
</Stack>
</Modal>
</div>
<div>
<Modal
isOpen={modalDetailsIsOpen}
onRequestClose={closeModalDetails}
style={contactDetailsStyles}
contentLabel="Détails contact"
>
<Stack direction={'row'} alignContent="flex-end">
<Stack direction={'column'}>
<div style={{ height: '100px' }}>
<ConversationAvatar displayName={conversation.getDisplayNameNoFallback()} />
</div>
<div
style={{
fontSize: '20px',
marginBottom: '20px',
height: '20px',
}}
>
Informations
</div>
<Typography variant="caption">Nom d&apos;utilisateur</Typography>
<div style={{ height: '20px' }} />
<Typography variant="caption">Identifiant </Typography>
<div style={{ height: '20px' }} />
<div
style={{
flex: 1,
height: '150px',
flexDirection: 'column',
// alignSelf: "flex-end",
}}
>
<Typography variant="caption">Code QR</Typography>
</div>
<Typography variant="caption">est un swarm </Typography>
</Stack>
<Stack direction={'column'}>
<div
style={{
fontWeight: 'bold',
fontSize: '20px',
height: '100px',
}}
>
{conversation.getDisplayNameNoFallback() + '(resolved name)'}
</div>
<div
style={{
height: '40px',
}}
/>
<Typography variant="caption">
<div style={{ fontWeight: 'bold' }}>{conversation.getDisplayNameNoFallback()}</div>
</Typography>
<div style={{ height: '20px' }} />
<Typography variant="caption">
<div style={{ fontWeight: 'bold' }}> {userId}</div>
</Typography>
<div style={{ height: '20px' }} />
<div>
<QRCodeCanvas size={40} value={`${userId}`} />
</div>
<Typography variant="caption">
<div style={{ fontWeight: 'bold' }}> {isSwarm}</div>
</Typography>
</Stack>
</Stack>
<div
onClick={closeModalDetails}
style={{
width: '100px',
borderStyle: 'solid',
textAlign: 'center',
borderRadius: '5px',
marginLeft: '150px',
marginTop: '10px',
}}
>
<Typography variant="caption">Fermer</Typography>
</div>
</Modal>
</div>
<div>
<Modal
isOpen={modalDeleteIsOpen}
onRequestClose={closeModalDelete}
style={cancelStyles}
contentLabel="Merci de confirmer"
>
<Typography variant="h4">Merci de confirmer</Typography>
<Stack direction={'column'} justifyContent="space-around" spacing={'75px'}>
<div style={{ textAlign: 'center', marginTop: '10%' }}>
<Typography variant="body2">
Voulez vous vraiment {blockOrRemove ? 'bloquer' : 'supprimer'} ce contact?
</Typography>
</div>
<Stack direction={'row'} top={'25px'} alignSelf="center" spacing={1}>
<Box
onClick={() => {
if (blockOrRemove) removeOrBlock('block');
else removeOrBlock('remove');
}}
style={{
width: '100px',
textAlign: 'center',
borderStyle: 'solid',
borderColor: 'red',
borderRadius: '10px',
color: 'red',
}}
>
{blockOrRemove ? 'Bloquer' : 'Supprimer'}
</Box>
<Box
onClick={closeModalDelete}
style={{
width: '100px',
textAlign: 'center',
paddingLeft: '12px',
paddingRight: '12px',
borderStyle: 'solid',
borderRadius: '10px',
}}
>
Annuler
</Box>
</Stack>
</Stack>
</Modal>
</div>
<ListItem
button
alignItems="flex-start"
selected={isSelected}
onClick={() => navigate(`/account/${conversation.getAccountId()}/${uri}`)}
>
<ListItemAvatar>
<ConversationAvatar displayName={conversation.getDisplayNameNoFallback()} />
</ListItemAvatar>
<ListItemText primary={conversation.getDisplayName()} secondary={conversation.getDisplayUri()} />
</ListItem>
</div>
);
}