diff --git a/VERSION b/VERSION index e1df5de7..03e5161d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.4 \ No newline at end of file +1.4.5 \ No newline at end of file diff --git a/acp/package.json b/acp/package.json index da7908ae..2d6bcc99 100644 --- a/acp/package.json +++ b/acp/package.json @@ -1,6 +1,6 @@ { "name": "mnml-client", - "version": "1.4.4", + "version": "1.4.5", "description": "", "main": "index.js", "scripts": { diff --git a/client/assets/styles/controls.less b/client/assets/styles/controls.less index eebcc6c6..58bc0b9f 100644 --- a/client/assets/styles/controls.less +++ b/client/assets/styles/controls.less @@ -53,7 +53,7 @@ aside { border-color: forestgreen; } - &:active, &:focus { + &:active, &:focus, &.enabled { background: forestgreen; color: black; border-color: forestgreen; diff --git a/client/assets/styles/styles.less b/client/assets/styles/styles.less index 66bdb2cd..83ab40d9 100644 --- a/client/assets/styles/styles.less +++ b/client/assets/styles/styles.less @@ -286,3 +286,9 @@ li { background-repeat: no-repeat; background-position: center; } + +#clipboard { + width: 1px; + height: 1px; + padding: 0px; +} \ No newline at end of file diff --git a/client/package.json b/client/package.json index 2897558c..f03cab0e 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "mnml-client", - "version": "1.4.4", + "version": "1.4.5", "description": "", "main": "index.js", "scripts": { @@ -29,6 +29,7 @@ "preact-compat": "^3.19.0", "preact-context": "^1.1.3", "preact-redux": "^2.1.0", + "query-string": "^6.8.3", "react-string-replace": "^0.4.4", "react-stripe-elements": "^3.0.0", "redux": "^4.0.0" diff --git a/client/src/actions.jsx b/client/src/actions.jsx index d4fe0dc8..ccfadcaa 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -19,6 +19,7 @@ export const setConstructRename = value => ({ type: 'SET_CONSTRUCT_RENAME', valu export const setGame = value => ({ type: 'SET_GAME', value }); export const setInfo = value => ({ type: 'SET_INFO', value }); export const setEmail = value => ({ type: 'SET_EMAIL', value }); +export const setInvite = value => ({ type: 'SET_INVITE', value }); export const setInstance = value => ({ type: 'SET_INSTANCE', value }); export const setInstances = value => ({ type: 'SET_INSTANCES', value }); export const setItemEquip = value => ({ type: 'SET_ITEM_EQUIP', value }); diff --git a/client/src/components/anims/banish.jsx b/client/src/components/anims/banish.jsx index 62d3096a..12ae365a 100644 --- a/client/src/components/anims/banish.jsx +++ b/client/src/components/anims/banish.jsx @@ -2,7 +2,7 @@ const anime = require('animejs').default; const { TIMES } = require('../../constants'); -function Banish(id) { +function Banish(id, idle) { return anime({ targets: [document.getElementById(id)], scaleY: 0, @@ -11,6 +11,8 @@ function Banish(id) { delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.45, direction: 'alternate', + begin: idle.pause, + complete: idle.play, }); } diff --git a/client/src/components/anims/invert.jsx b/client/src/components/anims/invert.jsx index 57a787d8..ac083bea 100644 --- a/client/src/components/anims/invert.jsx +++ b/client/src/components/anims/invert.jsx @@ -2,7 +2,7 @@ const anime = require('animejs').default; const { TIMES } = require('../../constants'); -function Invert(id) { +function Invert(id, idle) { return anime({ targets: [document.getElementById(id)], rotate: 180, @@ -10,6 +10,8 @@ function Invert(id) { duration: TIMES.TARGET_DURATION_MS * 0.45, easing: 'easeInOutElastic', direction: 'alternate', + begin: idle.pause, + complete: idle.play, }); } diff --git a/client/src/components/anims/source.cast.jsx b/client/src/components/anims/source.cast.jsx index 25cb8ae8..74a17184 100644 --- a/client/src/components/anims/source.cast.jsx +++ b/client/src/components/anims/source.cast.jsx @@ -2,15 +2,17 @@ const anime = require('animejs').default; const { TIMES } = require('../../constants'); -function sourceCast(id, direction) { +function sourceCast(id, direction, idle) { const { x, y } = direction; return anime({ targets: [document.getElementById(id)], - translateX: [0, x * 200], - translateY: [0, y * 200], + translateX: x * window.screen.width * 0.15, + translateY: y * window.screen.height * 0.15, easing: 'easeInOutElastic', direction: 'alternate', duration: TIMES.SOURCE_DURATION_MS, + begin: idle.pause, + complete: idle.play, }); } diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 17e97349..964da49c 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -37,73 +37,8 @@ class ConstructAvatar extends Component { } componentDidMount() { - const { animSource, animTarget, construct } = this.props; - - // back to idle - if (!animTarget && !animSource) { - if (!this.idle) { - this.idle = idleAnimation(this.props.construct.id); - return this.animations.push(this.idle); - } - - return this.idle.play(); - } - - const isSource = animSource && animSource.constructId === construct.id; - - const selectAnim = () => { - if (isSource) { - console.warn(construct.name, animSource); - return sourceCast(animSource.constructId, animSource.direction); - } - - switch (animTarget.skill) { - case 'banish': return banish(construct.id); - case 'invert': return invert(construct.id); - default: return null; - } - }; - - const anim = selectAnim(); - if (!anim) return false; - - this.idle.pause(); - this.animations.push(anim); - return true; - } - - componentDidUpdate(prevProps) { - const { animSource, animTarget, construct } = this.props; - - // back to idle - if (!animTarget && !animSource) { - if (!this.idle) { - this.idle = idleAnimation(this.props.construct.id); - return this.animations.push(this.idle); - } - return this.idle.play(); - } - - const isSource = animSource && animSource.constructId === construct.id; - - const selectAnim = () => { - if (isSource) { - return sourceCast(animSource.constructId, animSource.direction); - } - - switch (animTarget.skill) { - case 'Banish': return banish(construct.id); - case 'Invert': return invert(construct.id); - default: return null; - } - }; - - const anim = selectAnim(); - if (!anim) return false; - - this.idle.pause(); - this.animations.push(anim); - return true; + this.idle = idleAnimation(this.props.construct.id); + return this.animations.push(this.idle); } resetAnimations() { @@ -132,24 +67,19 @@ class ConstructAvatar extends Component { // this is the source if (animSource && animSource.constructId === construct.id) { // console.warn(construct.name, 'should update') - return true; + return sourceCast(animSource.constructId, animSource.direction, this.idle); } // this is the target if (animTarget && animTarget.constructId.includes(construct.id)) { // console.warn(construct.name, 'should update') - return true; + switch (animTarget.skill) { + case 'Banish': return banish(construct.id, this.idle); + case 'Invert': return invert(construct.id, this.idle); + default: return null; + } } - // we were previously doing src anim - const prevSrc = this.props.animSource && this.props.animSource.constructId === construct.id; - if (prevSrc && !animSource) return true; - - const prevTarget = this.props.animTarget && this.props.animTarget.constructId.includes(construct.id); - if (prevTarget && !animTarget) return true; - - // console.warn(construct.name, 'not updating'); - return false; } } diff --git a/client/src/components/instance.ctrl.jsx b/client/src/components/instance.ctrl.jsx index faa38afb..329eea45 100644 --- a/client/src/components/instance.ctrl.jsx +++ b/client/src/components/instance.ctrl.jsx @@ -76,11 +76,13 @@ function Controls(args) { background: displayColour, }; - const timer = ( -
-
 
-
- ); + const timer = instance.phase !== 'InProgress' + ? null + : ( +
+
 
+
+ ); const ready = instance.phase !== 'Finished' ? diff --git a/client/src/components/play.ctrl.jsx b/client/src/components/play.ctrl.jsx index e87e01e5..0df4f4d0 100644 --- a/client/src/components/play.ctrl.jsx +++ b/client/src/components/play.ctrl.jsx @@ -1,11 +1,14 @@ const preact = require('preact'); const { connect } = require('preact-redux'); +const { errorToast, infoToast } = require('../utils'); + const addState = connect( function receiveState(state) { const { ws, instances, + invite, } = state; function sendInstanceState(id) { @@ -20,12 +23,18 @@ const addState = connect( ws.sendInstanceQueue(); } + function sendInstanceInvite() { + ws.sendInstanceInvite(); + } + return { instances, + invite, sendInstanceState, sendInstanceQueue, sendInstancePractice, + sendInstanceInvite, }; } ); @@ -33,10 +42,12 @@ const addState = connect( function JoinButtons(args) { const { instances, + invite, sendInstanceState, sendInstanceQueue, sendInstancePractice, + sendInstanceInvite, } = args; if (instances.length) { @@ -55,6 +66,48 @@ function JoinButtons(args) { ); } + const inviteBtn = () => { + if (!invite) { + return ( + + ); + } + + function copyClick(e) { + const link = `${document.location.origin}#join=${invite}`; + const textArea = document.createElement('textarea', { id: '#clipboard' }); + textArea.value = link; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + document.execCommand('copy'); + infoToast('Invite link copied.'); + } catch (err) { + console.error('link copy error', err); + errorToast('Invite link copy error.'); + } + + document.body.removeChild(textArea); + return true; + } + + return ( + + ); + }; + return (