blob: ba9b932187b0cef0d21091ae07fbf85f3e047d0a [file] [log] [blame]
idillon322e4ac2022-09-14 12:48:43 -04001import React, { useCallback, useContext, useEffect, useState } from 'react';
Adrien Béraud35e7d7c2021-04-13 03:28:39 -04002import MessageList from './MessageList';
3import SendMessageForm from './SendMessageForm';
Adrien Béraud35e7d7c2021-04-13 03:28:39 -04004import Conversation from '../../../model/Conversation';
Adrien Béraud150b4782021-04-21 19:40:59 -04005import LoadingPage from './loading';
idillonbef18a52022-09-01 01:51:40 -04006import { Box, Stack, Typography } from '@mui/material';
7import ConversationAvatar from './ConversationAvatar';
idillonea465602022-09-13 19:58:51 -04008import { useConversationQuery, useMessagesQuery, useSendMessageMutation } from '../services/conversation';
idillon322e4ac2022-09-14 12:48:43 -04009import { SocketContext } from '../contexts/socket';
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040010
Adrien Béraud5e9e19b2021-04-22 01:38:53 -040011const ConversationView = props => {
idillon322e4ac2022-09-14 12:48:43 -040012 const socket = useContext(SocketContext)
idillon08f77172022-09-13 19:14:17 -040013 const [conversation, setConversation] = useState()
14 const [messages, setMessages] = useState([])
idillonea465602022-09-13 19:58:51 -040015 const [isLoading, setIsLoading] = useState(true)
idillon08f77172022-09-13 19:14:17 -040016 const [error, setError] = useState(false)
17
18 const conversationQuery = useConversationQuery(props.accountId, props.conversationId)
19 const messagesQuery = useMessagesQuery(props.accountId, props.conversationId)
idillonea465602022-09-13 19:58:51 -040020 const sendMessageMutation = useSendMessageMutation(props.accountId, props.conversationId)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040021
Adrien Béraud5e9e19b2021-04-22 01:38:53 -040022 useEffect(() => {
idillonea465602022-09-13 19:58:51 -040023 if (conversationQuery.isSuccess) {
idillon08f77172022-09-13 19:14:17 -040024 const conversation = Conversation.from(props.accountId, conversationQuery.data)
25 setConversation(conversation)
26 }
27 }, [conversationQuery.data])
28
29 useEffect(() => {
idillonea465602022-09-13 19:58:51 -040030 if (messagesQuery.isSuccess) {
idillon08f77172022-09-13 19:14:17 -040031 const sortedMessages = sortMessages(messagesQuery.data)
32 setMessages(sortedMessages)
33 }
34 }, [messagesQuery.data])
35
36 useEffect(() => {
idillonea465602022-09-13 19:58:51 -040037 setIsLoading(conversationQuery.isLoading || messagesQuery.isLoading)
idillon08f77172022-09-13 19:14:17 -040038 }, [conversationQuery.isLoading, messagesQuery.isLoading])
39
40 useEffect(() => {
41 setError(conversationQuery.isError || messagesQuery.isError)
42 }, [conversationQuery.isError, messagesQuery.isError])
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040043
idillonea465602022-09-13 19:58:51 -040044 const sendMessage = useCallback(
45 (message) => sendMessageMutation.mutate(message),
46 [sendMessageMutation]
47 )
48
Adrien Béraudabba2e52021-04-24 21:39:56 -040049 useEffect(() => {
idillon08f77172022-09-13 19:14:17 -040050 if (!conversation)
Adrien Béraudabba2e52021-04-24 21:39:56 -040051 return
idillon08f77172022-09-13 19:14:17 -040052 console.log(`io set conversation ${props.conversationId} `+ socket)
Adrien Béraudabba2e52021-04-24 21:39:56 -040053 if (socket)
idillon08f77172022-09-13 19:14:17 -040054 socket.emit('conversation', { accountId: props.accountId, conversationId: props.conversationId })
Adrien Béraudabba2e52021-04-24 21:39:56 -040055 socket.off('newMessage')
56 socket.on('newMessage', (data) => {
57 console.log("newMessage")
idillon322e4ac2022-09-14 12:48:43 -040058 setMessages(
59 (messages) => addMessage(messages, data)
60 )
Adrien Béraudabba2e52021-04-24 21:39:56 -040061 })
idillon322e4ac2022-09-14 12:48:43 -040062 }, [socket, setMessages])
Adrien Béraudabba2e52021-04-24 21:39:56 -040063
idillonea465602022-09-13 19:58:51 -040064 if (isLoading) {
Adrien Béraud5e9e19b2021-04-22 01:38:53 -040065 return <LoadingPage />
idillon08f77172022-09-13 19:14:17 -040066 } else if (error) {
67 return <div>Error loading {props.conversationId}</div>
Adrien Béraud5e9e19b2021-04-22 01:38:53 -040068 }
idillonbef18a52022-09-01 01:51:40 -040069
70 return (
71 <Stack
72 flexGrow={1}
73 height="100%"
74 >
75 <Stack direction="row" flexGrow={0}>
76 <Box style={{ margin: 16, flexShrink: 0 }}>
idillon08f77172022-09-13 19:14:17 -040077 <ConversationAvatar displayName={conversation?.getDisplayNameNoFallback()} />
idillonbef18a52022-09-01 01:51:40 -040078 </Box>
79 <Box style={{ flex: "1 1 auto", overflow: 'hidden' }}>
idillon08f77172022-09-13 19:14:17 -040080 <Typography className="title" variant="h6">{conversation?.getDisplayName()}</Typography>
81 <Typography className="subtitle" variant="subtitle1" >{props.conversationId}</Typography>
idillonbef18a52022-09-01 01:51:40 -040082 </Box>
83 </Stack>
idillonaedab942022-09-01 14:29:43 -040084 <Stack flexGrow={1} overflow="auto" direction="column-reverse">
idillonbef18a52022-09-01 01:51:40 -040085 <MessageList
idillon08f77172022-09-13 19:14:17 -040086 messages={messages}
idillonbef18a52022-09-01 01:51:40 -040087 />
88 </Stack>
89 <Stack flexGrow={0}>
90 <SendMessageForm onSend={sendMessage} />
91 </Stack>
92 </Stack>
93 )
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040094}
95
idillon08f77172022-09-13 19:14:17 -040096const addMessage = (sortedMessages, message) => {
97 if (sortedMessages.length === 0) {
98 return [message]
99 } else if (message.id === sortedMessages[sortedMessages.length - 1].linearizedParent) {
100 return [...sortedMessages, message]
101 } else if (message.linearizedParent === sortedMessages[0].id) {
102 return [message, ...sortedMessages]
103 } else {
104 console.log("Can't insert message " + message.id)
105 }
106}
107
108const sortMessages = (messages) => {
109 let sortedMessages = []
110 messages.forEach(message => sortedMessages = addMessage(sortedMessages, message))
111 return sortedMessages
112}
113
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400114export default ConversationView