From fac652b6b50d0d673d160260db7868573d2dd948 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Tue, 1 Mar 2022 15:39:09 -0800 Subject: [PATCH] Adding Activity window Signed-off-by: James Ketrenos --- client/src/Activities.css | 29 ++++++++++++++ client/src/Activities.js | 34 ++++++++++++++++ client/src/Table.css | 18 --------- client/src/Table.js | 81 ++++++++++++++++++++------------------- 4 files changed, 105 insertions(+), 57 deletions(-) create mode 100644 client/src/Activities.css create mode 100644 client/src/Activities.js diff --git a/client/src/Activities.css b/client/src/Activities.css new file mode 100644 index 0000000..94e0ec9 --- /dev/null +++ b/client/src/Activities.css @@ -0,0 +1,29 @@ +.Activities { + display: flex; + flex-direction: column; + position: absolute; + left: 1em; + top: 1em; + justify-content: left; + align-items: left; + z-index: 1000; + max-height: 100vh; + pointer-events: none; +} + +.Activities .Resource { + width: 3em; /* 5x7 aspect ratio */ + height: 5.2em; +} + +.Activities .PlayerColor { + display: inline-flex; + width: 0.8em; + height: 0.8em; + padding: 0; + margin: 0; +} + +.Activities > div { + padding: 0.5em; +} \ No newline at end of file diff --git a/client/src/Activities.js b/client/src/Activities.js new file mode 100644 index 0000000..f52e0b6 --- /dev/null +++ b/client/src/Activities.js @@ -0,0 +1,34 @@ +import React from "react"; +import "./Activities.css"; +import Paper from '@material-ui/core/Paper'; +import Resource from './Resource.js'; +import { getPlayerName } from './Common.js'; +import PlayerColor from './PlayerColor.js'; + + +const Activities = ({table }) => { + if (!table.game) { + return <>; + } + + const + game = table.game, + isTurn = (game.turn && game.turn.color === game.color) ? true : false, + normalPlay = (game.state === 'initial-placement' || game.state === 'normal'); + + return ( + + { !isTurn && normalPlay && (!game.player || !game.player.mustDiscard) && +
Waiting for {table.game.turn.name} to complete their turn.
+ } + { isTurn && normalPlay && game.player && game.player.mustDiscard && +
You must discard.
+ } + { isTurn && normalPlay && (!game.player || !game.player.mustDiscard) && +
It is your turn.
+ } +
+ ); +}; + +export default Activities; \ No newline at end of file diff --git a/client/src/Table.css b/client/src/Table.css index 083b06a..dcea2a5 100755 --- a/client/src/Table.css +++ b/client/src/Table.css @@ -46,24 +46,6 @@ overflow: visible; } -.WaitingForPlayer { - display: flex; - position: absolute; - left: 0.5em; - opacity: 0.8; - top: 0.5em; - justify-content: center; - align-items: center; - /*background: rgba(0,0,0,0.5);*/ - z-index: 0;/*1000*/ -} - -.WaitingForPlayer .Title { - align-self: center; - padding: 0.5em; - font-weight: bold; -} - .GameOrder { display: flex; position: absolute; diff --git a/client/src/Table.js b/client/src/Table.js index c058f76..642bb96 100755 --- a/client/src/Table.js +++ b/client/src/Table.js @@ -19,6 +19,7 @@ import ChooseCard from './ChooseCard.js'; import Chat from './Chat.js'; import { CircularProgress } from "@material-ui/core"; import 'moment-timezone'; +import Activities from './Activities.js'; /* Start of withRouter polyfill */ // https://reactrouter.com/docs/en/v6/faq#what-happened-to-withrouter-i-need-it @@ -131,16 +132,6 @@ const StartButton = ({ table }) => { ); }; -const WaitingForPlayer = ({table}) => { - return ( -
- { table.game && table.game.turn && -
Waiting for {table.game.turn.name} to complete their turn.
-
} -
- ); -} - const GameOrder = ({table}) => { const rollClick = (event) => { @@ -742,42 +733,59 @@ class Table extends React.Component { this.setState({ message: message }); } - resetKeepAlive() { + resetKeepAlive(isDead) { if (this.keepAlive) { clearTimeout(this.keepAlive); + this.keepAlive = 0; } - this.keepAlive = setTimeout(() => { - console.error(`No server ping for 5 seconds!`); - this.ws.close(); + + if (this.state.noNetwork !== false && !isDead) { + this.setState({ noNetwork: false }); + } else if (this.state.noNetwork !== true && isDead) { this.setState({ noNetwork: true }); + } + + this.keepAlive = setTimeout(() => { + console.error(`No server ping!`); + this.setState({ noNetwork: true }); + if (this.ws) { + this.ws.close(); + } if (!this.websocketReconnect) { this.websocketReconnect = setTimeout(() => { delete this.websocketReconnect; this.connectWebSocket(); }, 1000); } - }, 5000); + }, isDead ? 1000 : 5000); } connectWebSocket() { + if (!this.game) { + console.log(`Cannot initiate websocket connection while no game is set.`); + this.resetKeepAlive(true); + return; + } + let loc = window.location, new_uri; if (loc.protocol === "https:") { new_uri = "wss"; } else { new_uri = "ws"; } - new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${this.id}`; + new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${this.game.id}`; console.log(`Attempting WebSocket connection to ${new_uri}`); this.ws = new WebSocket(new_uri); this.ws.onopen = (event) => { console.log(`WebSocket open:`, event); - this.setState({ noNetwork: false }); this.resetKeepAlive(); }; this.ws.onmessage = (event) => { + this.resetKeepAlive(); + let data; try { data = JSON.parse(event.data); @@ -801,31 +809,18 @@ class Table extends React.Component { console.log(`Unknown event type: ${data.type}`); break; } - - this.resetKeepAlive(); - this.setState({ noNetwork: false }); } this.ws.onerror = (event) => { this.setState({ error: event.message }); console.error(`WebSocket error:`, event); - if (!this.websocketReconnect) { - this.websocketReconnect = setTimeout(() => { - delete this.websocketReconnect; - this.connectWebSocket(); - }, 1000); - } + this.resetKeepAlive(true); }; this.ws.onclose = (event) => { console.error(`WebSocket close:`, event); - this.setState({ noNetowrk: true, error: event.message }); - if (!this.websocketReconnect) { - this.websocketReconnect = setTimeout(() => { - delete this.websocketReconnect; - this.connectWebSocket(); - }, 1000); - } + this.setState({ error: event.message }); + this.resetKeepAlive(true); }; } @@ -833,7 +828,6 @@ class Table extends React.Component { this.start = new Date(); console.log(`Mounted: ${base}`); - this.connectWebSocket(); const params = {}; if (this.id) { @@ -886,8 +880,13 @@ class Table extends React.Component { if (!this.id) { history.push(`${gamesPath}/${game.id}`); } + this.id = game.id; this.updateGame(game); + + /* Connect to the WebSocket (after the game is setup) */ + this.connectWebSocket(); + this.updateMessage(); this.setState({ error: "" }); @@ -902,9 +901,15 @@ class Table extends React.Component { componentWillUnmount() { if (this.loadTimer) { clearTimeout(this.loadTimer); + this.loadTimer = 0; } if (this.keepAlive) { clearTimeout(this.keepAlive); + this.keepAlive = 0; + } + if (this.websocketReconnect) { + clearTimeout(this.websocketReconnect); + this.websocketReconnect = 0; } if (this.updateSizeTimer) { clearTimeout(this.updateSizeTimer); @@ -912,6 +917,7 @@ class Table extends React.Component { } if (this.errorTimeout) { clearTimeout(this.errorTimeout); + this.errorTimeout = 0; } } @@ -962,6 +968,8 @@ class Table extends React.Component { { this.state.loading > 0 && } { this.state.noNetwork &&
} + + { this.game && }
@@ -1041,11 +1049,6 @@ class Table extends React.Component { } - { game && game.turn && !isTurn && - (game.state === 'initial-placement' || game.state === 'normal') && - (!game.player || !game.player.mustDiscard) && - } - { this.state.error && this.setState({ error: undefined })} className="Error">
{this.state.error}
}