diff --git a/WORKLOG.md b/WORKLOG.md
index 23d9bfdb..a6a115b5 100644
--- a/WORKLOG.md
+++ b/WORKLOG.md
@@ -35,6 +35,7 @@
*CLIENT*
reconnect based on time delta
menu footer
+fix refresh button
*SERVER*
diff --git a/client/.eslintrc.js b/client/.eslintrc.js
index 1f98c512..6d563030 100644
--- a/client/.eslintrc.js
+++ b/client/.eslintrc.js
@@ -61,6 +61,7 @@ module.exports = {
"react/jsx-uses-vars": 1,
"react/prefer-stateless-function": 1,
"react/prop-types": 0,
+ "react/no-unknown-property": 0,
// airbnb copypasta
// enforces getter/setter pairs in objects
diff --git a/client/assets/styles/game.css b/client/assets/styles/game.css
index 329d82fa..a5ac1076 100644
--- a/client/assets/styles/game.css
+++ b/client/assets/styles/game.css
@@ -79,8 +79,13 @@
stroke-width: 2px;
stroke: whitesmoke;
- /* some stupid bug in chrome makes it fill the entire screen */
- max-height: 10em;
+}
+
+/* some stupid bug in chrome makes it fill the entire screen */
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+ #targeting {
+ max-height: 10em;
+ }
}
.resolving #targeting {
diff --git a/client/assets/styles/instance.css b/client/assets/styles/instance.css
index da30514a..5de6c027 100644
--- a/client/assets/styles/instance.css
+++ b/client/assets/styles/instance.css
@@ -418,4 +418,4 @@ button.equipping {
}
/* Mobile Nav*/
-.instance .nav-btn { display: none; }
+.instance-nav { display: none; }
diff --git a/client/assets/styles/instance.mobile.css b/client/assets/styles/instance.mobile.css
index 92c7bbec..be7a2878 100644
--- a/client/assets/styles/instance.mobile.css
+++ b/client/assets/styles/instance.mobile.css
@@ -2,12 +2,10 @@
.instance {
display: grid;
grid-template-columns: 1fr;
- grid-template-rows: min-content, min-content, min-content, 1fr;
+ grid-template-rows: min-content, 1fr;
grid-template-areas:
- "top"
- "controls"
"vbox"
- "constructs"
+ "constructs";
}
.instance .nav-btn { display: initial; }
@@ -131,4 +129,20 @@
.instance-construct:last-child {
border-left: 1px solid #222;
}
+
+ .instance-nav {
+ display: flex;
+ grid-area: nav;
+ margin-right: 0;
+ border-top: 2px solid #444;
+ }
+
+ .instance-nav button {
+ font-size: 150%;
+ border-right: 2px solid #444;
+ }
+
+ .instance-nav button:last-child {
+ border: none;
+ }
}
\ No newline at end of file
diff --git a/client/assets/styles/styles.css b/client/assets/styles/styles.css
index ed9808a9..3c04b736 100644
--- a/client/assets/styles/styles.css
+++ b/client/assets/styles/styles.css
@@ -23,7 +23,7 @@ html, body, #mnml {
/*padding: 0 20%;*/
/* stops inspector going skitz*/
- /*overflow: hidden;*/
+ overflow-x: hidden;
}
html {
@@ -70,10 +70,11 @@ figure {
padding: 0 2em;
display: grid;
grid-template-columns: 1fr 8fr;
- grid-template-rows: min-content 1fr;
+ grid-template-rows: min-content 1fr min-content;
grid-template-areas:
"hd hd"
- "nav main";
+ "nav main"
+ "nav footer";
}
nav {
@@ -145,6 +146,7 @@ button, input {
letter-spacing: 0.25em;
box-sizing: border-box;
font-size: 100%;
+ flex: 1;
/*the transitions */
transition-property: color;
@@ -159,22 +161,6 @@ button:hover, button:focus {
border-color: whitesmoke;
}
-button.right[disabled]:hover, button.left[disabled]:hover {
- box-shadow: none;
-}
-
-button.top:hover, button.top:focus {
- box-shadow: inset 0 0.25em 0 0 whitesmoke;
-}
-
-button.right:hover, button.right:focus {
- box-shadow: inset -0.5em 0 0 0 whitesmoke;
-}
-
-button.left:hover, button.left:focus {
- box-shadow: inset 0.5em 0 0 0 whitesmoke;
-}
-
a {
color: whitesmoke;
font-size: 150%;
@@ -313,18 +299,20 @@ header {
letter-spacing: 0.05em;
}
-.header-username {
- letter-spacing: 0.05em;
- display: inline;
+.header-status {
+ margin: 1em 0;
+ display: flex;
}
-.header-status {
- text-align: right;
+.header-username {
+ letter-spacing: 0.05em;
+ flex: 1;
+ display: inline;
}
.header-status svg {
margin: 0.5em 0 0 1em;
- height: 1.5em;
+ height: 1em;
background-color: black;
stroke: whitesmoke;
}
@@ -359,29 +347,14 @@ header {
TEAM
*/
-.menu-constructs {
+.team {
+ display: flex;
display: grid;
- grid-template-rows: min-content min-content;
-
- grid-template-areas:
- "top"
- "team";
-}
-
-.constructs-list {
- max-height: 100%;
- margin-top: 0.5em;
- grid-area: team;
-
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- grid-auto-rows: 1fr;
- grid-gap: 0.5em;
+ grid-gap: 1em;
+ grid-template-columns: repeat(auto-fill,minmax(200px, 1fr));
}
.menu-construct {
- height: 100%;
- box-sizing: border-box;
border: 1px solid black;
display: flex;
@@ -544,10 +517,11 @@ main .top button {
max-height: 0.25em;
border: none;
- margin: 1em 0;
+ margin: 1em 0 0 0;
}
.timer {
+ flex: 1 0 100%;
background: whitesmoke;
transition-property: all;
transition-duration: 0.5s;
@@ -559,6 +533,33 @@ main .top button {
margin-bottom: 2em;
}
+footer {
+ display: flex;
+ flex-flow: row wrap;
+ grid-area: footer;
+ margin: 0;
+}
+
+footer button {
+ margin: 0;
+ border: none;
+ background: #222;
+}
+
+footer button:disabled {
+ color: #444;
+}
+
+footer button:not(:last-child) {
+ background: #222;
+ border-right: 1px solid black;
+}
+
+footer button .ready {
+ background: forestgreen;
+ color: black;
+}
+
@media (max-height: 900px), (max-width: 1500px) {
#mnml {
font-size: 75%;
@@ -569,7 +570,6 @@ main .top button {
}
}
-/* Mobile Nav*/
-#nav-btn {
+#nav-btn, #instance-nav {
display: none;
}
diff --git a/client/assets/styles/styles.mobile.css b/client/assets/styles/styles.mobile.css
index 75a4baed..62a5904a 100644
--- a/client/assets/styles/styles.mobile.css
+++ b/client/assets/styles/styles.mobile.css
@@ -2,11 +2,11 @@
#mnml {
font-size: 8pt;
padding: 0;
- grid-template-columns: min-content 1fr;
- grid-template-rows: min-content 1fr;
+ grid-template-columns: 1fr;
+ grid-template-rows: 1fr min-content;
grid-template-areas:
- "tnav hd "
- "main main";
+ "main"
+ "footer";
}
#mnml button {
@@ -21,9 +21,8 @@
display: none;
}
- #nav-btn {
- display: inline-block;
- margin: 0 0.5em;
+ #nav-btn, #instance-nav {
+ display: unset;
}
#mnml.nav-visible nav {
@@ -35,6 +34,10 @@
display: none;
}
+ header {
+ display: none;
+ }
+
main {
overflow-x: hidden;
}
diff --git a/client/src/components/footer.jsx b/client/src/components/footer.jsx
new file mode 100644
index 00000000..d7cfa295
--- /dev/null
+++ b/client/src/components/footer.jsx
@@ -0,0 +1,36 @@
+// eslint-disable-next-line
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const actions = require('./../actions');
+
+const TeamFooter = require('./team.footer');
+const ListFooter = require('./list.footer');
+const InstanceFooter = require('./instance.footer');
+const GameFooter = require('./game.footer');
+
+const addState = connect(
+ ({ nav, instance, game }) => {
+ return { nav, instance, game };
+ },
+ dispatch => ({
+ setShowNav: v => dispatch(actions.setShowNav(v)),
+ })
+);
+
+function renderHeader(args) {
+ const {
+ nav,
+ instance,
+ game,
+ } = args;
+
+ if (instance) return ;
+ if (game) return ;
+
+ if (nav === 'team') return ;
+ if (nav === 'list') return ;
+}
+
+
+module.exports = addState(renderHeader);
diff --git a/client/src/components/game.component.jsx b/client/src/components/game.component.jsx
deleted file mode 100644
index 9e3e4dee..00000000
--- a/client/src/components/game.component.jsx
+++ /dev/null
@@ -1,122 +0,0 @@
-const preact = require('preact');
-const GameConstruct = require('./game.construct');
-const Targeting = require('./targeting.arrows');
-
-function GamePanel(props) {
- const {
- game,
- account,
- resolution,
- setActiveSkill,
- setActiveConstruct,
- sendInstanceState,
- sendGameReady,
- skip,
- quit,
- } = props;
-
- if (!game) return
...
;
-
- function actionClick() {
- if (game.phase === 'Finish') {
- sendInstanceState(game.instance);
- quit();
- return true;
- }
-
- if (resolution) {
- return skip();
- }
-
- return sendGameReady();
- }
-
- const otherTeams = game.players.filter(t => t.id !== account.id);
- const playerTeam = game.players.find(t => t.id === account.id);
-
- let actionText = 'Ready';
- let actionStyles = 'instance-btn instance-ui-btn right';
- if (game.phase === 'Finish') actionText = 'Done';
- if (resolution) actionText = 'Skip';
- if (actionText === 'Ready' && playerTeam.ready) actionStyles += ' ready';
-
- const header = (
-
-
-
- );
-
- function findConstruct(id) {
- const team = game.players.find(t => t.constructs.find(c => c.id === id));
- if (team) return team.constructs.find(c => c.id === id);
- return null;
- }
-
- const zero = Date.parse(game.phase_start);
- const now = Date.now();
- const end = Date.parse(game.phase_end);
- const timerPct = ((now - zero) / (end - zero) * 100);
- const displayPct = resolution || game.phase === 'Finish'
- ? 0
- : Math.min(timerPct, 100);
-
- const displayColour = playerTeam.ready
- ? 'forestgreen'
- : timerPct > 80
- ? 'red'
- : 'whitesmoke';
-
- const timerStyles = {
- width: `${displayPct}%`,
- background: displayColour,
- };
-
- const timer = (
-
- );
-
- function PlayerTeam(team) {
- const constructs = team.constructs.map((c, i) =>
- );
- return (
-
- {constructs}
-
- );
- }
-
- function OpponentTeam(team) {
- const constructs = team.constructs.map((c, i) =>
- );
- return (
-
- {constructs}
-
- );
- }
-
- const gameClasses = `game ${resolution ? 'resolving': ''}`;
-
- function gameClick(e) {
- e.stopPropagation();
- setActiveConstruct(null);
- }
-
- return (
-
- {header}
- {timer}
- {otherTeams.map(OpponentTeam)}
-
- {PlayerTeam(playerTeam, setActiveSkill)}
-
- );
-}
-
-module.exports = GamePanel;
diff --git a/client/src/components/game.container.jsx b/client/src/components/game.container.jsx
deleted file mode 100644
index f6709c4c..00000000
--- a/client/src/components/game.container.jsx
+++ /dev/null
@@ -1,81 +0,0 @@
-const { connect } = require('preact-redux');
-
-const actions = require('../actions');
-
-const Game = require('./game.component');
-
-const addState = connect(
- function receiveState(state) {
- const {
- ws,
- game,
- account,
- resolution,
- showLog,
- activeSkill,
- activeConstruct,
- } = state;
-
- function selectSkillTarget(targetConstructId) {
- if (activeSkill) {
- return ws.sendGameSkill(game.id, activeSkill.constructId, targetConstructId, activeSkill.skill);
- }
- return false;
- }
-
- function sendGameReady() {
- ws.sendGameReady(game.id);
- }
-
- function sendInstanceState(instanceId) {
- if (!instanceId) return false;
- return ws.sendInstanceState(instanceId);
- }
-
- // intercept self casting skills
- if (activeSkill && activeSkill.skill.self_targeting) {
- ws.sendGameSkill(game.id, activeSkill.constructId, null, activeSkill.skill.skill);
- }
-
- return {
- game,
- showLog,
- account,
- resolution,
- activeSkill,
- activeConstruct,
- selectSkillTarget,
- sendInstanceState,
- sendGameReady,
- };
- },
-
- function receiveDispatch(dispatch) {
- function setActiveSkill(constructId, skill) {
- dispatch(actions.setActiveSkill(constructId, skill));
- // particlesJS(`particles-${constructId}`, config);
- }
-
- function setActiveConstruct(construct) {
- dispatch(actions.setActiveConstruct(construct));
- }
-
- function quit() {
- dispatch(actions.setGame(null));
- dispatch(actions.setInstance(null));
- }
-
- function toggleLog(v) {
- dispatch(actions.setShowLog(v));
- }
-
- function skip() {
- dispatch(actions.setSkip(true));
- }
-
- return { setActiveSkill, setActiveConstruct, quit, toggleLog, skip };
- }
-
-);
-
-module.exports = addState(Game);
diff --git a/client/src/components/game.footer.jsx b/client/src/components/game.footer.jsx
new file mode 100644
index 00000000..fd0bdc05
--- /dev/null
+++ b/client/src/components/game.footer.jsx
@@ -0,0 +1,136 @@
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const actions = require('../actions');
+
+const addState = connect(
+ function receiveState(state) {
+ const {
+ ws,
+ game,
+ account,
+ resolution,
+ showNav,
+ } = state;
+
+ function sendGameReady() {
+ ws.sendGameReady(game.id);
+ }
+
+ function sendInstanceState(instanceId) {
+ if (!instanceId) return false;
+ return ws.sendInstanceState(instanceId);
+ }
+
+ return {
+ game,
+ account,
+ resolution,
+ sendInstanceState,
+ sendGameReady,
+ showNav,
+ };
+ },
+
+ function receiveDispatch(dispatch) {
+ function quit() {
+ dispatch(actions.setGame(null));
+ dispatch(actions.setInstance(null));
+ }
+
+ function skip() {
+ dispatch(actions.setSkip(true));
+ }
+
+ function setShowNav(v) {
+ return dispatch(actions.setShowNav(v));
+ }
+
+ return { setShowNav, quit, skip };
+ }
+
+);
+
+function GameFooter(props) {
+ const {
+ game,
+ account,
+ resolution,
+ showNav,
+
+ quit,
+ skip,
+ setShowNav,
+ sendGameReady,
+ sendInstanceState,
+ } = props;
+
+ if (!game) {
+ return (
+
+ );
+ }
+
+ const playerTeam = game.players.find(t => t.id === account.id);
+
+ function actionClick() {
+ if (game.phase === 'Finish') {
+ sendInstanceState(game.instance);
+ quit();
+ return true;
+ }
+
+ if (resolution) {
+ return skip();
+ }
+
+ return sendGameReady();
+ }
+
+ let actionText = 'Ready';
+ if (game.phase === 'Finish') actionText = 'Done';
+ if (resolution) actionText = 'Skip';
+ const ready = (actionText === 'Ready' && playerTeam.ready)
+ ? 'ready'
+ : '';
+
+ const zero = Date.parse(game.phase_start);
+ const now = Date.now();
+ const end = Date.parse(game.phase_end);
+ const timerPct = ((now - zero) / (end - zero) * 100);
+ const displayPct = resolution || game.phase === 'Finish'
+ ? 0
+ : Math.min(timerPct, 100);
+
+ const displayColour = playerTeam.ready
+ ? 'forestgreen'
+ : timerPct > 80
+ ? 'red'
+ : 'whitesmoke';
+
+ const timerStyles = {
+ width: `${displayPct}%`,
+ background: displayColour,
+ };
+
+ const timer = (
+
+ );
+
+ return (
+
+ );
+}
+
+module.exports = addState(GameFooter);
diff --git a/client/src/components/game.jsx b/client/src/components/game.jsx
new file mode 100644
index 00000000..0c681863
--- /dev/null
+++ b/client/src/components/game.jsx
@@ -0,0 +1,107 @@
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const actions = require('../actions');
+
+const GameConstruct = require('./game.construct');
+const Targeting = require('./targeting.arrows');
+
+const addState = connect(
+ function receiveState(state) {
+ const {
+ ws,
+ game,
+ account,
+ resolution,
+ activeSkill,
+ activeConstruct,
+ } = state;
+
+ function selectSkillTarget(targetConstructId) {
+ if (activeSkill) {
+ return ws.sendGameSkill(game.id, activeSkill.constructId, targetConstructId, activeSkill.skill);
+ }
+ return false;
+ }
+
+ // intercept self casting skills
+ if (activeSkill && activeSkill.skill.self_targeting) {
+ ws.sendGameSkill(game.id, activeSkill.constructId, null, activeSkill.skill.skill);
+ }
+
+ return {
+ game,
+ account,
+ resolution,
+ activeSkill,
+ activeConstruct,
+ selectSkillTarget,
+ };
+ },
+
+ function receiveDispatch(dispatch) {
+ function setActiveSkill(constructId, skill) {
+ dispatch(actions.setActiveSkill(constructId, skill));
+ // particlesJS(`particles-${constructId}`, config);
+ }
+
+ function setActiveConstruct(construct) {
+ dispatch(actions.setActiveConstruct(construct));
+ }
+
+ return { setActiveSkill, setActiveConstruct };
+ }
+
+);
+
+function Game(props) {
+ const {
+ game,
+ account,
+ resolution,
+ setActiveSkill,
+ setActiveConstruct,
+ } = props;
+
+ if (!game) return ...
;
+
+ const otherTeams = game.players.filter(t => t.id !== account.id);
+ const playerTeam = game.players.find(t => t.id === account.id);
+
+ function PlayerTeam(team) {
+ const constructs = team.constructs.map((c, i) =>
+ );
+ return (
+
+ {constructs}
+
+ );
+ }
+
+ function OpponentTeam(team) {
+ const constructs = team.constructs.map((c, i) =>
+ );
+ return (
+
+ {constructs}
+
+ );
+ }
+
+ const gameClasses = `game ${resolution ? 'resolving': ''}`;
+
+ function gameClick(e) {
+ e.stopPropagation();
+ setActiveConstruct(null);
+ }
+
+ return (
+
+ {otherTeams.map(OpponentTeam)}
+
+ {PlayerTeam(playerTeam, setActiveSkill)}
+
+ );
+}
+
+module.exports = addState(Game);
diff --git a/client/src/components/header.container.jsx b/client/src/components/header.container.jsx
deleted file mode 100644
index 2b1e73f1..00000000
--- a/client/src/components/header.container.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-const { connect } = require('preact-redux');
-
-const Header = require('./header.component');
-const actions = require('./../actions');
-
-const addState = connect(
- ({ account, ping, showNav }) => {
- return { account, ping, showNav };
- },
- dispatch => ({
- setShowNav: v => dispatch(actions.setShowNav(v)),
- })
-);
-
-module.exports = addState(Header);
diff --git a/client/src/components/header.component.jsx b/client/src/components/header.jsx
similarity index 65%
rename from client/src/components/header.component.jsx
rename to client/src/components/header.jsx
index dc4f37da..d2ffdedc 100644
--- a/client/src/components/header.component.jsx
+++ b/client/src/components/header.jsx
@@ -1,7 +1,9 @@
// eslint-disable-next-line
const preact = require('preact');
+const { connect } = require('preact-redux');
const { saw } = require('./shapes');
+const actions = require('./../actions');
function pingColour(ping) {
if (ping < 100) return 'forestgreen';
@@ -9,8 +11,14 @@ function pingColour(ping) {
return 'red';
}
+const addState = connect(
+ ({ account, ping, showNav }) => {
+ return { account, ping };
+ },
+);
+
function renderHeader(args) {
- const { account, ping, setShowNav, showNav } = args;
+ const { account, ping } = args;
const accountStatus = account
? (
@@ -22,14 +30,11 @@ function renderHeader(args) {
return (
-
- setShowNav(!showNav)} >☰
- mnml.gg
-
+ mnml.gg
{accountStatus}
);
}
-module.exports = renderHeader;
+module.exports = addState(renderHeader);
diff --git a/client/src/components/instance.component.jsx b/client/src/components/instance.component.jsx
index 457ba45a..8ef11ff3 100644
--- a/client/src/components/instance.component.jsx
+++ b/client/src/components/instance.component.jsx
@@ -10,13 +10,8 @@ const actions = require('../actions');
const addState = connect(
function receiveState(state) {
- const { ws, instance, player, account, nav } = state;
-
- function sendInstanceReady() {
- return ws.sendInstanceReady(instance.id);
- }
-
- return { player, instance, sendInstanceReady, nav };
+ const { ws, instance, nav } = state;
+ return { instance, nav };
},
function receiveDispatch(dispatch) {
@@ -24,13 +19,8 @@ const addState = connect(
return dispatch(actions.setInfo(c));
}
- function setNav(v) {
- return dispatch(actions.setNav(v));
- }
-
return {
setInfo,
- setNav,
};
}
);
@@ -38,62 +28,13 @@ const addState = connect(
function Instance(args) {
const {
instance,
- player,
- sendInstanceReady,
setInfo,
nav,
- setNav,
} = args;
if (!instance) return false;
- function hoverInfo(e, info) {
- e.stopPropagation();
- return setInfo(info);
- }
-
- const rdyClasses = `instance-btn instance-ui-btn ${player.ready ? 'ready' : ''}`;
- const readyInfo = instance.phase === 'Lobby'
- ? 'lobbyReady'
- : 'ready';
- const readyBtn = (
-
- );
-
- function navClick() {
- if (nav === 'vbox') return setNav('constructs');
- return setNav('vbox');
- }
-
- const navBtn = (
-
- );
-
-
- const actionBtn = player
- ? readyBtn
- : null;
-
- // TIMER
- const zero = Date.parse(instance.phase_start);
- const now = Date.now();
- const end = Date.parse(instance.phase_end);
- const timerPct = ((now - zero) / (end - zero) * 100);
- const timerStyles = {
- width: `${timerPct < 100 ? timerPct : 0}%`,
- background: player.ready ? 'forestgreen' : 'whitesmoke',
- };
-
function playerRound(id) {
if (!instance.rounds.length) return null;
return instance.rounds[instance.rounds.length - 1].find(r => r.player_ids.includes(id));
@@ -139,21 +80,10 @@ function Instance(args) {
);
}
- const timer = (
-
- );
-
const instanceClasses = `instance ${nav === 'constructs' ? 'constructs-visible' : ''}`;
return (
setInfo(null)} >
-
- {actionBtn}
- {timer}
- {navBtn}
-
diff --git a/client/src/components/instance.footer.jsx b/client/src/components/instance.footer.jsx
new file mode 100644
index 00000000..e07e4db0
--- /dev/null
+++ b/client/src/components/instance.footer.jsx
@@ -0,0 +1,126 @@
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const actions = require('../actions');
+
+const addState = connect(
+ function receiveState(state) {
+ const { ws, instance, player, nav, showNav } = state;
+
+ function sendInstanceReady() {
+ return ws.sendInstanceReady(instance.id);
+ }
+
+ return { player, instance, sendInstanceReady, nav, showNav };
+ },
+
+ function receiveDispatch(dispatch) {
+ function setShowNav(v) {
+ return dispatch(actions.setShowNav(v));
+ }
+
+ function setInfo(c) {
+ return dispatch(actions.setInfo(c));
+ }
+
+ function setNav(v) {
+ return dispatch(actions.setNav(v));
+ }
+
+ return {
+ setInfo,
+ setNav,
+ setShowNav,
+ };
+ }
+);
+
+function Instance(args) {
+ const {
+ instance,
+ player,
+ nav,
+ showNav,
+
+ setInfo,
+ setNav,
+ setShowNav,
+
+ sendInstanceReady,
+ } = args;
+
+ if (!instance || !player) {
+ return (
+
+ );
+ }
+
+ function hoverInfo(e, info) {
+ e.stopPropagation();
+ return setInfo(info);
+ }
+
+ const rdyClasses = `${player.ready ? 'ready' : ''}`;
+ const readyInfo = instance.phase === 'Lobby'
+ ? 'lobbyReady'
+ : 'ready';
+
+ const readyBtn = (
+
+ );
+
+ function navClick() {
+ if (nav === 'vbox') return setNav('constructs');
+ return setNav('vbox');
+ }
+
+ const navBtn = instance.phase === 'InProgress'
+ ? (
+
+ )
+ : null;
+
+ const zero = Date.parse(instance.phase_start);
+ const now = Date.now();
+ const end = Date.parse(instance.phase_end);
+ const timerPct = ((now - zero) / (end - zero) * 100);
+
+ const displayColour = player.ready
+ ? 'forestgreen'
+ : timerPct > 80
+ ? 'red'
+ : 'whitesmoke';
+
+ const timerStyles = {
+ width: `${timerPct}%`,
+ background: displayColour,
+ };
+
+ const timer = (
+
+ );
+
+ return (
+
+ );
+}
+
+module.exports = addState(Instance);
diff --git a/client/src/components/list.footer.jsx b/client/src/components/list.footer.jsx
new file mode 100644
index 00000000..36a509cf
--- /dev/null
+++ b/client/src/components/list.footer.jsx
@@ -0,0 +1,47 @@
+const { connect } = require('preact-redux');
+const preact = require('preact');
+
+const actions = require('./../actions');
+
+const addState = connect(
+ function receiveState(state) {
+ const { showNav } = state;
+ return { showNav };
+ },
+ function receiveDispatch(dispatch) {
+ function navToTeam() {
+ return dispatch(actions.setNav('team'));
+ }
+
+ function setShowNav(v) {
+ return dispatch(actions.setShowNav(v));
+ }
+
+ return {
+ navToTeam,
+ setShowNav,
+ };
+ }
+);
+
+function ListFooter(args) {
+ const {
+ showNav,
+
+ navToTeam,
+ setShowNav,
+ } = args;
+
+ return (
+
+ );
+}
+
+module.exports = addState(ListFooter);
diff --git a/client/src/components/list.jsx b/client/src/components/list.jsx
index fe708d49..a8e6c8b4 100644
--- a/client/src/components/list.jsx
+++ b/client/src/components/list.jsx
@@ -37,15 +37,6 @@ const addState = connect(
instanceList,
};
},
-
- function receiveDispatch(dispatch) {
- function navToTeam() {
- return dispatch(actions.setNav('team'));
- }
- return {
- navToTeam,
- };
- }
);
function List(args) {
@@ -57,7 +48,6 @@ function List(args) {
sendInstanceJoin,
sendInstanceList,
instanceList,
- navToTeam,
} = args;
function listElements() {
@@ -120,20 +110,8 @@ function List(args) {
);
- const header = (
-
-
-
- );
-
-
return (
- {header}
{constructPanels}
diff --git a/client/src/components/main.jsx b/client/src/components/main.jsx
index a74bbd8b..2c418847 100644
--- a/client/src/components/main.jsx
+++ b/client/src/components/main.jsx
@@ -3,7 +3,7 @@ const preact = require('preact');
const { connect } = require('preact-redux');
const Login = require('./login');
-const GameContainer = require('./game.container');
+const Game = require('./game');
const Instance = require('./instance.component');
const Team = require('./team');
const List = require('./list');
@@ -28,7 +28,7 @@ function Main(props) {
}
if (game) {
- return ;
+ return ;
}
if (instance) {
diff --git a/client/src/components/mnml.jsx b/client/src/components/mnml.jsx
index 31f79e3e..bfa5adb6 100644
--- a/client/src/components/mnml.jsx
+++ b/client/src/components/mnml.jsx
@@ -1,19 +1,20 @@
const preact = require('preact');
const { connect } = require('preact-redux');
-const Header = require('./header.container');
+// const Header = require('./header');
const Main = require('./main');
const Nav = require('./nav');
+const Footer = require('./footer');
const addState = connect(
state => ({ showNav: state.showNav })
);
-const Mnml = ({ showNav, setShowNav }) =>
+const Mnml = ({ showNav }) =>
-
+
;
module.exports = addState(Mnml);
diff --git a/client/src/components/nav.jsx b/client/src/components/nav.jsx
index 6fed6645..7b65f110 100644
--- a/client/src/components/nav.jsx
+++ b/client/src/components/nav.jsx
@@ -3,9 +3,17 @@ const preact = require('preact');
const { Fragment } = require('preact');
const actions = require('../actions');
+const { saw } = require('./shapes');
+
const testGame = process.env.NODE_ENV === 'development' && require('./../test.game');
const testInstance = process.env.NODE_ENV === 'development' && require('./../test.instance');
+function pingColour(ping) {
+ if (ping < 100) return 'forestgreen';
+ if (ping < 200) return 'yellow';
+ return 'red';
+}
+
const addState = connect(
function receiveState(state) {
const {
@@ -13,7 +21,8 @@ const addState = connect(
account,
instances,
team,
- // constructs,
+ ping,
+
game,
} = state;
@@ -34,6 +43,7 @@ const addState = connect(
instances,
team,
game,
+ ping,
sendInstanceState,
sendAccountInstances,
sendInstanceList,
@@ -79,14 +89,15 @@ const addState = connect(
function Nav(args) {
const {
account,
- sendInstanceState,
- sendAccountInstances,
- sendInstanceList,
-
+ ping,
team,
instances,
game,
+ sendInstanceState,
+ sendAccountInstances,
+ sendInstanceList,
+
setTestGame,
setTestInstance,
setNav,
@@ -122,8 +133,18 @@ function Nav(args) {
const canJoin = team.some(c => !c);
+ const accountStatus = account
+ ? (
+
{account.name}
+ {saw(pingColour(ping))}
+
{ping}ms
+
)
+ : false;
+
return (