diff --git a/js/src/views/ParityBar/parityBar.css b/js/src/views/ParityBar/parityBar.css
index 985b169176d..6db06c2f451 100644
--- a/js/src/views/ParityBar/parityBar.css
+++ b/js/src/views/ParityBar/parityBar.css
@@ -47,7 +47,7 @@
right: 0;
&:hover {
- cursor: pointer;
+ cursor: move;
}
}
}
@@ -56,12 +56,16 @@
position: fixed;
transition-property: left, top, right, bottom;
- transition-duration: 0.1s;
- transition-timing-function: ease-in-out;
+ transition-duration: 0.25s;
+ transition-timing-function: ease;
+
+ &.moving {
+ transition-duration: 0.05s;
+ transition-timing-function: ease-in-out;
+ }
}
.expanded {
- right: 1em;
border-radius: 4px 4px 0 0;
display: flex;
flex-direction: column;
@@ -188,6 +192,28 @@
align-items: center;
&:hover {
- cursor: pointer;
+ cursor: move;
+ }
+}
+
+.dragButton {
+ width: 1em;
+ height: 1em;
+ margin-left: 0.5em;
+
+ background-color: white;
+ opacity: 0.25;
+ border-radius: 50%;
+
+ transition-property: opacity;
+ transition-duration: 0.1s;
+ transition-timing-function: ease-in-out;
+
+ &:hover {
+ opacity: 0.5;
+ }
+
+ &.moving {
+ opacity: 0.75;
}
}
diff --git a/js/src/views/ParityBar/parityBar.js b/js/src/views/ParityBar/parityBar.js
index 3108735be14..dfd20eeb734 100644
--- a/js/src/views/ParityBar/parityBar.js
+++ b/js/src/views/ParityBar/parityBar.js
@@ -18,9 +18,9 @@ import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { Link } from 'react-router';
import { connect } from 'react-redux';
-import { debounce } from 'lodash';
+import { throttle } from 'lodash';
-import { CancelIcon, FingerprintIcon, MoveIcon } from '~/ui/Icons';
+import { CancelIcon, FingerprintIcon } from '~/ui/Icons';
import { Badge, Button, ContainerTitle, ParityBackground } from '~/ui';
import { Embedded as Signer } from '../Signer';
@@ -28,8 +28,8 @@ import imagesEthcoreBlock from '../../../assets/images/parity-logo-white-no-text
import styles from './parityBar.css';
class ParityBar extends Component {
+ measures = null;
moving = false;
- offset = null;
static propTypes = {
pending: PropTypes.array,
@@ -39,15 +39,17 @@ class ParityBar extends Component {
state = {
moving: false,
opened: false,
- top: false,
- x: 0,
- y: 0
+ position: { right: '1em', bottom: 0 }
};
constructor (props) {
super(props);
- this.debouncedMouseMove = debounce(this._onMouseMove, 40, { leading: true });
+ this.debouncedMouseMove = throttle(
+ this._onMouseMove,
+ 40,
+ { leading: true, trailing: true }
+ );
}
componentWillReceiveProps (nextProps) {
@@ -66,8 +68,7 @@ class ParityBar extends Component {
}
render () {
- const { moving, opened, top, x, y } = this.state;
- const position = this.getPosition(x, y);
+ const { moving, opened, position } = this.state;
const content = opened
? this.renderExpanded()
@@ -85,25 +86,40 @@ class ParityBar extends Component {
? styles.expanded
: styles.corner;
- const parityBgStyle = opened
- ? {
- top: top ? 0 : undefined,
- bottom: top ? undefined : 0
+ const parityBgClassNames = [ parityBgClassName, styles.parityBg ];
+
+ if (moving) {
+ parityBgClassNames.push(styles.moving);
+ }
+
+ const parityBgStyle = {
+ ...position
+ };
+
+ if (opened) {
+ if (position.top !== undefined) {
+ parityBgStyle.top = 0;
+ } else {
+ parityBgStyle.bottom = 0;
+ }
+
+ if (position.left !== undefined) {
+ parityBgStyle.left = '1em';
+ } else {
+ parityBgStyle.right = '1em';
}
- : {
- left: position.x,
- top: position.y
- };
+ }
return (
@@ -113,30 +129,6 @@ class ParityBar extends Component {
);
}
- getPosition (_x, _y) {
- if (!this.moving || !this.offset) {
- return { x: _x, y: _y };
- }
-
- const { pageWidth = 0, pageHeight = 0, width = 0, height = 0 } = this.offset;
-
- const maxX = pageWidth - width;
- const maxY = pageHeight - height;
-
- const x = Math.min(maxX, Math.max(0, _x));
- const y = Math.min(maxY, Math.max(0, _y));
-
- if (y < 75) {
- return { x, y: 0 };
- }
-
- if (maxY - y < 75) {
- return { x, y: maxY };
- }
-
- return { x, y };
- }
-
renderBar () {
const { dapp } = this.props;
@@ -150,6 +142,12 @@ class ParityBar extends Component {
className={ styles.parityIcon } />
);
+ const dragButtonClasses = [ styles.dragButton ];
+
+ if (this.state.moving) {
+ dragButtonClasses.push(styles.moving);
+ }
+
return (
@@ -168,7 +166,10 @@ class ParityBar extends Component {
className={ styles.moveIcon }
onMouseDown={ this.onMouseDown }
>
-
+
);
@@ -222,22 +223,106 @@ class ParityBar extends Component {
return this.renderLabel('Signer', bubble);
}
+ getHorizontal (x) {
+ const { page, button, container } = this.measures;
+
+ const left = x - button.offset.left;
+ const centerX = left + container.width / 2;
+
+ // left part of the screen
+ if (centerX < page.width / 2) {
+ return { left: Math.max(0, left) };
+ }
+
+ const right = page.width - x - button.offset.right;
+ return { right: Math.max(0, right) };
+ }
+
+ getVertical (y) {
+ const STICKY_SIZE = 75;
+ const { page, button, container } = this.measures;
+
+ const top = y - button.offset.top;
+ const centerY = top + container.height / 2;
+
+ // top part of the screen
+ if (centerY < page.height / 2) {
+ // Add Sticky edges
+ const stickyTop = top < STICKY_SIZE
+ ? 0
+ : top;
+
+ return { top: Math.max(0, stickyTop) };
+ }
+
+ const bottom = page.height - y - button.offset.bottom;
+ // Add Sticky edges
+ const stickyBottom = bottom < STICKY_SIZE
+ ? 0
+ : bottom;
+
+ return { bottom: Math.max(0, stickyBottom) };
+ }
+
+ getPosition (x, y) {
+ if (!this.moving || !this.measures) {
+ return {};
+ }
+
+ const horizontal = this.getHorizontal(x);
+ const vertical = this.getVertical(y);
+
+ const position = {
+ ...horizontal,
+ ...vertical
+ };
+
+ return position;
+ }
+
onMouseDown = (event) => {
- const container = ReactDOM.findDOMNode(this.refs.container);
+ const containerElt = ReactDOM.findDOMNode(this.refs.container);
+ const dragButtonElt = ReactDOM.findDOMNode(this.refs.dragButton);
- if (!container) {
+ if (!containerElt || !dragButtonElt) {
+ console.warn(containerElt ? 'drag button' : 'container', 'not found...');
return;
}
- const { left, top, width, height } = container.getBoundingClientRect();
- const { clientX, clientY } = event;
const bodyRect = document.body.getBoundingClientRect();
+ const containerRect = containerElt.getBoundingClientRect();
+ const buttonRect = dragButtonElt.getBoundingClientRect();
+
+ const buttonOffset = {
+ top: (buttonRect.top + buttonRect.height / 2) - containerRect.top,
+ left: (buttonRect.left + buttonRect.width / 2) - containerRect.left
+ };
+
+ buttonOffset.bottom = containerRect.height - buttonOffset.top;
+ buttonOffset.right = containerRect.width - buttonOffset.left;
+
+ const button = {
+ offset: buttonOffset,
+ height: buttonRect.height,
+ width: buttonRect.width
+ };
- const pageHeight = bodyRect.height;
- const pageWidth = bodyRect.width;
+ const container = {
+ height: containerRect.height,
+ width: containerRect.width
+ };
+
+ const page = {
+ height: bodyRect.height,
+ width: bodyRect.width
+ };
this.moving = true;
- this.offset = { x: clientX - left, y: clientY - top, pageWidth, pageHeight, width, height };
+ this.measures = {
+ button,
+ container,
+ page
+ };
this.setState({ moving: true });
}
@@ -251,14 +336,23 @@ class ParityBar extends Component {
// If no left-click, stop move
if (buttons !== 1) {
- this.onMouseUp();
+ this.onMouseUp(event);
}
}
+ onMouseLeave = (event) => {
+ if (!this.moving) {
+ return;
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ }
+
onMouseMove = (event) => {
const { pageX, pageY } = event;
- this._onMouseMove({ pageX, pageY });
- // this.debouncedMouseMove({ pageX, pageY });
+ // this._onMouseMove({ pageX, pageY });
+ this.debouncedMouseMove({ pageX, pageY });
event.stopPropagation();
event.preventDefault();
@@ -270,9 +364,8 @@ class ParityBar extends Component {
}
const { pageX, pageY } = event;
- const { x = 0, y = 0 } = this.offset;
-
- this.setState({ x: pageX - x, y: pageY - y });
+ const position = this.getPosition(pageX, pageY);
+ this.setState({ position });
}
onMouseUp = (event) => {
@@ -280,22 +373,18 @@ class ParityBar extends Component {
return;
}
- const { height, width, pageHeight, pageWidth } = this.offset;
- const { x } = this.getPosition(this.state.x, this.state.y);
- const { y } = this.state;
-
- const top = y < (pageHeight / 2);
-
- const nextX = x < 25
- ? 25
- : x > (pageWidth - width - 25) ? x - 25 : x;
+ const { pageX, pageY } = event;
+ const position = this.getPosition(pageX, pageY);
- const nextY = top
- ? 0
- : (pageHeight - height);
+ // Stick to bottom or top
+ if (position.top !== undefined) {
+ position.top = 0;
+ } else {
+ position.bottom = 0;
+ }
this.moving = false;
- this.setState({ moving: false, top, x: nextX, y: nextY });
+ this.setState({ moving: false, position });
}
toggleDisplay = () => {