Skip to content

Instantly share code, notes, and snippets.

@kvnam
Created May 22, 2019 02:57
Show Gist options
  • Save kvnam/3896ca1dd4e5b4cd7e4ef6a71555612c to your computer and use it in GitHub Desktop.
Save kvnam/3896ca1dd4e5b4cd7e4ef6a71555612c to your computer and use it in GitHub Desktop.
ReactChat-ChatComponent
import React, { useState, useEffect } from "react";
import Grid from "@material-ui/core/Grid";
import {
createStyles,
Theme,
WithStyles,
withStyles,
Typography,
Button
} from "@material-ui/core";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import TextField from '@material-ui/core/TextField';
import Message from "../components/Room/Chat/Message";
import { getUserService } from "../services/Users";
import { getWSService } from "../services/WebSocket";
import "./chatroom.scss";
interface User {
username: string;
room: string;
joined? : Date
last_active? : Date
}
interface Message {
type: string;
msg: any;
sent: Date | string;
user: User;
}
const styles = (theme: Theme) =>
createStyles({
...
});
export interface Props extends WithStyles<typeof styles> {
user: User;
}
function ChatRoom(props: Props) {
const { classes } = props;
//Handle users
const [users, setUsers] = useState<User[]>(
getUserService().getUserList(props.user.room)
);
//Handle the messages in the chat window
const [messageList, updateMessageList] = useState<Message[]>([]);
const [fields, setFields] = useState({
userService: getUserService(),
userAdded: false
});
//Handle message being sent by the user
const [currentMessage, setCurrentMessage] = useState<Message>({
type: "",
msg: "",
user: {
username: "",
room: ""
},
sent: ""
});
//Add message to the list
const addMessageToList = (message: Message) => {
let updatedList = [...messageList];
updatedList.push(message);
updateMessageList(updatedList);
}
//Handler to receive chat messages from the WebSocket service
const chatMessageHandler = (message: Message) => {
if (message.type === "all") {
addMessageToList(message);
}
};
//Handler to receive user list messages from the WebSocket service
const userListMessageHandler = (message: Message) => {
if(message.type === "userlist"){
const userList = message.msg;
const updatedUserList = userList.map((msgObj: User) => {
const { joined, username, room, last_active, } = msgObj;
return {
joined,
username,
room,
last_active,
};
});
setUsers(updatedUserList);
}
}
//Handle input change
const onInputChange = (event: React.FormEvent<EventTarget>) => {
let eventTarget = event.target as HTMLInputElement;
let updatedMsg = { ...currentMessage };
updatedMsg.msg = eventTarget.value;
setCurrentMessage(updatedMsg);
}
// Handle sending of a message to chat
const onSendMessage = () => {
let updatedMsg = { ...currentMessage };
updatedMsg.type = "all";
updatedMsg.sent = new Date();
updatedMsg.user = {
username: props.user.username,
room: props.user.room
};
setCurrentMessage(updatedMsg);
getWSService().sendMessage("test", updatedMsg);
//Add this message to chat
addMessageToList(updatedMsg);
//Reset chat box
updatedMsg = {
type: "",
msg: "",
user: {
username: "",
room: ""
},
sent: ""
};
setCurrentMessage(updatedMsg);
}
//Handle the change in user service status
useEffect(() => {
if(!fields.userAdded && !users.find(usrVal => usrVal.username === props.user.username)){
const userAdd = fields.userService.addUser({
username: props.user.username,
room: props.user.room
});
setFields({...fields, userAdded: userAdd});
}
}, [fields.userService]);
//Handle change in user added status
useEffect(() => {
if (
fields.userAdded &&
users &&
!users.find(usrVal => usrVal.username === props.user.username)
) {
const userList = [...users];
userList.push(props.user);
setUsers(userList);
//Add message listener for this chat room
getWSService().addMessageListener(
props.user.room,
"all",
chatMessageHandler
);
//Add user list listener
getWSService().addMessageListener(
props.user.room,
"userlist",
userListMessageHandler
);
}
}, [fields.userAdded]);
if(fields.userAdded){
return (
<Grid
container
alignItems="flex-start"
justify="flex-start"
className={classes.roomContainer}
>
<Grid item xs={12} md={8}>
<Grid
container
alignItems="flex-start"
justify="flex-start"
direction="column"
>
<Grid item xs={12} md={12} className={classes.root}>
<div className={classes.chatWindow}>
<Typography className={classes.greeting} variant="h5">
Welcome to room {props.user.room}!
</Typography>
{messageList.map((message, index) => (
<Message key={index} message={message} />
))}
</div>
</Grid>
<Grid item xs={12} md={12} className={classes.root}>
<Grid container direction="row" alignItems="flex-start">
<Grid item xs={9} md={11}>
<div className={classes.sendChatBox}>
<TextField id="standard-multiline-flexible" label="Enter your message here"
multiline rowsMax="4" fullWidth value={currentMessage.msg}
onChange={(event) => onInputChange(event)}
className="msg-box" margin="normal"
/>
</div>
</Grid>
<Grid item xs={3} md={1}>
<div>
<Button onClick={onSendMessage} className={classes.sendBtn} variant="contained"
type="button" color="secondary">Send</Button>
</div>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={4}>
<div className={classes.members}>
<Typography className={classes.greeting} variant="h5">
Members
</Typography>
<List>
{users.map((user, index) => {
return (
<ListItem key={user.username + index} className="user-name">
<ListItemText primary={user.username} />
</ListItem>
);
})}
</List>
</div>
</Grid>
</Grid>
);
}
return <div className="loading">Adding you to the room, please wait..</div>;
}
export default withStyles(styles)(ChatRoom);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment