diff --git a/chatter/src/components/Messages/components/Footer.js b/chatter/src/components/Messages/components/Footer.js index a0f36e352..fc4ac6ce9 100644 --- a/chatter/src/components/Messages/components/Footer.js +++ b/chatter/src/components/Messages/components/Footer.js @@ -16,6 +16,7 @@ export default function Footer({ sendMessage, onChangeMessage, message }) { placeholder="Write a message..." id="user-message-input" onChange={onChangeMessage} + value={message} />
@@ -25,4 +26,4 @@ export default function Footer({ sendMessage, onChangeMessage, message }) {
); -} +} \ No newline at end of file diff --git a/chatter/src/components/Messages/components/Messages.js b/chatter/src/components/Messages/components/Messages.js index 4d388a8b0..e21d009f4 100644 --- a/chatter/src/components/Messages/components/Messages.js +++ b/chatter/src/components/Messages/components/Messages.js @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React, { useContext, useState, useEffect, useRef } from 'react'; import io from 'socket.io-client'; import useSound from 'use-sound'; import config from '../../../config'; @@ -8,25 +8,95 @@ import Header from './Header'; import Footer from './Footer'; import Message from './Message'; import '../styles/_messages.scss'; +import initialBottyMessage from '../../../common/constants/initialBottyMessage'; -const socket = io( - config.BOT_SERVER_ENDPOINT, - { transports: ['websocket', 'polling', 'flashsocket'] } -); +const socket = io(config.BOT_SERVER_ENDPOINT, { + transports: ['websocket', 'polling', 'flashsocket'] +}); -function Messages() { +const Messages = () => { + const { setLatestMessage } = useContext(LatestMessagesContext); + const [messages] = useState([{ message: initialBottyMessage, user: 'bot' }]); + const [messageText, setMessageText] = useState(''); + const [displayError, setDisplayError] = useState({ isVisible: false, message: '' }); + const [displayTyping, setDisplayTyping] = useState(false); const [playSend] = useSound(config.SEND_AUDIO_URL); const [playReceive] = useSound(config.RECEIVE_AUDIO_URL); - const { setLatestMessage } = useContext(LatestMessagesContext); + const refVal = useRef(null); + + const sendMessage = () => { + const newMessage = { message: messageText, user: 'me' }; + messages.push(newMessage); + socket.emit('user-message', newMessage.message); + setLatestMessage(newMessage.message); + playSend(); + setMessageText(''); + }; + + const handleNewMessage = (newBotMessage) => { + playReceive(); + setLatestMessage(newBotMessage); + messages.push({ message: newBotMessage, user: 'bot' }); + setDisplayTyping(false); + }; + + const handleBotTyping = () => setDisplayTyping(true); + + const scrollToLastMessage = () => { + refVal.current?.scrollIntoView(); + }; + + const displayMessages = () => messages.map((item, index) => ( + + )); + + const displayErrorText = () => displayError.isVisible &&

{displayError.message}

; + + useEffect(() => { + socket.on('bot-message', handleNewMessage); + socket.on('bot-typing', handleBotTyping); + + const errorEvents = ['connect_error', 'disconnect', 'reconnect_error', 'error', 'connect_timeout']; + + socket.on('connect_error', (error) => { + setDisplayError({isVisible: true, message: "There was an error connecting."}) + }); + socket.on('disconnect', (reason) => { + setDisplayError({isVisible: true, message: "There was an error. Disconnected from Botty."}) + }); + socket.on('reconnect_error', (error) => { + setDisplayError({isVisible: true, message: "There was an error reconnecting."}) + }); + socket.on('error', (error) => { + setDisplayError({isVisible: true, message: "There was an error. Please refresh and try again."}) + }); + socket.on('connect_timeout', (timeout) => { + setDisplayError({isVisible: true, message: "There was an error, connection timed out."}) + }); + + scrollToLastMessage(); + + return () => { + socket.off('bot-message', handleNewMessage); + socket.off('bot-typing', handleBotTyping); + errorEvents.forEach(event => socket.off(event)); + }; + }, []); return (
+ { displayMessages() } + { displayTyping && } + { displayErrorText() } +
-
+ {!displayError.isVisible && ( +
setMessageText(e.target.value)} /> + )}
); -} +}; -export default Messages; +export default Messages; \ No newline at end of file diff --git a/chatter/src/layouts/CoreLayout/components/IconBackground.js b/chatter/src/layouts/CoreLayout/components/IconBackground.js index 8caef381c..7b1d8abae 100644 --- a/chatter/src/layouts/CoreLayout/components/IconBackground.js +++ b/chatter/src/layouts/CoreLayout/components/IconBackground.js @@ -16,11 +16,12 @@ function getRandomIcon() { function IconRow({ numberOfIcons }) { return (
- {[...new Array(numberOfIcons)].map(() => { + {[...new Array(numberOfIcons)].map((item, index) => { const icon = getRandomIcon(); return (