diff --git a/src/modals/ForceUpdateModal.js b/src/modals/ForceUpdateModal.js
new file mode 100644
index 0000000..7edf7bc
--- /dev/null
+++ b/src/modals/ForceUpdateModal.js
@@ -0,0 +1,23 @@
+import React from "react";
+import { Box, Label, Text } from "theme-ui";
+
+import Modal from "../components/Modal";
+
+function ForceUpdateModal({ isOpen }) {
+ return (
+
+
+
+
+ Please refresh your browser to update to the latest version.
+
+
+
+ );
+}
+
+export default ForceUpdateModal;
diff --git a/src/network/Session.js b/src/network/Session.js
index 88d4671..b2973cc 100644
--- a/src/network/Session.js
+++ b/src/network/Session.js
@@ -26,7 +26,7 @@ import { logError } from "../helpers/logging";
* Session Status Event - Status of the session has changed
*
* @event Session#status
- * @property {"ready"|"joining"|"joined"|"offline"|"reconnecting"|"auth"} status
+ * @property {"ready"|"joining"|"joined"|"offline"|"reconnecting"|"auth"|"needs_update"} status
*/
/**
@@ -101,6 +101,7 @@ class Session extends EventEmitter {
this.socket.on("game_expired", this._handleGameExpired.bind(this));
this.socket.on("disconnect", this._handleSocketDisconnect.bind(this));
this.socket.io.on("reconnect", this._handleSocketReconnect.bind(this));
+ this.socket.on("force_update", this._handleForceUpdate.bind(this));
this.emit("status", "ready");
} catch (error) {
@@ -197,7 +198,7 @@ class Session extends EventEmitter {
this._gameId = gameId;
this._password = password;
- this.socket.emit("join_game", gameId, password);
+ this.socket.emit("join_game", gameId, password, process.env.REACT_APP_VERSION);
this.emit("status", "joining");
}
@@ -418,6 +419,16 @@ class Session extends EventEmitter {
this.joinGame(this._gameId, this._password);
}
}
+
+ _handleForceUpdate() {
+ /**
+ * Force Update Event - An update has been released
+ *
+ * @event Session#forceUpdate
+ */
+ this.socket.disconnect();
+ this.emit("status", "needs_update");
+ }
}
export default Session;
diff --git a/src/routes/Game.js b/src/routes/Game.js
index 7610850..190fb86 100644
--- a/src/routes/Game.js
+++ b/src/routes/Game.js
@@ -11,6 +11,7 @@ import MapLoadingOverlay from "../components/map/MapLoadingOverlay";
import AuthModal from "../modals/AuthModal";
import GameExpiredModal from "../modals/GameExpiredModal";
+import ForceUpdateModal from "../modals/ForceUpdateModal";
import { useAuth } from "../contexts/AuthContext";
import { MapStageProvider } from "../contexts/MapStageContext";
@@ -83,6 +84,7 @@ function Game() {
};
}, [session]);
+
// Join game
useEffect(() => {
if (sessionStatus === "ready" && databaseStatus !== "loading") {
@@ -137,6 +139,9 @@ function Game() {
isOpen={gameExpired}
onRequestClose={() => setGameExpired(false)}
/>
+
{!sessionStatus && }