robosats/frontend/src/components/Chat.js

169 lines
6.4 KiB
JavaScript
Raw Normal View History

import React, { Component } from 'react';
2022-03-10 21:35:16 +00:00
import {Button, Badge, TextField, Grid, Container, Card, CardHeader, Paper, Avatar, FormHelperText, Typography} from "@mui/material";
import ReconnectingWebSocket from 'reconnecting-websocket';
export default class Chat extends Component {
constructor(props) {
super(props);
}
state = {
messages: [],
value:'',
2022-03-10 21:35:16 +00:00
connected: false,
peer_connected: false,
};
2022-03-10 21:35:16 +00:00
rws = new ReconnectingWebSocket('ws://' + window.location.host + '/ws/chat/' + this.props.orderId + '/');
componentDidMount() {
2022-03-10 21:35:16 +00:00
this.rws.addEventListener('open', () => {
console.log('Connected!');
this.setState({connected: true});
this.rws.send(JSON.stringify({
type: "message",
message: 'just-connected',
nick: this.props.ur_nick,
}));
});
this.rws.addEventListener('message', (message) => {
const dataFromServer = JSON.parse(message.data);
console.log('Got reply!', dataFromServer.type);
2022-03-10 21:35:16 +00:00
if (dataFromServer){
if (dataFromServer.message != 'just-connected' & dataFromServer.message != 'peer-disconnected'){
this.setState((state) =>
({
messages: [...state.messages,
{
msg: dataFromServer.message,
userNick: dataFromServer.user_nick,
}],
})
)
}
this.setState({peer_connected: dataFromServer.peer_connected})
}
2022-03-10 21:35:16 +00:00
});
2022-03-10 21:35:16 +00:00
this.rws.addEventListener('close', () => {
console.log('Socket is closed. Reconnect will be attempted');
this.setState({connected: false});
});
this.rws.addEventListener('error', () => {
console.error('Socket encountered error: Closing socket');
});
}
componentDidUpdate() {
this.scrollToBottom();
}
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
onButtonClicked = (e) => {
2022-03-02 13:12:27 +00:00
if(this.state.value!=''){
2022-03-10 21:35:16 +00:00
this.rws.send(JSON.stringify({
2022-03-02 13:12:27 +00:00
type: "message",
message: this.state.value,
nick: this.props.ur_nick,
}));
this.state.value = ''
}
e.preventDefault();
}
render() {
return (
<Container component="main" maxWidth="xs">
2022-03-10 21:35:16 +00:00
<Paper elevation={1} style={{ height: 300, maxHeight: 300, overflow: 'auto', backgroundColor: '#F7F7F7' }}>
<Grid container xs={12} spacing={0.5}>
2022-03-10 22:41:58 +00:00
<Grid item xs={0.3}/>
<Grid item xs={5.5}>
2022-03-10 21:35:16 +00:00
<Paper elevation={1} style={this.state.connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
<Typography variant='caption' >
You: {this.state.connected ? 'connected': 'disconnected'}
</Typography>
</Paper>
</Grid>
2022-03-10 22:41:58 +00:00
<Grid item xs={0.4}/>
<Grid item xs={5.5}>
2022-03-10 21:35:16 +00:00
<Paper elevation={1} style={this.state.peer_connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
<Typography variant='caption'>
Peer: {this.state.peer_connected ? 'connected': 'disconnected'}
</Typography>
</Paper>
</Grid>
2022-03-10 22:41:58 +00:00
<Grid item xs={0.3}/>
2022-03-10 21:35:16 +00:00
</Grid>
{this.state.messages.map(message => <>
<Card elevation={5} align="left" >
{/* If message sender is not our nick, gray color, if it is our nick, green color */}
{message.userNick == this.props.ur_nick ?
<CardHeader
avatar={
2022-03-10 21:35:16 +00:00
<Badge variant="dot" overlap="circular" badgeContent="" color={this.state.connected ? "success" : "error"}>
<Avatar className="flippedSmallAvatar"
alt={message.userNick}
src={window.location.origin +'/static/assets/avatars/' + message.userNick + '.png'}
/>
</Badge>
}
style={{backgroundColor: '#e8ffe6'}}
title={message.userNick}
subheader={message.msg}
subheaderTypographyProps={{sx: {wordWrap: "break-word", width: 200}}}
/>
:
<CardHeader
avatar={
2022-03-10 21:35:16 +00:00
<Badge variant="dot" overlap="circular" badgeContent="" color={this.state.peer_connected ? "success" : "error"}>
<Avatar className="flippedSmallAvatar"
alt={message.userNick}
src={window.location.origin +'/static/assets/avatars/' + message.userNick + '.png'}
/>
</Badge>
}
style={{backgroundColor: '#fcfcfc'}}
title={message.userNick}
subheader={message.msg}
subheaderTypographyProps={{sx: {wordWrap: "break-word", width: 200}}}
/>}
</Card>
</>)}
<div style={{ float:"left", clear: "both" }} ref={(el) => { this.messagesEnd = el; }}></div>
</Paper>
<form noValidate onSubmit={this.onButtonClicked}>
<Grid containter alignItems="stretch" style={{ display: "flex" }}>
2022-03-10 21:35:16 +00:00
<Grid item alignItems="stretch" style={{ display: "flex"}}>
<TextField
label="Type a message"
2022-03-10 21:35:16 +00:00
variant="standard"
size="small"
2022-03-10 21:35:16 +00:00
helperText={this.state.connected ? null : "Connecting..."}
value={this.state.value}
onChange={e => {
this.setState({ value: e.target.value });
this.value = this.state.value;
}}
2022-03-10 21:35:16 +00:00
sx={{width: 214}}
/>
</Grid>
<Grid item alignItems="stretch" style={{ display: "flex" }}>
2022-03-10 21:35:16 +00:00
<Button disabled={!this.state.connected} type="submit" variant="contained" color="primary" > Send </Button>
</Grid>
</Grid>
</form>
2022-03-02 12:57:52 +00:00
<FormHelperText>
The chat has no memory: if you leave, messages are lost. <a target="_blank" href="https://github.com/Reckless-Satoshi/robosats/blob/main/docs/sensitive-data-PGP-guide.md/"> Learn easy PGP encryption.</a>
2022-03-02 12:57:52 +00:00
</FormHelperText>
</Container>
)
}
}