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

Refresh UI on nodeKind changes, e.g. personal -> public #5312

Merged
merged 13 commits into from
Apr 20, 2017
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really follow why a reload does not happen if current chain is a default chain? (I know the logic here didn't change, just curious).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is slightly wrongly named. On startup we don't know the chain, so we set it to DEFAULT_CHAIN (DEFAULT_CHAIN = '(unknown)'). So when the value changes from this, we don't do the reload, but on any subsequent changes, we do.

}

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