Skip to content

20250626 refresh #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion chatter/src/components/Messages/components/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function Footer({ sendMessage, onChangeMessage, message }) {
placeholder="Write a message..."
id="user-message-input"
onChange={onChangeMessage}
value={message}
/>
<div className="messages__footer__actions">
<i className="far fa-smile" />
Expand All @@ -25,4 +26,4 @@ export default function Footer({ sendMessage, onChangeMessage, message }) {
</div>
</div>
);
}
}
90 changes: 80 additions & 10 deletions chatter/src/components/Messages/components/Messages.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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) => (
<Message key={index} message={item} nextMessage={messages[index + 1]} botTyping={displayTyping} />
));

const displayErrorText = () => displayError.isVisible && <p>{displayError.message}</p>;

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 (
<div className="messages">
<Header />
<div className="messages__list" id="message-list">
{ displayMessages() }
{ displayTyping && <TypingMessage /> }
{ displayErrorText() }
<div ref={refVal} />
</div>
<Footer message={message} sendMessage={sendMessage} onChangeMessage={onChangeMessage} />
{!displayError.isVisible && (
<Footer message={messageText} sendMessage={sendMessage} onChangeMessage={(e) => setMessageText(e.target.value)} />
)}
</div>
);
}
};

export default Messages;
export default Messages;
9 changes: 5 additions & 4 deletions chatter/src/layouts/CoreLayout/components/IconBackground.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ function getRandomIcon() {
function IconRow({ numberOfIcons }) {
return (
<div className="icon-background__row">
{[...new Array(numberOfIcons)].map(() => {
{[...new Array(numberOfIcons)].map((item, index) => {
const icon = getRandomIcon();

return (
<i
key={index}
aria-hidden="true"
className={icon.name}
style={{
Expand All @@ -43,9 +44,9 @@ export default function IconBackground() {

return (
<div className="icon-background">
{[...new Array(numberOfRows)].map(() => (
<IconRow numberOfIcons={numberOfElsPerRow} />
{[...new Array(numberOfRows)].map((item, index) => (
<IconRow key={index} numberOfIcons={numberOfElsPerRow} />
))}
</div>
)
}
}
Loading