blob: 51e9254d691db6998c57ba5cdd152fe50074f43f [file] [log] [blame]
simon07b4eb02022-09-29 17:50:26 -04001import { Box, Stack, Typography } from '@mui/material';
simond47ef9e2022-09-28 22:24:28 -04002import { useCallback, useContext, useEffect, useState } from 'react';
simon07b4eb02022-09-29 17:50:26 -04003
4import Conversation from '../../../model/Conversation';
5import { SocketContext } from '../contexts/socket';
6import { useConversationQuery, useMessagesQuery, useSendMessageMutation } from '../services/conversation';
7import ConversationAvatar from './ConversationAvatar';
8import LoadingPage from './loading';
Adrien Béraud35e7d7c2021-04-13 03:28:39 -04009import MessageList from './MessageList';
10import SendMessageForm from './SendMessageForm';
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040011
simond47ef9e2022-09-28 22:24:28 -040012const ConversationView = (props) => {
13 const socket = useContext(SocketContext);
14 const [conversation, setConversation] = useState();
15 const [messages, setMessages] = useState([]);
16 const [isLoading, setIsLoading] = useState(true);
17 const [error, setError] = useState(false);
idillon08f77172022-09-13 19:14:17 -040018
simond47ef9e2022-09-28 22:24:28 -040019 const conversationQuery = useConversationQuery(props.accountId, props.conversationId);
20 const messagesQuery = useMessagesQuery(props.accountId, props.conversationId);
21 const sendMessageMutation = useSendMessageMutation(props.accountId, props.conversationId);
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040022
Adrien Béraud5e9e19b2021-04-22 01:38:53 -040023 useEffect(() => {
idillonea465602022-09-13 19:58:51 -040024 if (conversationQuery.isSuccess) {
simond47ef9e2022-09-28 22:24:28 -040025 const conversation = Conversation.from(props.accountId, conversationQuery.data);
26 setConversation(conversation);
idillon08f77172022-09-13 19:14:17 -040027 }
simond47ef9e2022-09-28 22:24:28 -040028 }, [conversationQuery.data]);
idillon08f77172022-09-13 19:14:17 -040029
30 useEffect(() => {
idillonea465602022-09-13 19:58:51 -040031 if (messagesQuery.isSuccess) {
simond47ef9e2022-09-28 22:24:28 -040032 const sortedMessages = sortMessages(messagesQuery.data);
33 setMessages(sortedMessages);
idillon08f77172022-09-13 19:14:17 -040034 }
simond47ef9e2022-09-28 22:24:28 -040035 }, [messagesQuery.data]);
idillon08f77172022-09-13 19:14:17 -040036
37 useEffect(() => {
simond47ef9e2022-09-28 22:24:28 -040038 setIsLoading(conversationQuery.isLoading || messagesQuery.isLoading);
39 }, [conversationQuery.isLoading, messagesQuery.isLoading]);
idillonea465602022-09-13 19:58:51 -040040
Adrien Béraudabba2e52021-04-24 21:39:56 -040041 useEffect(() => {
simond47ef9e2022-09-28 22:24:28 -040042 setError(conversationQuery.isError || messagesQuery.isError);
43 }, [conversationQuery.isError, messagesQuery.isError]);
44
45 const sendMessage = useCallback((message) => sendMessageMutation.mutate(message), [sendMessageMutation]);
46
47 useEffect(() => {
48 if (!conversation) return;
49 console.log(`io set conversation ${props.conversationId} ` + socket);
50 if (socket) socket.emit('conversation', { accountId: props.accountId, conversationId: props.conversationId });
51 socket.off('newMessage');
Adrien Béraudabba2e52021-04-24 21:39:56 -040052 socket.on('newMessage', (data) => {
simond47ef9e2022-09-28 22:24:28 -040053 console.log('newMessage');
54 setMessages((messages) => addMessage(messages, data));
55 });
56 }, [socket, setMessages]);
Adrien Béraudabba2e52021-04-24 21:39:56 -040057
idillonea465602022-09-13 19:58:51 -040058 if (isLoading) {
simond47ef9e2022-09-28 22:24:28 -040059 return <LoadingPage />;
idillon08f77172022-09-13 19:14:17 -040060 } else if (error) {
simond47ef9e2022-09-28 22:24:28 -040061 return <div>Error loading {props.conversationId}</div>;
Adrien Béraud5e9e19b2021-04-22 01:38:53 -040062 }
idillonbef18a52022-09-01 01:51:40 -040063
64 return (
simond47ef9e2022-09-28 22:24:28 -040065 <Stack flexGrow={1} height="100%">
idillonbef18a52022-09-01 01:51:40 -040066 <Stack direction="row" flexGrow={0}>
67 <Box style={{ margin: 16, flexShrink: 0 }}>
idillon08f77172022-09-13 19:14:17 -040068 <ConversationAvatar displayName={conversation?.getDisplayNameNoFallback()} />
idillonbef18a52022-09-01 01:51:40 -040069 </Box>
simond47ef9e2022-09-28 22:24:28 -040070 <Box style={{ flex: '1 1 auto', overflow: 'hidden' }}>
71 <Typography className="title" variant="h6">
72 {conversation?.getDisplayName()}
73 </Typography>
74 <Typography className="subtitle" variant="subtitle1">
75 {props.conversationId}
76 </Typography>
idillonbef18a52022-09-01 01:51:40 -040077 </Box>
78 </Stack>
idillonaedab942022-09-01 14:29:43 -040079 <Stack flexGrow={1} overflow="auto" direction="column-reverse">
simond47ef9e2022-09-28 22:24:28 -040080 <MessageList messages={messages} />
idillonbef18a52022-09-01 01:51:40 -040081 </Stack>
82 <Stack flexGrow={0}>
83 <SendMessageForm onSend={sendMessage} />
84 </Stack>
85 </Stack>
simond47ef9e2022-09-28 22:24:28 -040086 );
87};
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040088
idillon08f77172022-09-13 19:14:17 -040089const addMessage = (sortedMessages, message) => {
90 if (sortedMessages.length === 0) {
simond47ef9e2022-09-28 22:24:28 -040091 return [message];
idillon08f77172022-09-13 19:14:17 -040092 } else if (message.id === sortedMessages[sortedMessages.length - 1].linearizedParent) {
simond47ef9e2022-09-28 22:24:28 -040093 return [...sortedMessages, message];
idillon08f77172022-09-13 19:14:17 -040094 } else if (message.linearizedParent === sortedMessages[0].id) {
simond47ef9e2022-09-28 22:24:28 -040095 return [message, ...sortedMessages];
idillon08f77172022-09-13 19:14:17 -040096 } else {
simond47ef9e2022-09-28 22:24:28 -040097 console.log("Can't insert message " + message.id);
idillon08f77172022-09-13 19:14:17 -040098 }
simond47ef9e2022-09-28 22:24:28 -040099};
idillon08f77172022-09-13 19:14:17 -0400100
101const sortMessages = (messages) => {
simond47ef9e2022-09-28 22:24:28 -0400102 let sortedMessages = [];
103 messages.forEach((message) => (sortedMessages = addMessage(sortedMessages, message)));
104 return sortedMessages;
105};
idillon08f77172022-09-13 19:14:17 -0400106
simond47ef9e2022-09-28 22:24:28 -0400107export default ConversationView;