From 38c6f4069db96fef0f13189719514a4a94933e4d Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 4 Feb 2022 15:45:59 -0800 Subject: [PATCH] Improved sizing of game UI for phones. Signed-off-by: James Ketrenos --- client/src/Board.css | 1 + client/src/Table.css | 49 ++++++++++++++------- client/src/Table.js | 92 +++++++++++++++++++-------------------- server/routes/games.js | 98 +++++++++++++++--------------------------- 4 files changed, 113 insertions(+), 127 deletions(-) diff --git a/client/src/Board.css b/client/src/Board.css index d74b4c5..39dc7c6 100644 --- a/client/src/Board.css +++ b/client/src/Board.css @@ -4,6 +4,7 @@ position: relative; flex: 1; align-items: stretch; + margin-right: 40vw; } /* Offset 'BorderBox' such that 0,0 is the center diff --git a/client/src/Table.css b/client/src/Table.css index 9adc505..9e3c5ca 100755 --- a/client/src/Table.css +++ b/client/src/Table.css @@ -119,15 +119,16 @@ } .Game { - display: inline-flex; + display: flex; + position: absolute; flex-direction: column; box-sizing: border-box; - width: 40vw; max-height: 100vh; overflow: hidden; max-width: 40vw; z-index: 100; padding: 0.5em; + right: 0px; } .Game > * { @@ -139,48 +140,61 @@ margin-bottom: 0.5em; } -.Game .lobby { +.Game.lobby { + max-width: 100vw; width: 100vw; + position: absolute; } +/* + * Game + * Message + * Players + * Chat + * Action + */ + .Chat { display: flex; flex-direction: column; - flex: 1; + flex-grow: 1; padding: 0.5em; } -.Chat > * { +.ChatList { /* for Firefox */ min-height: 0; -} - -#ChatList { - flex: 1; + flex-grow: 1; + flex-shrink: 1; overflow: auto; scroll-behavior: smooth; align-items: flex-start; } -#ChatList .MuiListItem-gutters { +.ChatInput { + flex-grow: 0; + flex-shrink: 0; +} + +.ChatList .MuiListItem-gutters { padding: 2px 0 2px 0; } -#ChatList .MuiTypography-body1 { +.ChatList .MuiTypography-body1 { font-size: 0.8rem; } -#ChatList .MuiTypography-body2 { +.ChatList .MuiTypography-body2 { font-size: 0.7rem; } -#ChatList .MuiListItemText-multiline { +.ChatList .MuiListItemText-multiline { margin-top: 0; margin-bottom: 0; padding: 4px 0px 4px 4px; } -#ChatList .PlayerColor { +.ChatList .PlayerColor { width: 1em; height: 1em; padding: 0; @@ -188,6 +202,8 @@ } .Players { + flex: 1 0; + overflow: hidden; padding: 0.5em; user-select: none; } @@ -311,6 +327,7 @@ .Action { display: flex; + flex: 1 0; align-items: center; justify-content: space-evenly; background-color: rgba(16, 16, 16, 0.25); @@ -340,9 +357,9 @@ button { } .Message { - display: inline; + display: inline-block; + flex: 1 0; justify-content: left; - background-color: rgba(224, 224, 224); text-align: left; font-size: 12pt; padding: 0.5em; diff --git a/client/src/Table.js b/client/src/Table.js index d0c49cc..692a24e 100755 --- a/client/src/Table.js +++ b/client/src/Table.js @@ -156,7 +156,7 @@ class Resource extends React.Component { } }; -const Chat = ({ table, promoteGameState }) => { +const Chat = ({ table }) => { const [lastTop, setLastTop] = useState(0), [autoScroll, setAutoscroll] = useState(true), [scrollTime, setScrollTime] = useState(0); @@ -170,12 +170,8 @@ const Chat = ({ table, promoteGameState }) => { setAutoscroll(true); } - promoteGameState({ - chat: { - player: table.game.color ? table.game.color : undefined, - message: event.target.value - } - }); + table.sendChat(event.target.value); + event.target.value = ""; } }; @@ -230,11 +226,11 @@ const Chat = ({ table, promoteGameState }) => { const messages = table.game && table.game.chat.map((item, index) => { /* If the date is in the future, set it to now */ - const name = getPlayerName(table.game.sessions, item.from), + const name = item.from ? item.from : item.color, from = name ? `${name}, ` : ''; return ( - + {from} Date.now() ? @@ -247,10 +243,10 @@ const Chat = ({ table, promoteGameState }) => { return ( - + { messages } - { } const sendName = () => { - console.log(`Send: ${name}`); if (name !== table.game.name) { table.setPlayerName(name); } else { @@ -417,7 +412,6 @@ const getPlayerName = (sessions, color) => { * player's active item in the game */ const Players = ({ table }) => { const toggleSelected = (key) => { - console.log('toggle'); table.setSelected(table.game.color === key ? "" : key); } @@ -480,7 +474,6 @@ class Table extends React.Component { this.componentDidMount = this.componentDidMount.bind(this); this.updateDimensions = this.updateDimensions.bind(this); this.throwDice = this.throwDice.bind(this); - this.promoteGameState = this.promoteGameState.bind(this); this.resetGameLoad = this.resetGameLoad.bind(this); this.loadGame = this.loadGame.bind(this); this.rollDice = this.rollDice.bind(this); @@ -544,6 +537,39 @@ class Table extends React.Component { }); } + sendChat(message) { + if (this.loadTimer) { + window.clearTimeout(this.loadTimer); + this.loadTimer = null; + } + + return window.fetch(`${base}/api/v1/games/${this.state.game.id}/chat`, { + method: "PUT", + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ message: message }) + }).then((res) => { + if (res.status >= 400) { + throw new Error(`Unable to send chat message!`); + } + return res.json(); + }).then((game) => { + const error = (game.status !== 'success') ? game.status : undefined; + this.updateGame(game); + this.updateMessage(); + this.setState({ error: error }); + }).catch((error) => { + console.error(error); + this.setState({error: error.message}); + }).then(() => { + this.resetGameLoad(); + }); + } + + setPlayerName(name) { if (this.loadTimer) { window.clearTimeout(this.loadTimer); @@ -696,39 +722,6 @@ class Table extends React.Component { this.loadTimer = window.setTimeout(this.loadGame, 1000); } - promoteGameState(change) { - console.log("Requesting state change: ", change); - - if (this.loadTimer) { - window.clearTimeout(this.loadTimer); - this.loadTimer = null; - } - - return window.fetch(`${base}/api/v1/games/${this.state.game.id}`, { - method: "PUT", - cache: 'no-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(change) - }).then((res) => { - if (res.status >= 400) { - console.error(res); - throw new Error(`Unable to change state`); - } - return res.json(); - }).then((game) => { - this.updateGame(game); - this.setState({ error: "" }); - }).catch((error) => { - console.error(error); - this.setState({error: error.message}); - }).then(() => { - this.resetGameLoad(); - }); - } - setGameState(state) { if (this.loadTimer) { window.clearTimeout(this.loadTimer); @@ -1007,16 +1000,19 @@ class Table extends React.Component { return (
+ + { game &&
{ this.state.message } {(this.state.pickName || !game.name) && } {(!this.state.pickName && game.name) && <> - + }
} + { game && game.state === 'game-order' && } diff --git a/server/routes/games.js b/server/routes/games.js index 6a7e9bb..e9116f4 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -181,7 +181,7 @@ const processGameOrder = (game, player, dice) => { message = `Player order set to ${players.map((player, index) => { return `${index+1}. ${getPlayerName(game, player)}`; }).join(', ')}.`; - game.chat.push({ date: Date.now(), message: message }); + addChatMessage(game, null, message); game.state = 'active' message = `Game has started!`; } else { @@ -190,7 +190,7 @@ const processGameOrder = (game, player, dice) => { } if (message) { - game.chat.push({ date: Date.now(), message: message }); + addChatMessage(game, null, message); } } @@ -230,7 +230,7 @@ const roll = (game, session) => { } if (!error && message) { - game.chat.push({ from: session.color, date: Date.now(), message: message }); + addChatMessage(game, session, message); } return error; }; @@ -387,10 +387,7 @@ const adminActions = (game, action, value) => { } console.log(`Kicking ${value} from ${game.id}.`); const preamble = session.name ? `${session.name}, playing as ${color},` : color; - game.chat.push({ - date: Date.now(), - message: `${preamble} was kicked from game by the Admin.` - }); + addChatMessage(game, null, `${preamble} was kicked from game by the Admin.`); if (player) { session.player = undefined; clearPlayer(player); @@ -433,10 +430,8 @@ const setPlayerName = (game, session, name) => { return `You can not set your name to nothing!`; } - game.chat.push({ - date: Date.now(), - message: message - }); + addChatMessage(game, null, message); + } const setPlayerColor = (game, session, color) => { @@ -452,20 +447,17 @@ const setPlayerColor = (game, session, color) => { } const priorActive = getActiveCount(game); - + let message; + if (player) { /* Deselect currently active player for this session */ clearPlayer(player); - let message; if (game.state !== 'lobby') { message = `${name} has exited to the lobby and is no longer playing as ${session.color}.` + addChatMessage(game, null, message); } else { - message = `${name} is no longer ${session.color}.`; + message = `${name} is no longer ${session.color}.`; } - game.chat.push({ - date: Date.now(), - message: message - }); session.player = undefined; session.color = undefined; } @@ -477,6 +469,9 @@ const setPlayerColor = (game, session, color) => { /* If the player is not selecting a color, then return */ if (!color) { + if (message) { + addChatMessage(game, null, message); + } return; } @@ -499,23 +494,26 @@ const setPlayerColor = (game, session, color) => { session.player.status = `Active`; session.player.lastActive = Date.now(); session.color = color; - game.chat.push({ - from: color, - date: Date.now(), - message: `${session.name} has chosen to play as ${color}.` - }); + addChatMessage(game, session, `${session.name} has chosen to play as ${color}.`); const afterActive = getActiveCount(game); if (afterActive !== priorActive) { if (priorActive < 2 && afterActive >= 2) { - game.chat.push({ - date: Date.now(), - message: `There are now enough players to start the game when you are ready.` - }); + addChatMessage(game, null, + `There are now enough players to start the game when you are ready.`); } } }; +const addChatMessage = (game, session, message) => { + game.chat.push({ + from: session ? session.name : undefined, + color: session ? session.color : undefined, + date: Date.now(), + message: message + }); +}; + router.put("/:id/:action/:value?", async (req, res) => { const { action, id } = req.params, value = req.params.value ? req.params.value : ""; @@ -547,6 +545,10 @@ router.put("/:id/:action/:value?", async (req, res) => { case 'player-selected': error = setPlayerColor(game, session, value); return sendGame(req, res, game, error); + case 'chat': + const chat = req.body; + addChatMessage(game, session, chat.message); + return sendGame(req, res, game); } if (!session.player) { @@ -571,7 +573,7 @@ router.put("/:id/:action/:value?", async (req, res) => { if (!error) { shuffleBoard(game); const message = `${name} requested a new board.`; - game.chat.push({ date: Date.now(), message: message }); + addChatMessage(game, null, message); console.log(message); } break @@ -600,7 +602,7 @@ router.put("/:id/:action/:value?", async (req, res) => { } message = `${name} requested to start the game.`; - game.chat.push({ date: Date.now(), message: message }); + addChatMessage(game, null, message); game.state = state; break; } @@ -624,38 +626,6 @@ router.get("/:id", async (req, res/*, next*/) => { return sendGame(req, res, game); }); -router.put("/:id", (req, res/*, next*/) => { - const { id } = req.params; - - console.log("PUT games/" + id); - if (!(id in games)) { - const error = `Game not found: ${req.params.id}`; - return res.status(404).send(error); - } - - const game = games[id], - changes = req.body; - - for (let change in changes) { - switch (change) { - case "chat": - console.log("Chat change."); - game.chat.push({ - from: changes.chat.player, - date: Date.now(), - message: changes.chat.message - }); -/* - if (game.chat.length > 10) { - game.chat.splice(0, game.chat.length - 10); - } -*/ - break; - } - } - return sendGame(req, res, game); -}); - const getActiveCount = (game) => { let active = 0; for (let color in game.players) { @@ -672,7 +642,7 @@ const sendGame = async (req, res, game, error) => { if (active < 2 && game.state != 'lobby' && game.state != 'invalid') { let message = "Insufficient players in game. Setting back to lobby." console.log(game); - game.chat.push({ date: Date.now(), message: message }); + addChatMessage(game, null, message); console.log(message); game.state = 'lobby'; } @@ -770,10 +740,12 @@ const createGame = (id) => { wheat: 19, longestRoad: null, largestArmy: null, - chat: [ { date: Date.now(), message: `New game started for ${id}` } ], + chat: [], id: id }; + addChatMessage(game, null, `New game started for ${id}`); + [ "pips", "borders", "tiles" ].forEach((field) => { game[field] = assetData[field] });