diff --git a/VERSION b/VERSION
index 721b9931..3e1ad720 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.4.8
\ No newline at end of file
+1.5.0
\ No newline at end of file
diff --git a/acp/package.json b/acp/package.json
index 67f5a80c..3d3a55d5 100644
--- a/acp/package.json
+++ b/acp/package.json
@@ -1,6 +1,6 @@
{
"name": "mnml-client",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/client/assets/styles/controls.less b/client/assets/styles/controls.less
index 58bc0b9f..f267351a 100644
--- a/client/assets/styles/controls.less
+++ b/client/assets/styles/controls.less
@@ -14,32 +14,32 @@ aside {
padding-left: 1em;
- .instance-ctrl {
- grid-template-rows: 1fr 1fr 1fr min-content;
- }
-
.controls {
grid-area: controls;
-
display: grid;
- grid-auto-rows: 1fr;
+
+ grid-template-areas:
+ "top"
+ "p0"
+ "p1"
+ "bottom";
+
+ .flex {
+ display: flex;
+ flex-flow: column;;
+ }
+
+ grid-template-rows: min-content 3fr 3fr 1fr;
grid-gap: 0.5em 0;
}
- &.play-ctrl {
- .controls {
- grid-template-rows: 4fr 4fr 1fr;
- }
- }
+ // &.play-ctrl {
+ // .controls {
+ // grid-template-rows: 4fr 4fr 1fr;
+ // }
+ // }
- // fix chrome being inconsistent
- table {
- height: 100%;
- }
-
- div {
- text-align: right;
- }
+ text-align: center;
button {
width: 100%;
@@ -106,8 +106,20 @@ aside {
padding: 0 0.75em 0 0.75em;
}
-.instance-ctrl-btns {
+.instance-ctrl-btns, .game-ctrl-btns {
font-size: 50%;
+
+ display: flex;
+ flex-flow: column;
+
+ button {
+ flex: 0;
+ }
+
+ .ready, .quit {
+ flex: 1;
+ font-size: 200%;
+ }
}
.abandon:not([disabled]) {
diff --git a/client/assets/styles/instance.less b/client/assets/styles/instance.less
index 9d3ea05a..151443c1 100644
--- a/client/assets/styles/instance.less
+++ b/client/assets/styles/instance.less
@@ -195,15 +195,6 @@
}
.construct-list {
- .avatar {
- grid-area: avatar;
- object-fit: contain;
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center;
- // pointer-events: none;
- }
-
.name {
grid-area: name;
margin-bottom: 0.5em;
diff --git a/client/assets/styles/player.less b/client/assets/styles/player.less
index 3dd302b9..03465f16 100644
--- a/client/assets/styles/player.less
+++ b/client/assets/styles/player.less
@@ -2,29 +2,35 @@
.player-box {
display: grid;
-
grid-template-areas:
- "score"
+ "msg"
"img"
+ "name"
+ "score"
"ctrl";
+ grid-template-rows: min-content 1fr min-content min-content min-content;
+
&.top {
grid-template-areas:
"ctrl"
+ "score"
+ "name"
"img"
- "score";
+ "msg";
- .img {
- display: flex;
- flex-flow: column;
- justify-content: flex-end;
- }
+ grid-template-rows: min-content min-content min-content 1fr min-content;
}
- grid-template-rows: min-content 1fr min-content;
-
.score {
grid-area: score;
+ display: flex;
+ justify-content: space-around;
+ text-align: center;
+
+ span {
+ flex: 1;
+ }
}
.img {
@@ -34,4 +40,10 @@
.ctrl {
grid-area: ctrl;
}
+
+ .msg {
+ grid-area: msg;
+ color: @white;
+ }
+
}
diff --git a/client/assets/styles/styles.less b/client/assets/styles/styles.less
index 2eb724cd..c512bf0f 100644
--- a/client/assets/styles/styles.less
+++ b/client/assets/styles/styles.less
@@ -286,7 +286,7 @@ li {
.logo {
height: 2em;
- background-image: url("../../src/components/svgs/mnml.2.svg");
+ background-image: url("../../src/components/svgs/menu.logo.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: left;
@@ -299,6 +299,15 @@ li {
background-position: center;
}
+.avatar {
+ grid-area: avatar;
+ object-fit: contain;
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: center;
+ // pointer-events: none;
+}
+
#clipboard {
width: 1px;
height: 1px;
diff --git a/client/package.json b/client/package.json
index 387e4c64..51074c78 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "mnml-client",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/client/src/components/account.box.jsx b/client/src/components/account.box.jsx
new file mode 100644
index 00000000..c6383c55
--- /dev/null
+++ b/client/src/components/account.box.jsx
@@ -0,0 +1,114 @@
+const { Component } = require('preact');
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const idleAnimation = require('./anims/idle');
+const wiggle = require('./anims/wiggle');
+
+const addState = connect(
+ function receiveState(state) {
+ const {
+ ws,
+ account,
+ mtxActive,
+ } = state;
+
+ function sendMtxAccountApply() {
+ return ws.sendMtxAccountApply(mtxActive);
+ }
+
+ return {
+ account,
+ mtxActive,
+
+ sendMtxAccountApply,
+ };
+ }
+);
+
+class AccountAvatar extends Component {
+ constructor() {
+ super();
+ // The animation ids are a check to ensure that animations are not repeated
+ // When a new account animation is communicated with state it will have a corresponding Id
+ // which is a count of how many resoluttions have passed
+ this.animations = [];
+ this.resetAnimations = this.resetAnimations.bind(this);
+ }
+
+ render() {
+ const { account, mtxActive } = this.props;
+ const imgStyle = account.img
+ ? { 'background-image': `url(/imgs/${account.img}.svg)`, cursor: mtxActive ? 'pointer' : '' }
+ : null;
+ return (
+
+
+ );
+ }
+
+ onClick() {
+ if (this.props.mtxActive) {
+ return this.props.sendMtxAccountApply();
+ }
+ return this.animations.push(wiggle(this.props.account.id, this.idle));
+ }
+
+ componentDidMount() {
+ this.idle = idleAnimation(this.props.account.id);
+ return this.animations.push(this.idle);
+ }
+
+ resetAnimations() {
+ for (let i = this.animations.length - 1; i >= 0; i--) {
+ this.animations[i].reset();
+ }
+ }
+
+ componentWillUnmount() {
+ this.resetAnimations();
+ }
+
+ // shouldComponentUpdate(newProps) {
+ // const { account } = newProps;
+
+ // if (account !== this.props.account) {
+ // return true;
+ // }
+
+ // return false;
+ // }
+}
+
+const StateAccountAvatar = addState(AccountAvatar);
+
+function AccountBox(args) {
+ const {
+ account,
+ } = args;
+
+ // if (!isTop) {
+ // return (
+ //
+ //
Processor
+ //
+ //
+ //
+ // );
+ // }
+
+ return (
+
+ );
+}
+
+module.exports = addState(AccountBox);
diff --git a/client/src/components/controls.jsx b/client/src/components/controls.jsx
index 828c767e..8df3d524 100644
--- a/client/src/components/controls.jsx
+++ b/client/src/components/controls.jsx
@@ -38,7 +38,7 @@ function Controls(args) {
if (game) return ;
if (instance) return ;
- if (nav === 'play' || !nav) return
+ if (nav === 'play' || nav === 'shop' || !nav) return
if (nav === 'team' || nav === 'account') return
return false;
diff --git a/client/src/components/game.ctrl.btns.jsx b/client/src/components/game.ctrl.btns.jsx
new file mode 100644
index 00000000..30513961
--- /dev/null
+++ b/client/src/components/game.ctrl.btns.jsx
@@ -0,0 +1,83 @@
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const actions = require('../actions');
+
+const addState = connect(
+ function receiveState(state) {
+ const {
+ ws,
+ game,
+ animating,
+ } = state;
+
+ function sendReady() {
+ document.activeElement.blur();
+ return ws.sendGameReady(game.id);
+ }
+
+ function getInstanceState() {
+ return ws.sendInstanceState(game.instance);
+ }
+
+ function sendGameSkillClear() {
+ return ws.sendGameSkillClear(game.id);
+ }
+
+ function sendAbandon() {
+ return ws.sendInstanceAbandon(game.instance);
+ }
+
+ return {
+ game,
+ sendAbandon,
+ sendGameSkillClear,
+ sendReady,
+ getInstanceState,
+ animating,
+ };
+ },
+
+ function receiveDispatch(dispatch) {
+ function quit() {
+ dispatch(actions.setNav('transition'));
+ dispatch(actions.setGame(null));
+ dispatch(actions.setInstance(null));
+ }
+
+ return { quit };
+ }
+);
+
+function GameCtrlBtns(args) {
+ const {
+ game,
+ animating,
+
+ getInstanceState,
+ sendGameSkillClear,
+ sendReady,
+ quit,
+ } = args;
+
+ if (!game) return false;
+ const finished = game.phase === 'Finish';
+
+ function quitClick() {
+ getInstanceState();
+ quit();
+ }
+
+ const readyBtn = ;
+ const quitBtn = ;
+
+ return (
+
+
+
+ {finished ? quitBtn : readyBtn}
+
+ );
+}
+
+module.exports = addState(GameCtrlBtns);
diff --git a/client/src/components/game.ctrl.btns.top.jsx b/client/src/components/game.ctrl.btns.top.jsx
new file mode 100644
index 00000000..5abcdcae
--- /dev/null
+++ b/client/src/components/game.ctrl.btns.top.jsx
@@ -0,0 +1,64 @@
+const preact = require('preact');
+const { connect } = require('preact-redux');
+
+const actions = require('../actions');
+
+const addState = connect(
+ function receiveState(state) {
+ const {
+ ws,
+ game,
+ } = state;
+
+ function sendAbandon() {
+ return ws.sendInstanceAbandon(game.instance);
+ }
+
+ return {
+ game,
+
+ sendAbandon,
+ };
+ },
+ function receiveDispatch(dispatch) {
+ function leave() {
+ dispatch(actions.setNav('play'));
+ dispatch(actions.setGame(null));
+ dispatch(actions.setInstance(null));
+ }
+
+ return { leave };
+ }
+);
+
+function GameCtrlTopBtns(args) {
+ const {
+ game,
+
+ leave,
+ sendAbandon,
+ } = args;
+
+ const finished = game && game.phase === 'Finished';
+ const { abandonState } = this.state;
+
+ const abandonStateTrue = e => {
+ e.stopPropagation();
+ this.setState({ abandonState: true });
+ setTimeout(() => this.setState({ abandonState: false }), 2000);
+ };
+
+ const abandonClasses = `abandon ${abandonState ? 'confirming' : ''}`;
+ const abandonAction = abandonState ? sendAbandon : abandonStateTrue;
+
+ const abandonBtn = ;
+ const leaveBtn = ;
+
+ return (
+
+ {finished ? leaveBtn : abandonBtn}
+
+ );
+}
+
+module.exports = addState(GameCtrlTopBtns);
diff --git a/client/src/components/game.ctrl.jsx b/client/src/components/game.ctrl.jsx
index 0aa4220f..12c308a5 100644
--- a/client/src/components/game.ctrl.jsx
+++ b/client/src/components/game.ctrl.jsx
@@ -4,80 +4,34 @@ const { connect } = require('preact-redux');
const actions = require('../actions');
const PlayerBox = require('./player.box');
-const InstanceCtrlBtns = require('./instance.ctrl.btns');
+const GameCtrlButtons = require('./game.ctrl.btns');
+const GameCtrlTopButtons = require('./game.ctrl.btns.top');
const addState = connect(
function receiveState(state) {
const {
- ws,
game,
account,
- animating,
} = state;
- function sendReady() {
- document.activeElement.blur();
- return ws.sendGameReady(game.id);
- }
-
- function getInstanceState() {
- return ws.sendInstanceState(game.instance);
- }
-
- function sendGameSkillClear() {
- return ws.sendGameSkillClear(game.id);
- }
-
- function sendAbandon() {
- return ws.sendInstanceAbandon(game.instance);
- }
-
return {
game,
- sendAbandon,
- sendGameSkillClear,
- sendReady,
account,
- getInstanceState,
- animating,
};
},
-
- function receiveDispatch(dispatch) {
- function quit() {
- dispatch(actions.setNav('transition'));
- dispatch(actions.setGame(null));
- dispatch(actions.setInstance(null));
- }
-
- return { quit };
- }
);
function Controls(args) {
const {
account,
- sendAbandon,
game,
- animating,
- sendGameSkillClear,
- sendReady,
- getInstanceState,
- quit,
} = args;
if (!game) return false;
- const { abandonState } = this.state;
-
const opponent = game.players.find(t => t.id !== account.id);
const player = game.players.find(t => t.id === account.id);
- function quitClick() {
- getInstanceState();
- quit();
- }
-
const zero = Date.parse(game.phase_start);
const now = Date.now();
const end = Date.parse(game.phase_end);
@@ -104,30 +58,14 @@ function Controls(args) {
);
- const readyBtn = ;
- const quitBtn = ;
-
- const cancelAbandon = e => {
- e.stopPropagation();
- return this.setState({ abandonState: false });
- };
-
- const abandonStateTrue = e => {
- e.stopPropagation();
- this.setState({ abandonState: true });
- };
-
- const abandonClasses = `abandon ${abandonState ? 'confirming' : ''}`;
- const abandonAction = abandonState ? sendAbandon : abandonStateTrue;
-
return (
-