
Fixed some more WebSocket timeouts Changed Resource to support a label=true mode which puts a bubble lable instead of creating a stack Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
143 lines
4.5 KiB
JavaScript
143 lines
4.5 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import "./Chat.css";
|
|
import PlayerColor from './PlayerColor.js';
|
|
import Paper from '@material-ui/core/Paper';
|
|
import List from '@material-ui/core/List';
|
|
import ListItem from '@material-ui/core/ListItem';
|
|
import ListItemText from '@material-ui/core/ListItemText';
|
|
import Moment from 'react-moment';
|
|
import TextField from '@material-ui/core/TextField';
|
|
|
|
import Resource from './Resource.js';
|
|
import Dice from './Dice.js';
|
|
|
|
const Chat = ({ table }) => {
|
|
const [lastTop, setLastTop] = useState(0),
|
|
[autoScroll, setAutoscroll] = useState(true),
|
|
[latest, setLatest] = useState(''),
|
|
[scrollTime, setScrollTime] = useState(0);
|
|
|
|
const chatInput = (event) => {
|
|
};
|
|
|
|
const chatKeyPress = (event) => {
|
|
if (event.key === "Enter") {
|
|
if (!autoScroll) {
|
|
setAutoscroll(true);
|
|
}
|
|
|
|
table.sendChat(event.target.value);
|
|
|
|
event.target.value = "";
|
|
}
|
|
};
|
|
|
|
const chatScroll = (event) => {
|
|
const chatList = event.target,
|
|
fromBottom = Math.round(Math.abs((chatList.scrollHeight - chatList.offsetHeight) - chatList.scrollTop));
|
|
|
|
/* If scroll is within 20 pixels of the bottom, turn on auto-scroll */
|
|
const shouldAutoscroll = (fromBottom < 20);
|
|
|
|
if (shouldAutoscroll !== autoScroll) {
|
|
setAutoscroll(shouldAutoscroll);
|
|
}
|
|
|
|
/* If the list should not auto scroll, then cache the current
|
|
* top of the list and record when we did this so we honor
|
|
* the auto-scroll for at least 500ms */
|
|
if (!shouldAutoscroll) {
|
|
const target = Math.round(chatList.scrollTop);
|
|
if (target !== lastTop) {
|
|
setLastTop(target);
|
|
setScrollTime(Date.now());
|
|
}
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const chatList = document.getElementById("ChatList"),
|
|
currentTop = Math.round(chatList.scrollTop);
|
|
|
|
if (autoScroll) {
|
|
/* Auto-scroll to the bottom of the chat window */
|
|
const target = Math.round(chatList.scrollHeight - chatList.offsetHeight);
|
|
if (currentTop !== target) {
|
|
chatList.scrollTop = target;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Maintain current position in scrolled view if the user hasn't
|
|
* been scrolling in the past 0.5s */
|
|
if ((Date.now() - scrollTime) > 500 && currentTop !== lastTop) {
|
|
chatList.scrollTop = lastTop;
|
|
}
|
|
});
|
|
|
|
//const timeDelta = game.timestamp - Date.now();
|
|
if (!table.game) {
|
|
console.log("Why no game?");
|
|
}
|
|
|
|
const messages = table.game && table.game.chat.map((item, index) => {
|
|
let message;
|
|
/* If the date is in the future, set it to now */
|
|
const dice = item.message.match(/^(.*rolled )([1-6])(, ([1-6]))?(.*)$/);
|
|
if (dice) {
|
|
if (dice[4]) {
|
|
message = <>{dice[1]}<Dice pips={dice[2]}/>, <Dice pips={dice[4]}/>{dice[5]}</>;
|
|
} else {
|
|
message = <>{dice[1]}<Dice pips={dice[2]}/>{dice[5]}</>;
|
|
}
|
|
} else {
|
|
let start = item.message;
|
|
while (start) {
|
|
const resource = start.match(/^(.*)(([0-9]+) (wood|sheep|wheat|stone|brick),?)(.*)$/);
|
|
if (resource) {
|
|
const count = resource[3] ? parseInt(resource[3]) : 1;
|
|
message = <><Resource label={true} count={count} type={resource[4]}/>{resource[5]}{message}</>;
|
|
start = resource[1];
|
|
} else {
|
|
message = <>{start}{message}</>;
|
|
start = '';
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<ListItem key={`msg-${item.date}`} className={item.color ? '' : 'System'}>
|
|
{ item.color &&
|
|
<PlayerColor color={item.color}/>
|
|
}
|
|
<ListItemText primary={message}
|
|
secondary={item.color && <Moment fromNow date={item.date > Date.now() ?
|
|
Date.now() : item.date} interval={1000}/>} />
|
|
</ListItem>
|
|
);
|
|
});
|
|
|
|
if (table.game && table.game.chat &&
|
|
table.game.chat.length &&
|
|
table.game.chat[table.game.chat.length - 1].date !== latest) {
|
|
setLatest(table.game.chat[table.game.chat.length - 1].date);
|
|
setAutoscroll(true);
|
|
}
|
|
|
|
const name = table.game ? table.game.name : "Why no game?";
|
|
const elapsed = table.game ? (table.game.timestamp - table.game.startTime) : undefined;
|
|
return (
|
|
<Paper className="Chat">
|
|
<List className="ChatList" id="ChatList" onScroll={chatScroll}>
|
|
{ messages }
|
|
</List>
|
|
<TextField className="ChatInput"
|
|
disabled={!name}
|
|
onChange={chatInput}
|
|
onKeyPress={chatKeyPress}
|
|
label={elapsed && <Moment tz={"Etc/GMT"} format="h:mm:ss" durationFromNow interval={1000} date={table.game.startTime}></Moment>} variant="outlined"/>
|
|
</Paper>
|
|
);
|
|
}
|
|
|
|
export default Chat; |