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 ( +
+
 
+ +
{account.name}
+
 
+
+ ); +} + +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 ( -