diff --git a/js/src/redux/providers/balances.js b/js/src/redux/providers/balances.js index cc7df73dd..a2f49cfa8 100644 --- a/js/src/redux/providers/balances.js +++ b/js/src/redux/providers/balances.js @@ -241,7 +241,7 @@ export default class Balances { // If syncing, only retrieve balances once every // few seconds - if (syncing) { + if (syncing || syncing === null) { this.shortThrottledFetch.cancel(); this.longThrottledFetch(skipNotifications); diff --git a/js/src/redux/providers/statusReducer.js b/js/src/redux/providers/statusReducer.js index 12fe9654d..3a6968548 100644 --- a/js/src/redux/providers/statusReducer.js +++ b/js/src/redux/providers/statusReducer.js @@ -33,7 +33,7 @@ const initialState = { netVersion: '0', nodeKind: null, nodeKindFull: null, - syncing: true, + syncing: null, isConnected: false, isConnecting: false, isTest: undefined, diff --git a/js/src/views/Application/application.js b/js/src/views/Application/application.js index 2fac18c6f..73f0cdda8 100644 --- a/js/src/views/Application/application.js +++ b/js/src/views/Application/application.js @@ -22,6 +22,7 @@ import UpgradeStore from '~/modals/UpgradeParity/store'; import Connection from '../Connection'; import ParityBar from '../ParityBar'; +import SyncWarning, { showSyncWarning } from '../SyncWarning'; import Snackbar from './Snackbar'; import Container from './Container'; @@ -36,6 +37,7 @@ import Requests from './Requests'; import styles from './application.css'; const inFrame = window.parent !== window && window.parent.frames.length !== 0; +const doShowSyncWarning = showSyncWarning(); @observer class Application extends Component { @@ -78,6 +80,11 @@ class Application extends Component { ? this.renderMinimized() : this.renderApp() } + { + doShowSyncWarning + ? () + : null + } diff --git a/js/src/views/SyncWarning/index.js b/js/src/views/SyncWarning/index.js new file mode 100644 index 000000000..098605b2a --- /dev/null +++ b/js/src/views/SyncWarning/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default, { showSyncWarning } from './syncWarning'; diff --git a/js/src/views/SyncWarning/syncWarning.css b/js/src/views/SyncWarning/syncWarning.css new file mode 100644 index 000000000..828036499 --- /dev/null +++ b/js/src/views/SyncWarning/syncWarning.css @@ -0,0 +1,60 @@ +/* Copyright 2015-2017 Parity Technologies (UK) Ltd. +/* This file is part of Parity. +/* +/* Parity is free software: you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published by +/* the Free Software Foundation; either version 3 of the License; or +/* (at your option) any later version. +/* +/* Parity is distributed in the hope that it will be useful; +/* but WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with Parity. If not; see . +*/ + +.overlay { + background: rgba(255, 255, 255, 0.75); + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 10000; +} + +.modal { + align-items: flex-start; + bottom: 0; + display: flex; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 10001; +} + +.body { + background: rgba(25, 25, 25, 0.75); + box-shadow: rgba(0, 0, 0, 0.25) 0 14px 45px, rgba(0, 0, 0, 0.22) 0 10px 18px; + color: rgb(208, 208, 208); + display: flex; + flex-direction: column; + margin: 0 auto; + max-width: 20em; + padding: 2em 4em; + text-align: center; +} + +.button { + margin-top: 1em; +} + +.body, +.button { + > * { + margin: 0.5em 0; + } +} diff --git a/js/src/views/SyncWarning/syncWarning.js b/js/src/views/SyncWarning/syncWarning.js new file mode 100644 index 000000000..67deff075 --- /dev/null +++ b/js/src/views/SyncWarning/syncWarning.js @@ -0,0 +1,130 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { Checkbox } from 'material-ui'; +import React, { Component, PropTypes } from 'react'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import store from 'store'; + +import { Button } from '~/ui'; + +import styles from './syncWarning.css'; + +const LS_DONT_SHOW_AGAIN = '_parity::syncWarning::dontShowAgain'; + +export const showSyncWarning = () => { + const dontShowAgain = store.get(LS_DONT_SHOW_AGAIN); + + if (dontShowAgain === undefined || dontShowAgain === null) { + return true; + } + + return !dontShowAgain; +}; + +class SyncWarning extends Component { + static propTypes = { + isSyncing: PropTypes.bool + }; + + state = { + dontShowAgain: false, + show: true + }; + + render () { + const { isSyncing } = this.props; + const { dontShowAgain, show } = this.state; + + if (!isSyncing || isSyncing === null || !show) { + return null; + } + + return ( +
+
+
+
+ + + +
+ + } + checked={ dontShowAgain } + onCheck={ this.handleCheck } + /> +
+
+
+
+ ); + } + + handleCheck = () => { + this.setState({ dontShowAgain: !this.state.dontShowAgain }); + } + + handleAgreeClick = () => { + if (this.state.dontShowAgain) { + store.set(LS_DONT_SHOW_AGAIN, true); + } + + this.setState({ show: false }); + } +} + +function mapStateToProps (state) { + const { syncing } = state.nodeStatus; + // syncing could be an Object, false, or null + const isSyncing = syncing + ? true + : syncing; + + return { + isSyncing + }; +} + +export default connect( + mapStateToProps, + null +)(SyncWarning); diff --git a/js/src/views/SyncWarning/syncWarning.spec.js b/js/src/views/SyncWarning/syncWarning.spec.js new file mode 100644 index 000000000..36c3c2436 --- /dev/null +++ b/js/src/views/SyncWarning/syncWarning.spec.js @@ -0,0 +1,57 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { shallow } from 'enzyme'; +import React from 'react'; + +import SyncWarning from './'; + +let component; + +function createRedux (syncing = null) { + return { + getState: () => { + return { + nodeStatus: { + syncing + } + }; + } + }; +} + +function render (store) { + component = shallow( + , + { context: { store: store || createRedux() } } + ).find('SyncWarning').shallow(); + + return component; +} + +describe('views/SyncWarning', () => { + it('renders defaults', () => { + expect(render()).to.be.ok; + }); + + it('does render when syncing', () => { + expect(render(createRedux({})).find('div')).to.have.length.gte(1); + }); + + it('does not render when not syncing', () => { + expect(render(createRedux(false)).find('div')).to.have.length(0); + }); +});