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 (