Add Resource replacement in Chat
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
7439eaf21f
commit
44cd877c4e
81
client/src/Chat.css
Normal file
81
client/src/Chat.css
Normal file
@ -0,0 +1,81 @@
|
||||
|
||||
.Chat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.ChatList {
|
||||
/* for Firefox */
|
||||
min-height: 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
overflow: auto;
|
||||
scroll-behavior: smooth;
|
||||
align-items: flex-start;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.ChatList .System {
|
||||
background-color: #f0f0f0;
|
||||
transform: scale(0.8);
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
.ChatInput {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ChatList .MuiListItem-gutters {
|
||||
padding: 2px 0 2px 0;
|
||||
}
|
||||
|
||||
.ChatList .MuiTypography-body1 {
|
||||
font-size: 0.8rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ChatList .System .MuiTypography-body1 {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.ChatList .MuiTypography-body2 {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.ChatList .MuiListItemText-multiline {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding: 4px 0px 4px 4px;
|
||||
}
|
||||
|
||||
.ChatList .PlayerColor {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
margin-top: 6px;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.ChatList .Resource {
|
||||
display: inline-flex;
|
||||
width: 3em;
|
||||
height: 4.3em;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ChatList .Stack {
|
||||
margin-left: 0;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.ChatList .Stack > *:not(:first-child) {
|
||||
margin-left: 0;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.ChatList .Dice {
|
||||
margin-left: 0.25em;
|
||||
}
|
143
client/src/Chat.js
Normal file
143
client/src/Chat.js
Normal file
@ -0,0 +1,143 @@
|
||||
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 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;
|
@ -264,66 +264,6 @@
|
||||
* Chat
|
||||
* Action
|
||||
*/
|
||||
|
||||
.Chat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.ChatList {
|
||||
/* for Firefox */
|
||||
min-height: 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
overflow: auto;
|
||||
scroll-behavior: smooth;
|
||||
align-items: flex-start;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.ChatList .System {
|
||||
background-color: #f0f0f0;
|
||||
transform: scale(0.8);
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
.ChatInput {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ChatList .MuiListItem-gutters {
|
||||
padding: 2px 0 2px 0;
|
||||
}
|
||||
|
||||
.ChatList .MuiTypography-body1 {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.ChatList .System .MuiTypography-body1 {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.ChatList .MuiTypography-body2 {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.ChatList .MuiListItemText-multiline {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding: 4px 0px 4px 4px;
|
||||
}
|
||||
|
||||
.ChatList .PlayerColor {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding: 0;
|
||||
margin-top: 6px;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.Players {
|
||||
flex: 1 0;
|
||||
overflow: hidden;
|
||||
|
@ -1,11 +1,10 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState } from "react";
|
||||
import "./Table.css";
|
||||
import history from "./history.js";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
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 Board from './Board.js';
|
||||
@ -17,6 +16,7 @@ import Resource from './Resource.js';
|
||||
import ViewCard from './ViewCard.js';
|
||||
import Winner from './Winner.js';
|
||||
import ChooseCard from './ChooseCard.js';
|
||||
import Chat from './Chat.js';
|
||||
import { CircularProgress } from "@material-ui/core";
|
||||
import 'moment-timezone';
|
||||
|
||||
@ -119,123 +119,6 @@ const Development = ({table, type, card, onClick}) => {
|
||||
);
|
||||
};
|
||||
|
||||
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 {
|
||||
message = item.message;
|
||||
}
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
const StartButton = ({ table }) => {
|
||||
const startClick = (event) => {
|
||||
table.setGameState("game-order").then((state) => {
|
||||
|
@ -1785,7 +1785,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
game.turn.actions = [];
|
||||
game.turn.limits = {};
|
||||
addChatMessage(game, session,
|
||||
`${session.name} randomly stole ${type} from ${playerNameFromColor(game, value)}.`);
|
||||
`${session.name} randomly stole 1 ${type} from ${playerNameFromColor(game, value)}.`);
|
||||
}
|
||||
debugChat(game, 'After steal');
|
||||
|
||||
@ -2891,9 +2891,7 @@ const createGame = (id) => {
|
||||
setBeginnerGame(game);
|
||||
resetGame(game);
|
||||
|
||||
console.log(`New game created with Beginner's Layout: ${game.id}`);
|
||||
addChatMessage(game, null,
|
||||
`New game created with Beginner's Layout: ${game.id}`);
|
||||
addChatMessage(game, null, `New game created with Beginner's Layout: ${game.id}`);
|
||||
|
||||
games[game.id] = game;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user