diff --git a/client/src/Board.css b/client/src/Board.css index 5d4c628..289e58e 100755 --- a/client/src/Board.css +++ b/client/src/Board.css @@ -108,6 +108,30 @@ scroll-behavior: smooth; } +#ChatList .MuiListItem-gutters { + padding: 2px 0 2px 0; +} + +#ChatList .MuiTypography-body1 { + font-size: 0.8rem; +} + +#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: 0px; +} + .Players { padding: 0.5em; user-select: none; @@ -123,6 +147,10 @@ cursor: pointer; } +.Players .PlayerSelector[data-selected=true] { + background-color: rgba(255,255,255,0.5); +} + .Players .PlayerToggle { min-width: 5em; display: inline-flex; @@ -229,13 +257,13 @@ button { user-select: none; } -.Message div { - display: inline-flex; +.Message .PlayerColor { + width: 1em; + height: 1em; } -.Message .PlayerColor { - position: relative; - top: -0.25em; +.Message div { + display: inline-flex; } .PlayerName { diff --git a/client/src/Board.js b/client/src/Board.js index 750c15b..614e732 100755 --- a/client/src/Board.js +++ b/client/src/Board.js @@ -6,12 +6,11 @@ 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 ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemText from '@material-ui/core/ListItemText'; -import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import { makeStyles } from '@material-ui/core/styles'; import { deepOrange, lightBlue, red, grey } from '@material-ui/core/colors'; import Avatar from '@material-ui/core/Avatar'; -import Switch from '@material-ui/core/Switch'; import Moment from 'react-moment'; //import moment from 'moment'; @@ -72,16 +71,9 @@ const useStyles = makeStyles((theme) => ({ })); const PlayerColor = ({ color }) => { - const colors = getPlayerColors(color) + const classes = useStyles(); return ( -
-
{color}
-
+ ); }; @@ -293,8 +285,6 @@ const Chat = ({ board, promoteGameState }) => { } }; - const classes = useStyles(); - useEffect(() => { const chatList = document.getElementById("ChatList"), currentTop = Math.round(chatList.scrollTop); @@ -318,13 +308,10 @@ const Chat = ({ board, promoteGameState }) => { //const timeDelta = game.timestamp - Date.now(); const messages = board.game.chat.map((item, index) => { /* If the date is in the future, set it to now */ - item.date = item.date > Date.now() ? Date.now() : item.date; return ( - - - {item.from} - - )} /> + + + Date.now() ? Date.now() : item.date} interval={1000}/>)} /> ); }); @@ -436,8 +423,6 @@ const Players = ({ board }) => { board.setSelected(board.game.color === key ? "" : key); } - const classes = useStyles(); - const players = []; for (let color in board.game.players) { const item = board.game.players[color]; @@ -445,35 +430,22 @@ const Players = ({ board }) => { continue; } const name = getPlayerName(board.game.sessions, color), - selectable = item.status === 'Not active' || board.game.color === color; - item.lastActive = item.lastActive > Date.now() ? Date.now() : item.lastActive; - let toggleText; - if (selectable) { - if (board.game.state !== 'lobby') { - toggleText = 'Exit to lobby.'; - } else { - toggleText = item.status === 'Not active' - ? Play as {board.game.color ? ' instead' : ''}. - : Stop playing as .; - } - } + selectable = board.game.state === 'lobby' && (item.status === 'Not active' || board.game.color === color); + let toggleText = name ? name : "Available"; players.push(( { selectable && toggleSelected(color) }} className="PlayerSelector" key={`player-${color}`}> - - {color} - - - { item.status + ' ' } - { item.status !== 'Not active' && } - )} /> - { selectable && -
- - {toggleText} -
+ data-selectable={selectable} + data-selected={board.game.color === color} + className="PlayerSelector" + key={`player-${color}`}> + { selectable && toggleSelected(color) }} color={color}/> + { selectable && toggleSelected(color) }}primary={toggleText} secondary={( + <> + { item.status + ' ' } + { item.status !== 'Not active' && Date.now() ? Date.now() : item.lastActive}/>} + )} /> + { board.game.state !== 'lobby' && board.game.color === color && + }
)); diff --git a/server/routes/games.js b/server/routes/games.js index a917d5d..17ac1e9 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -501,6 +501,7 @@ const getActiveCount = (game) => { const sendGame = async (req, res, game, error) => { const active = getActiveCount(game); + /* Enforce game limit of >= 2 players */ if (active < 2 && game.state != 'lobby' && game.state != 'invalid') { let message = "Insufficient players in game. Setting back to lobby." game.chat.push({ date: Date.now(), message: message }); @@ -509,6 +510,7 @@ const sendGame = async (req, res, game, error) => { } game.active = active; + /* Update the session lastActive clock */ let session; if (req.session) { session = getSession(game, req.session); @@ -522,6 +524,15 @@ const sendGame = async (req, res, game, error) => { }; } + /* Ensure chat messages have a unique date: stamp as it is used as the index key */ + let lastTime = 0; + if (game.chat) game.chat.forEach((message) => { + if (message.date <= lastTime) { + message.date = lastTime + 1; + } + lastTime = message.date; + }); + /* Shallow copy game, filling its sessions with a shallow copy of sessions so we can then * delete the player field from them */ const reducedGame = Object.assign({}, game, { sessions: {} }),