Adjust the location of the signer snippet (#4155)
* Move signer tab * WIP * Better movments * Save Parity Bar position per dapp * Add position to Dapp Manifest * Stick Parity Bar to the four corners
This commit is contained in:
parent
ebe9072836
commit
6b52ed4dfa
@ -25,8 +25,10 @@ import DashboardIcon from 'material-ui/svg-icons/action/dashboard';
|
|||||||
import DeleteIcon from 'material-ui/svg-icons/action/delete';
|
import DeleteIcon from 'material-ui/svg-icons/action/delete';
|
||||||
import DoneIcon from 'material-ui/svg-icons/action/done-all';
|
import DoneIcon from 'material-ui/svg-icons/action/done-all';
|
||||||
import EditIcon from 'material-ui/svg-icons/content/create';
|
import EditIcon from 'material-ui/svg-icons/content/create';
|
||||||
|
import FingerprintIcon from 'material-ui/svg-icons/action/fingerprint';
|
||||||
import LinkIcon from 'material-ui/svg-icons/content/link';
|
import LinkIcon from 'material-ui/svg-icons/content/link';
|
||||||
import LockedIcon from 'material-ui/svg-icons/action/lock';
|
import LockedIcon from 'material-ui/svg-icons/action/lock';
|
||||||
|
import MoveIcon from 'material-ui/svg-icons/action/open-with';
|
||||||
import NextIcon from 'material-ui/svg-icons/navigation/arrow-forward';
|
import NextIcon from 'material-ui/svg-icons/navigation/arrow-forward';
|
||||||
import PrevIcon from 'material-ui/svg-icons/navigation/arrow-back';
|
import PrevIcon from 'material-ui/svg-icons/navigation/arrow-back';
|
||||||
import SaveIcon from 'material-ui/svg-icons/content/save';
|
import SaveIcon from 'material-ui/svg-icons/content/save';
|
||||||
@ -48,8 +50,10 @@ export {
|
|||||||
DeleteIcon,
|
DeleteIcon,
|
||||||
DoneIcon,
|
DoneIcon,
|
||||||
EditIcon,
|
EditIcon,
|
||||||
|
FingerprintIcon,
|
||||||
LinkIcon,
|
LinkIcon,
|
||||||
LockedIcon,
|
LockedIcon,
|
||||||
|
MoveIcon,
|
||||||
NextIcon,
|
NextIcon,
|
||||||
PrevIcon,
|
PrevIcon,
|
||||||
SaveIcon,
|
SaveIcon,
|
||||||
|
@ -26,7 +26,12 @@ class ParityBackground extends Component {
|
|||||||
backgroundSeed: PropTypes.string,
|
backgroundSeed: PropTypes.string,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
onClick: PropTypes.func
|
onClick: PropTypes.func,
|
||||||
|
style: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
style: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -65,7 +70,11 @@ class ParityBackground extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { children, className, onClick } = this.props;
|
const { children, className, onClick } = this.props;
|
||||||
const { style } = this.state;
|
|
||||||
|
const style = {
|
||||||
|
...this.state.style,
|
||||||
|
...this.props.style
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
"description": "A Javascript development console complete with web3 and parity objects.",
|
"description": "A Javascript development console complete with web3 and parity objects.",
|
||||||
"version": "0.3",
|
"version": "0.3",
|
||||||
"author": "Gav Wood <gavin@ethcore.io>",
|
"author": "Gav Wood <gavin@ethcore.io>",
|
||||||
|
"position": "top-right",
|
||||||
"visible": true,
|
"visible": true,
|
||||||
"secure": true,
|
"secure": true,
|
||||||
"skipBuild": true
|
"skipBuild": true
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import EventEmitter from 'eventemitter3';
|
||||||
import { action, computed, observable, transaction } from 'mobx';
|
import { action, computed, observable, transaction } from 'mobx';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ const BUILTIN_APPS_KEY = 'BUILTIN_APPS_KEY';
|
|||||||
|
|
||||||
let instance = null;
|
let instance = null;
|
||||||
|
|
||||||
export default class DappsStore {
|
export default class DappsStore extends EventEmitter {
|
||||||
@observable apps = [];
|
@observable apps = [];
|
||||||
@observable displayApps = {};
|
@observable displayApps = {};
|
||||||
@observable modalOpen = false;
|
@observable modalOpen = false;
|
||||||
@ -44,6 +45,8 @@ export default class DappsStore {
|
|||||||
_registryAppsIds = null;
|
_registryAppsIds = null;
|
||||||
|
|
||||||
constructor (api) {
|
constructor (api) {
|
||||||
|
super();
|
||||||
|
|
||||||
this._api = api;
|
this._api = api;
|
||||||
|
|
||||||
this.readDisplayApps();
|
this.readDisplayApps();
|
||||||
@ -51,6 +54,14 @@ export default class DappsStore {
|
|||||||
this.subscribeToChanges();
|
this.subscribeToChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get (api) {
|
||||||
|
if (!instance) {
|
||||||
|
instance = new DappsStore(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to find the app from the local (local or builtin)
|
* Try to find the app from the local (local or builtin)
|
||||||
* apps, else fetch from the node
|
* apps, else fetch from the node
|
||||||
@ -68,6 +79,10 @@ export default class DappsStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.fetchRegistryApp(dappReg, id, true);
|
return this.fetchRegistryApp(dappReg, id, true);
|
||||||
|
})
|
||||||
|
.then((app) => {
|
||||||
|
this.emit('loaded', app);
|
||||||
|
return app;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,14 +105,6 @@ export default class DappsStore {
|
|||||||
.then(this.writeDisplayApps);
|
.then(this.writeDisplayApps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get (api) {
|
|
||||||
if (!instance) {
|
|
||||||
instance = new DappsStore(api);
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribeToChanges () {
|
subscribeToChanges () {
|
||||||
const { dappReg } = Contracts.get();
|
const { dappReg } = Contracts.get();
|
||||||
|
|
||||||
|
@ -15,15 +15,6 @@
|
|||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.bar, .expanded {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
font-size: 16px;
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
z-index: 10001;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -32,6 +23,15 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
background: rgba(255, 255, 255, 0.5);
|
background: rgba(255, 255, 255, 0.5);
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar, .expanded {
|
||||||
|
position: fixed;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
z-index: 10001;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
@ -39,35 +39,57 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
&.moving {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.parityBg {
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
transition-property: left, top, right, bottom;
|
||||||
|
transition-duration: 0.25s;
|
||||||
|
transition-timing-function: ease;
|
||||||
|
|
||||||
|
&.moving {
|
||||||
|
transition-duration: 0.05s;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.expanded {
|
.expanded {
|
||||||
right: 1em;
|
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: 4px 4px 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: 50vh;
|
max-height: 50vh;
|
||||||
}
|
|
||||||
|
|
||||||
.expanded .content {
|
.content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
background: rgba(0, 0, 0, 0.8);
|
background: rgba(0, 0, 0, 0.8);
|
||||||
min-height: 16em;
|
min-height: 16em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.corner {
|
.corner {
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 1em;
|
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: 4px 4px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cornercolor {
|
.cornercolor {
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
@ -76,12 +98,12 @@
|
|||||||
outline: none !important;
|
outline: none !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
|
||||||
|
|
||||||
.link img, .link svg {
|
img, svg {
|
||||||
height: 24px !important;
|
height: 24px !important;
|
||||||
width: 24px !important;
|
width: 24px !important;
|
||||||
margin: 2px 0.5em 0 0;
|
margin: 2px 0.5em 0 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.link+.link {
|
.link+.link {
|
||||||
@ -123,20 +145,20 @@
|
|||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
background: rgba(0, 0, 0, 0.25);
|
background: rgba(0, 0, 0, 0.25);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header:after {
|
.header, .corner {
|
||||||
clear: both;
|
button {
|
||||||
}
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
.header button,
|
svg {
|
||||||
.corner button {
|
fill: white !important;
|
||||||
color: white !important;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.header svg,
|
|
||||||
.coner svg {
|
|
||||||
fill: white !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
@ -150,12 +172,12 @@
|
|||||||
.actions {
|
.actions {
|
||||||
float: right;
|
float: right;
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
}
|
|
||||||
|
|
||||||
.actions div {
|
div {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.parityIcon, .signerIcon {
|
.parityIcon, .signerIcon {
|
||||||
@ -164,3 +186,34 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.moveIcon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,25 +15,62 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import ActionFingerprint from 'material-ui/svg-icons/action/fingerprint';
|
import { throttle } from 'lodash';
|
||||||
import ContentClear from 'material-ui/svg-icons/content/clear';
|
import store from 'store';
|
||||||
|
|
||||||
|
import { CancelIcon, FingerprintIcon } from '~/ui/Icons';
|
||||||
import { Badge, Button, ContainerTitle, ParityBackground } from '~/ui';
|
import { Badge, Button, ContainerTitle, ParityBackground } from '~/ui';
|
||||||
import { Embedded as Signer } from '../Signer';
|
import { Embedded as Signer } from '../Signer';
|
||||||
|
import DappsStore from '~/views/Dapps/dappsStore';
|
||||||
|
|
||||||
import imagesEthcoreBlock from '../../../assets/images/parity-logo-white-no-text.svg';
|
import imagesEthcoreBlock from '../../../assets/images/parity-logo-white-no-text.svg';
|
||||||
import styles from './parityBar.css';
|
import styles from './parityBar.css';
|
||||||
|
|
||||||
|
const LS_STORE_KEY = '_parity::parityBar';
|
||||||
|
const DEFAULT_POSITION = { right: '1em', bottom: 0 };
|
||||||
|
|
||||||
class ParityBar extends Component {
|
class ParityBar extends Component {
|
||||||
|
app = null;
|
||||||
|
measures = null;
|
||||||
|
moving = false;
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
api: PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
pending: PropTypes.array,
|
dapp: PropTypes.bool,
|
||||||
dapp: PropTypes.bool
|
pending: PropTypes.array
|
||||||
}
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
opened: false
|
moving: false,
|
||||||
|
opened: false,
|
||||||
|
position: DEFAULT_POSITION
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.debouncedMouseMove = throttle(
|
||||||
|
this._onMouseMove,
|
||||||
|
40,
|
||||||
|
{ leading: true, trailing: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount () {
|
||||||
|
const { api } = this.context;
|
||||||
|
|
||||||
|
// Hook to the dapp loaded event to position the
|
||||||
|
// Parity Bar accordingly
|
||||||
|
DappsStore.get(api).on('loaded', (app) => {
|
||||||
|
this.app = app;
|
||||||
|
this.loadPosition();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
@ -52,11 +89,69 @@ class ParityBar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { opened } = this.state;
|
const { moving, opened, position } = this.state;
|
||||||
|
|
||||||
return opened
|
const content = opened
|
||||||
? this.renderExpanded()
|
? this.renderExpanded()
|
||||||
: this.renderBar();
|
: this.renderBar();
|
||||||
|
|
||||||
|
const containerClassNames = opened
|
||||||
|
? [ styles.overlay ]
|
||||||
|
: [ styles.bar ];
|
||||||
|
|
||||||
|
if (!opened && moving) {
|
||||||
|
containerClassNames.push(styles.moving);
|
||||||
|
}
|
||||||
|
|
||||||
|
const parityBgClassName = opened
|
||||||
|
? styles.expanded
|
||||||
|
: styles.corner;
|
||||||
|
|
||||||
|
const parityBgClassNames = [ parityBgClassName, styles.parityBg ];
|
||||||
|
|
||||||
|
if (moving) {
|
||||||
|
parityBgClassNames.push(styles.moving);
|
||||||
|
}
|
||||||
|
|
||||||
|
const parityBgStyle = {
|
||||||
|
...position
|
||||||
|
};
|
||||||
|
|
||||||
|
// Open the Signer at one of the four corners
|
||||||
|
// of the screen
|
||||||
|
if (opened) {
|
||||||
|
// Set at top or bottom of the screen
|
||||||
|
if (position.top !== undefined) {
|
||||||
|
parityBgStyle.top = 0;
|
||||||
|
} else {
|
||||||
|
parityBgStyle.bottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set at left or right of the screen
|
||||||
|
if (position.left !== undefined) {
|
||||||
|
parityBgStyle.left = '1em';
|
||||||
|
} else {
|
||||||
|
parityBgStyle.right = '1em';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={ containerClassNames.join(' ') }
|
||||||
|
onMouseEnter={ this.onMouseEnter }
|
||||||
|
onMouseLeave={ this.onMouseLeave }
|
||||||
|
onMouseMove={ this.onMouseMove }
|
||||||
|
onMouseUp={ this.onMouseUp }
|
||||||
|
>
|
||||||
|
<ParityBackground
|
||||||
|
className={ parityBgClassNames.join(' ') }
|
||||||
|
ref='container'
|
||||||
|
style={ parityBgStyle }
|
||||||
|
>
|
||||||
|
{ content }
|
||||||
|
</ParityBackground>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBar () {
|
renderBar () {
|
||||||
@ -73,49 +168,59 @@ class ParityBar extends Component {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const dragButtonClasses = [ styles.dragButton ];
|
||||||
|
|
||||||
|
if (this.state.moving) {
|
||||||
|
dragButtonClasses.push(styles.moving);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.bar }>
|
<div className={ styles.cornercolor }>
|
||||||
<ParityBackground className={ styles.corner }>
|
<Link to='/apps'>
|
||||||
<div className={ styles.cornercolor }>
|
<Button
|
||||||
<Link to='/apps'>
|
className={ styles.parityButton }
|
||||||
<Button
|
icon={ parityIcon }
|
||||||
className={ styles.parityButton }
|
label={ this.renderLabel('Parity') }
|
||||||
icon={ parityIcon }
|
/>
|
||||||
label={ this.renderLabel('Parity') }
|
</Link>
|
||||||
/>
|
<Button
|
||||||
</Link>
|
className={ styles.button }
|
||||||
<Button
|
icon={ <FingerprintIcon /> }
|
||||||
className={ styles.button }
|
label={ this.renderSignerLabel() }
|
||||||
icon={ <ActionFingerprint /> }
|
onClick={ this.toggleDisplay }
|
||||||
label={ this.renderSignerLabel() }
|
/>
|
||||||
onClick={ this.toggleDisplay }
|
|
||||||
/>
|
<div
|
||||||
</div>
|
className={ styles.moveIcon }
|
||||||
</ParityBackground>
|
onMouseDown={ this.onMouseDown }
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={ dragButtonClasses.join(' ') }
|
||||||
|
ref='dragButton'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderExpanded () {
|
renderExpanded () {
|
||||||
return (
|
return (
|
||||||
<div className={ styles.overlay }>
|
<div>
|
||||||
<ParityBackground className={ styles.expanded }>
|
<div className={ styles.header }>
|
||||||
<div className={ styles.header }>
|
<div className={ styles.title }>
|
||||||
<div className={ styles.title }>
|
<ContainerTitle title='Parity Signer: Pending' />
|
||||||
<ContainerTitle title='Parity Signer: Pending' />
|
|
||||||
</div>
|
|
||||||
<div className={ styles.actions }>
|
|
||||||
<Button
|
|
||||||
icon={ <ContentClear /> }
|
|
||||||
label='Close'
|
|
||||||
onClick={ this.toggleDisplay }
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.content }>
|
<div className={ styles.actions }>
|
||||||
<Signer />
|
<Button
|
||||||
|
icon={ <CancelIcon /> }
|
||||||
|
label='Close'
|
||||||
|
onClick={ this.toggleDisplay }
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ParityBackground>
|
</div>
|
||||||
|
<div className={ styles.content }>
|
||||||
|
<Signer />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -148,6 +253,178 @@ class ParityBar extends Component {
|
|||||||
return this.renderLabel('Signer', bubble);
|
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 containerElt = ReactDOM.findDOMNode(this.refs.container);
|
||||||
|
const dragButtonElt = ReactDOM.findDOMNode(this.refs.dragButton);
|
||||||
|
|
||||||
|
if (!containerElt || !dragButtonElt) {
|
||||||
|
console.warn(containerElt ? 'drag button' : 'container', 'not found...');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 container = {
|
||||||
|
height: containerRect.height,
|
||||||
|
width: containerRect.width
|
||||||
|
};
|
||||||
|
|
||||||
|
const page = {
|
||||||
|
height: bodyRect.height,
|
||||||
|
width: bodyRect.width
|
||||||
|
};
|
||||||
|
|
||||||
|
this.moving = true;
|
||||||
|
this.measures = {
|
||||||
|
button,
|
||||||
|
container,
|
||||||
|
page
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setState({ moving: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseEnter = (event) => {
|
||||||
|
if (!this.moving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { buttons } = event;
|
||||||
|
|
||||||
|
// If no left-click, stop move
|
||||||
|
if (buttons !== 1) {
|
||||||
|
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 });
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onMouseMove = (event) => {
|
||||||
|
if (!this.moving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { pageX, pageY } = event;
|
||||||
|
const position = this.getPosition(pageX, pageY);
|
||||||
|
this.setState({ position });
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseUp = (event) => {
|
||||||
|
if (!this.moving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { pageX, pageY } = event;
|
||||||
|
const position = this.getPosition(pageX, pageY);
|
||||||
|
|
||||||
|
// Stick to bottom or top
|
||||||
|
if (position.top !== undefined) {
|
||||||
|
position.top = 0;
|
||||||
|
} else {
|
||||||
|
position.bottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stick to bottom or top
|
||||||
|
if (position.left !== undefined) {
|
||||||
|
position.left = '1em';
|
||||||
|
} else {
|
||||||
|
position.right = '1em';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moving = false;
|
||||||
|
this.setState({ moving: false, position });
|
||||||
|
this.savePosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
toggleDisplay = () => {
|
toggleDisplay = () => {
|
||||||
const { opened } = this.state;
|
const { opened } = this.state;
|
||||||
|
|
||||||
@ -155,6 +432,57 @@ class ParityBar extends Component {
|
|||||||
opened: !opened
|
opened: !opened
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get config () {
|
||||||
|
let config;
|
||||||
|
|
||||||
|
try {
|
||||||
|
config = JSON.parse(store.get(LS_STORE_KEY));
|
||||||
|
} catch (error) {
|
||||||
|
config = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPosition (props = this.props) {
|
||||||
|
const { app, config } = this;
|
||||||
|
|
||||||
|
if (!app) {
|
||||||
|
return this.setState({ position: DEFAULT_POSITION });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config[app.id]) {
|
||||||
|
return this.setState({ position: config[app.id] });
|
||||||
|
}
|
||||||
|
|
||||||
|
const position = this.stringToPosition(app.position);
|
||||||
|
this.setState({ position });
|
||||||
|
}
|
||||||
|
|
||||||
|
savePosition (position) {
|
||||||
|
const { app, config } = this;
|
||||||
|
config[app.id] = position;
|
||||||
|
|
||||||
|
store.set(LS_STORE_KEY, JSON.stringify(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
stringToPosition (value) {
|
||||||
|
switch (value) {
|
||||||
|
case 'top-left':
|
||||||
|
return { top: 0, left: '1em' };
|
||||||
|
|
||||||
|
case 'top-right':
|
||||||
|
return { top: 0, right: '1em' };
|
||||||
|
|
||||||
|
case 'bottom-left':
|
||||||
|
return { bottom: 0, left: '1em' };
|
||||||
|
|
||||||
|
case 'bottom-right':
|
||||||
|
default:
|
||||||
|
return DEFAULT_POSITION;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
Loading…
Reference in New Issue
Block a user