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}
}