blob: 9a928e742833a6673529048efbbb7ba53b7eda22 [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,
ListItemIcon,
ListItemText,
Menu,
MenuItem,
Stack,
Typography,
} from '@mui/material';
import { Conversation } from 'jami-web-common';
import { QRCodeCanvas } from 'qrcode.react';
import { MouseEvent, useState } from 'react';
import { Trans } from 'react-i18next';
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 { CancelIcon, RemoveContactIcon, VideoCallIcon } from './SvgIcon';
import { AudioCallIcon, BlockContactIcon, ContactDetailsIcon, MessageIcon } from './SvgIcon';
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 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 [menuAnchorEl, setMenuAnchorEl] = useState<HTMLElement | null>(null);
const [modalDetailsIsOpen, setModalDetailsIsOpen] = useState(false);
const [modalDeleteIsOpen, setModalDeleteIsOpen] = useState(false);
const [blockOrRemove, setBlockOrRemove] = useState(true);
const [userId] = useState(conversation?.getFirstMember()?.contact.getUri());
const [isSwarm] = useState(true);
const navigateUrlPrefix = `/deprecated-account/${conversation.getAccountId()}`;
const openMenu = (e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
console.log(e);
setMenuAnchorEl(e.currentTarget);
};
const openModalDetails = () => setModalDetailsIsOpen(true);
const openModalDelete = () => setModalDeleteIsOpen(true);
const closeModal = () => setMenuAnchorEl(null);
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(() => {
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={openMenu}>
<div>
<Menu open={!!menuAnchorEl} onClose={closeModal} anchorEl={menuAnchorEl}>
<MenuItem
onClick={() => {
navigate(`${navigateUrlPrefix}/${uri}`);
closeModal();
}}
>
<ListItemIcon>
<MessageIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_message" />
</ListItemText>
</MenuItem>
<MenuItem
onClick={() => {
navigate(`${navigateUrlPrefix}/call/${conversation.getId()}`);
}}
>
<ListItemIcon>
<AudioCallIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_start_audiocall" />
</ListItemText>
</MenuItem>
<MenuItem
onClick={() => {
navigate(`${navigateUrlPrefix}/call/${conversation.getId()}?video=true`);
}}
>
<ListItemIcon>
<VideoCallIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_start_videocall" />
</ListItemText>
</MenuItem>
{isSelected && (
<MenuItem
onClick={() => {
navigate(`${navigateUrlPrefix}/`);
closeModal();
}}
>
<ListItemIcon>
<CancelIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_close" />
</ListItemText>
</MenuItem>
)}
<MenuItem
onClick={() => {
console.log('open details contact for: ');
closeModal();
openModalDetails();
getContactDetails();
}}
>
<ListItemIcon>
<ContactDetailsIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_details" />
</ListItemText>
</MenuItem>
<MenuItem
onClick={() => {
setBlockOrRemove(true);
closeModal();
openModalDelete();
}}
>
<ListItemIcon>
<BlockContactIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_block_contact" />
</ListItemText>
</MenuItem>
<MenuItem
onClick={() => {
setBlockOrRemove(false);
closeModal();
openModalDelete();
}}
>
<ListItemIcon>
<RemoveContactIcon style={{ color: iconColor }} />
</ListItemIcon>
<ListItemText>
<Trans i18nKey="conversation_delete_contact" />
</ListItemText>
</MenuItem>
</Menu>
</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' }}> {String(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(`${navigateUrlPrefix}/${uri}`)}
>
<ListItemAvatar>
<ConversationAvatar displayName={conversation.getDisplayNameNoFallback()} />
</ListItemAvatar>
<ListItemText primary={conversation.getDisplayName()} secondary={conversation.getDisplayUri()} />
</ListItem>
</div>
);
}