use React Query to fetch messages
Change-Id: I85d0700efcc947462943ed0379498902b73950b3
diff --git a/client/src/components/ConversationView.js b/client/src/components/ConversationView.js
index dfba0d1..964d5bf 100644
--- a/client/src/components/ConversationView.js
+++ b/client/src/components/ConversationView.js
@@ -7,35 +7,40 @@
import io from "socket.io-client";
import { Box, Stack, Typography } from '@mui/material';
import ConversationAvatar from './ConversationAvatar';
+import { useConversationQuery, useMessagesQuery } from '../services/conversation';
const ConversationView = props => {
const [loadingMessages, setLoadingMessages] = useState(false)
- const [socket, setSocket] = useState(undefined)
- const [state, setState] = useState({
- loaded: false,
- error: false,
- conversation: undefined
- })
+ const [socket, setSocket] = useState()
+ const [conversation, setConversation] = useState()
+ const [messages, setMessages] = useState([])
+ const [loaded, setLoaded] = useState(true)
+ const [error, setError] = useState(false)
+
+ const conversationQuery = useConversationQuery(props.accountId, props.conversationId)
+ const messagesQuery = useMessagesQuery(props.accountId, props.conversationId)
useEffect(() => {
- const controller = new AbortController()
- authManager.fetch(`/api/accounts/${props.accountId}/conversations/${props.conversationId}`, {signal: controller.signal})
- .then(res => res.json())
- .then(result => {
- console.log(result)
- setState({
- loaded: true,
- conversation: Conversation.from(props.accountId, result)
- })
- }, error => {
- console.log(`get error ${error}`)
- setState({
- loaded: true,
- error: true
- })
- })
- // return () => controller.abort() // crash on React18
- }, [props.accountId, props.conversationId])
+ if (conversationQuery.data) {
+ const conversation = Conversation.from(props.accountId, conversationQuery.data)
+ setConversation(conversation)
+ }
+ }, [conversationQuery.data])
+
+ useEffect(() => {
+ if (messagesQuery.data) {
+ const sortedMessages = sortMessages(messagesQuery.data)
+ setMessages(sortedMessages)
+ }
+ }, [messagesQuery.data])
+
+ useEffect(() => {
+ setLoaded(!(conversationQuery.isLoading || messagesQuery.isLoading))
+ }, [conversationQuery.isLoading, messagesQuery.isLoading])
+
+ useEffect(() => {
+ setError(conversationQuery.isError || messagesQuery.isError)
+ }, [conversationQuery.isError, messagesQuery.isError])
useEffect(() => {
console.log("io.connect")
@@ -49,41 +54,18 @@
}, [])
useEffect(() => {
- if (!state.conversation)
+ if (!conversation)
return
- console.log(`io set conversation ${state.conversation.getId()} `+ socket)
+ console.log(`io set conversation ${props.conversationId} `+ socket)
if (socket)
- socket.emit('conversation', { accountId: state.conversation.getAccountId(), conversationId: state.conversation.getId() })
+ socket.emit('conversation', { accountId: props.accountId, conversationId: props.conversationId })
socket.off('newMessage')
socket.on('newMessage', (data) => {
console.log("newMessage")
console.log(data)
- setState(state => {
- if (state.conversation)
- state.conversation.addMessage(data)
- return {...state}
- })
+ setMessages(addMessage(messages, data))
})
- }, [state.conversation ? state.conversation.getId() : "", socket])
-
- useEffect(() => {
- if (!loadingMessages || !state.conversation)
- return
- console.log(`Load more messages`)
- const controller = new AbortController()
- authManager.fetch(`/api/accounts/${state.conversation.getAccountId()}/conversations/${state.conversation.getId()}/messages`, {signal: controller.signal})
- .then(res => res.json())
- .then(messages => {
- console.log(messages)
- setLoadingMessages(false)
- setState(state => {
- if (state.conversation)
- state.conversation.addLoadedMessages(messages)
- return {...state}
- })
- }).catch(e => console.log(e))
- // return () => controller.abort() // crash on React18
- }, [state, loadingMessages])
+ }, [conversation ? props.conversationId : "", socket])
const sendMessage = (message) => {
authManager.fetch(`/api/accounts/${props.accountId}/conversations/${props.conversationId}`, {
@@ -96,10 +78,10 @@
})
}
- if (state.loaded === false) {
+ if (!loaded) {
return <LoadingPage />
- } else if (state.error === true) {
- return <div>Error loding {props.conversationId}</div>
+ } else if (error) {
+ return <div>Error loading {props.conversationId}</div>
}
return (
@@ -109,19 +91,19 @@
>
<Stack direction="row" flexGrow={0}>
<Box style={{ margin: 16, flexShrink: 0 }}>
- <ConversationAvatar displayName={state.conversation.getDisplayNameNoFallback()} />
+ <ConversationAvatar displayName={conversation?.getDisplayNameNoFallback()} />
</Box>
<Box style={{ flex: "1 1 auto", overflow: 'hidden' }}>
- <Typography className="title" variant="h6">{state.conversation.getDisplayName()}</Typography>
- <Typography className="subtitle" variant="subtitle1" >{state.conversation.getId()}</Typography>
+ <Typography className="title" variant="h6">{conversation?.getDisplayName()}</Typography>
+ <Typography className="subtitle" variant="subtitle1" >{props.conversationId}</Typography>
</Box>
</Stack>
<Stack flexGrow={1} overflow="auto" direction="column-reverse">
<MessageList
- conversationId={state.conversation.getId()}
+ conversationId={props.conversationId}
loading={loadingMessages}
loadMore={() => setLoadingMessages(true)}
- messages={state.conversation.getMessages()}
+ messages={messages}
/>
</Stack>
<Stack flexGrow={0}>
@@ -131,4 +113,22 @@
)
}
+const addMessage = (sortedMessages, message) => {
+ if (sortedMessages.length === 0) {
+ return [message]
+ } else if (message.id === sortedMessages[sortedMessages.length - 1].linearizedParent) {
+ return [...sortedMessages, message]
+ } else if (message.linearizedParent === sortedMessages[0].id) {
+ return [message, ...sortedMessages]
+ } else {
+ console.log("Can't insert message " + message.id)
+ }
+}
+
+const sortMessages = (messages) => {
+ let sortedMessages = []
+ messages.forEach(message => sortedMessages = addMessage(sortedMessages, message))
+ return sortedMessages
+}
+
export default ConversationView
\ No newline at end of file
diff --git a/client/src/components/MessageList.js b/client/src/components/MessageList.js
index 3f16e46..f6da60c 100644
--- a/client/src/components/MessageList.js
+++ b/client/src/components/MessageList.js
@@ -1,5 +1,5 @@
import dayjs from "dayjs"
-import React, { useEffect } from 'react'
+import React, { useEffect, useMemo } from 'react'
import dayOfYear from 'dayjs/plugin/dayOfYear'
import isBetween from 'dayjs/plugin/isBetween'
import { Stack } from "@mui/system"
@@ -9,7 +9,10 @@
dayjs.extend(isBetween)
export default function MessageList(props) {
- const messagesComponents = buildMessagesList(props.messages)
+ const messagesComponents = useMemo(
+ () => buildMessagesList(props.messages),
+ [props.messages]
+ )
useEffect(() => {
if (!props.loading)