Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Refresh UI on nodeKind changes, e.g. personal -> public (#5312)
Browse files Browse the repository at this point in the history
* Poll details based on nodeKind

* Delay long polling when public/light

* Reload UI when nodeKind changed

* Fix tests (not using dispatch, reload instead)

* PR grumbles/cleanups
  • Loading branch information
jacogr authored Apr 20, 2017
1 parent ee25249 commit ba03ed4
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 34 deletions.
34 changes: 23 additions & 11 deletions js/src/redux/providers/chainMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import BalancesProvider from './balances';
import { showSnackbar } from './snackbarActions';
import { DEFAULT_NETCHAIN } from './statusReducer';

export default class ChainMiddleware {
Expand All @@ -24,20 +22,34 @@ export default class ChainMiddleware {
if (action.type === 'statusCollection') {
const { collection } = action;

if (collection && collection.netChain) {
const newChain = collection.netChain;
if (collection) {
const { nodeStatus } = store.getState();
const { netChain, nodeKind } = nodeStatus;
const newChain = collection.netChain;
const newNodeKind = collection.nodeKind;
let reloadChain = false;
let reloadType = false;

// force reload when chain has changed and is not initial value
if (newChain) {
const hasChainChanged = newChain !== netChain;
const isInitialChain = netChain === DEFAULT_NETCHAIN;

reloadChain = !isInitialChain && hasChainChanged;
}

if (newChain !== nodeStatus.netChain && nodeStatus.netChain !== DEFAULT_NETCHAIN) {
store.dispatch(showSnackbar(`Switched to ${newChain}. The UI will reload now...`));
// force reload when nodeKind (availability or capability) has changed
if (newNodeKind && nodeKind) {
const hasAvailabilityChanged = nodeKind.availability !== newNodeKind.availability;
const hasCapabilityChanged = nodeKind.capability !== newNodeKind.capability;

reloadType = hasAvailabilityChanged || hasCapabilityChanged;
}

if (reloadChain || reloadType) {
setTimeout(() => {
window.location.reload();
}, 0);

// Fetch the new balances without notifying the user of any change
BalancesProvider.get(store).fetchAllBalances({
changedNetwork: true
});
}
}
}
Expand Down
37 changes: 30 additions & 7 deletions js/src/redux/providers/chainMiddleware.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,22 @@ import { createWsApi } from '~/../test/e2e/ethapi';
let middleware;
let next;
let store;
let clock;

const api = createWsApi();

Contracts.create(api);

function stubGlobals () {
clock = sinon.useFakeTimers();
sinon.spy(window.location, 'reload');
}

function restoreGlobals () {
window.location.reload.restore();
clock.restore();
}

function createMiddleware (collection = {}) {
middleware = new ChainMiddleware().toMiddleware();
next = sinon.stub();
Expand All @@ -46,10 +57,22 @@ function createMiddleware (collection = {}) {
}

function callMiddleware (action) {
return middleware(store)(next)(action);
const result = middleware(store)(next)(action);

clock.tick(100);

return result;
}

describe('reduxs/providers/ChainMiddleware', () => {
beforeEach(() => {
stubGlobals();
});

afterEach(() => {
restoreGlobals();
});

describe('next action', () => {
beforeEach(() => {
createMiddleware();
Expand All @@ -69,25 +92,25 @@ describe('reduxs/providers/ChainMiddleware', () => {
});

describe('chain switching', () => {
it('does not dispatch when moving from the initial/unknown chain', () => {
it('does not reload when moving from the initial/unknown chain', () => {
createMiddleware();
callMiddleware({ type: 'statusCollection', collection: { netChain: 'homestead' } });

expect(store.dispatch).not.to.have.been.called;
expect(window.location.reload).not.to.have.been.called;
});

it('does not dispatch when moving to the same chain', () => {
it('does not reload when moving to the same chain', () => {
createMiddleware({ netChain: 'homestead' });
callMiddleware({ type: 'statusCollection', collection: { netChain: 'homestead' } });

expect(store.dispatch).not.to.have.been.called;
expect(window.location.reload).not.to.have.been.called;
});

it('does dispatch when moving between chains', () => {
it('does reload when moving between chains', () => {
createMiddleware({ netChain: 'homestead' });
callMiddleware({ type: 'statusCollection', collection: { netChain: 'ropsten' } });

expect(store.dispatch).to.have.been.called;
expect(window.location.reload).to.have.been.called;
});
});
});
47 changes: 31 additions & 16 deletions js/src/redux/providers/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ export default class Status {
}

_pollTraceMode = () => {
return this._api.trace.block()
return this._api.trace
.block()
.then(blockTraces => {
// Assumes not in Trace Mode if no transactions
// in latest block...
Expand All @@ -168,14 +169,12 @@ export default class Status {
getApiStatus = () => {
const { isConnected, isConnecting, needsToken, secureToken } = this._api;

const apiStatus = {
return {
isConnected,
isConnecting,
needsToken,
secureToken
};

return apiStatus;
}

_pollStatus = () => {
Expand All @@ -194,7 +193,10 @@ export default class Status {
return Promise.resolve();
}

const statusPromises = [ this._api.eth.syncing(), this._api.parity.netPeers() ];
const statusPromises = [
this._api.eth.syncing(),
this._api.parity.netPeers()
];

return Promise
.all(statusPromises)
Expand Down Expand Up @@ -225,32 +227,45 @@ export default class Status {
return Promise.resolve();
}

const nextTimeout = (timeout = 30000) => {
const { nodeKindFull } = this._store.getState().nodeStatus;
const defaultTimeout = (nodeKindFull === false ? 240 : 30) * 1000;

const nextTimeout = (timeout = defaultTimeout) => {
if (this._timeoutIds.longStatus) {
clearTimeout(this._timeoutIds.longStatus);
}

this._timeoutIds.longStatus = setTimeout(() => this._pollLongStatus(), timeout);
};

const statusPromises = [
this._api.parity.nodeKind(),
this._api.parity.netPeers(),
this._api.web3.clientVersion(),
this._api.net.version(),
this._api.parity.netChain()
];

if (nodeKindFull) {
statusPromises.push(this._upgradeStore.checkUpgrade());
}

return Promise
.all([
this._api.parity.netPeers(),
this._api.web3.clientVersion(),
this._api.net.version(),
this._api.parity.netChain(),
this._upgradeStore.checkUpgrade()
])
.then(([
netPeers, clientVersion, netVersion, netChain, upgradeStatus
]) => {
.all(statusPromises)
.then(([nodeKind, netPeers, clientVersion, netVersion, netChain]) => {
const isTest = [
'2', // morden
'3', // ropsten
'42' // kovan
].includes(netVersion);

const nodeKindFull = nodeKind &&
nodeKind.availability === 'personal' &&
nodeKind.capability === 'full';

const longStatus = {
nodeKind,
nodeKindFull,
netPeers,
clientVersion,
netChain,
Expand Down
2 changes: 2 additions & 0 deletions js/src/redux/providers/statusReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const initialState = {
peers: []
},
netVersion: '0',
nodeKind: null,
nodeKindFull: null,
syncing: true,
isConnected: false,
isConnecting: false,
Expand Down

0 comments on commit ba03ed4

Please sign in to comment.