Default account selection update (#4609)

* Default accounts setting - account provider

* RPC support for default accounts

* Updating JS code

* Rename whitelist to addresses

* Set the defaults using default, allowing for null/full lists

* Update failing tests (after merge)

* Fix merge with wrong rpc call names

* One account needs to be selected
This commit is contained in:
Jaco Greeff 2017-02-22 10:43:02 +01:00 committed by Gav Wood
parent 0a85fc7a3e
commit 5337bf6413
5 changed files with 53 additions and 42 deletions

View File

@ -20,6 +20,7 @@ export default class Store {
@observable accounts = []; @observable accounts = [];
@observable modalOpen = false; @observable modalOpen = false;
@observable whitelist = []; @observable whitelist = [];
@observable whitelistDefault = null;
constructor (api) { constructor (api) {
this._api = api; this._api = api;
@ -29,17 +30,14 @@ export default class Store {
@action closeModal = () => { @action closeModal = () => {
transaction(() => { transaction(() => {
let addresses = null;
const checkedAccounts = this.accounts.filter((account) => account.checked); const checkedAccounts = this.accounts.filter((account) => account.checked);
const defaultAddress = (this.accounts.find((account) => account.default) || {}).address;
if (checkedAccounts.length) { const addresses = checkedAccounts.length === this.accounts.length
addresses = checkedAccounts.filter((account) => account.default) ? null
.concat(checkedAccounts.filter((account) => !account.default)) : checkedAccounts.map((account) => account.address);
.map((account) => account.address);
}
this.modalOpen = false; this.modalOpen = false;
this.updateWhitelist(addresses); this.updateWhitelist(addresses, defaultAddress);
}); });
} }
@ -53,8 +51,8 @@ export default class Store {
checked: this.whitelist checked: this.whitelist
? this.whitelist.includes(account.address) ? this.whitelist.includes(account.address)
: true, : true,
default: this.whitelist default: this.whitelistDefault
? this.whitelist[0] === account.address ? this.whitelistDefault === account.address
: index === 0, : index === 0,
description: account.meta.description, description: account.meta.description,
name: account.name name: account.name
@ -66,8 +64,10 @@ export default class Store {
@action selectAccount = (address) => { @action selectAccount = (address) => {
transaction(() => { transaction(() => {
const isSingleAccount = this.accounts.filter((account) => account.checked).length === 1;
this.accounts = this.accounts.map((account) => { this.accounts = this.accounts.map((account) => {
if (account.address === address) { if (account.address === address && (!isSingleAccount || !account.checked)) {
account.checked = !account.checked; account.checked = !account.checked;
account.default = false; account.default = false;
} }
@ -96,26 +96,35 @@ export default class Store {
}); });
} }
@action setWhitelist = (whitelist) => { @action setWhitelist = (whitelist, whitelistDefault) => {
this.whitelist = whitelist; transaction(() => {
this.whitelist = whitelist;
this.whitelistDefault = whitelistDefault;
});
} }
loadWhitelist () { loadWhitelist () {
return this._api.parity return Promise
.getNewDappsAddresses() .all([
.then((whitelist) => { this._api.parity.getNewDappsAddresses(),
this.setWhitelist(whitelist); this._api.parity.getNewDappsDefaultAddress()
])
.then(([whitelist, whitelistDefault]) => {
this.setWhitelist(whitelist, whitelistDefault);
}) })
.catch((error) => { .catch((error) => {
console.warn('loadWhitelist', error); console.warn('loadWhitelist', error);
}); });
} }
updateWhitelist (whitelist) { updateWhitelist (whitelist, whitelistDefault = null) {
return this._api.parity return Promise
.setNewDappsAddresses(whitelist) .all([
this._api.parity.setNewDappsAddresses(whitelist),
this._api.parity.setNewDappsDefaultAddress(whitelistDefault)
])
.then(() => { .then(() => {
this.setWhitelist(whitelist); this.setWhitelist(whitelist, whitelistDefault);
}) })
.catch((error) => { .catch((error) => {
console.warn('updateWhitelist', error); console.warn('updateWhitelist', error);

View File

@ -32,14 +32,16 @@ function create () {
api = { api = {
parity: { parity: {
getNewDappsAddresses: sinon.stub().resolves(WHITELIST), getNewDappsAddresses: sinon.stub().resolves(WHITELIST),
setNewDappsAddresses: sinon.stub().resolves(true) getNewDappsDefaultAddress: sinon.stub().resolves(WHITELIST[0]),
setNewDappsAddresses: sinon.stub().resolves(true),
setNewDappsDefaultAddress: sinon.stub().resolves(true)
} }
}; };
store = new Store(api); store = new Store(api);
} }
describe('modals/DappPermissions/store', () => { describe.only('modals/DappPermissions/store', () => {
beforeEach(() => { beforeEach(() => {
create(); create();
}); });
@ -80,11 +82,11 @@ describe('modals/DappPermissions/store', () => {
}); });
it('calls setNewDappsAddresses', () => { it('calls setNewDappsAddresses', () => {
expect(api.parity.setNewDappsAddresses).to.have.been.calledOnce; expect(api.parity.setNewDappsAddresses).to.have.been.calledWith(['456', '789']);
}); });
it('has the default account in first position', () => { it('calls into setNewDappsDefaultAddress', () => {
expect(api.parity.setNewDappsAddresses).to.have.been.calledWith(['789', '456']); expect(api.parity.setNewDappsDefaultAddress).to.have.been.calledWith('789');
}); });
}); });
@ -107,6 +109,14 @@ describe('modals/DappPermissions/store', () => {
expect(store.accounts.find((account) => account.address === '456').default).to.be.false; expect(store.accounts.find((account) => account.address === '456').default).to.be.false;
expect(store.accounts.find((account) => account.address === '123').default).to.be.true; expect(store.accounts.find((account) => account.address === '123').default).to.be.true;
}); });
it('does not deselect the last account', () => {
store.selectAccount('123');
store.selectAccount('456');
console.log(store.accounts.map((account) => ({ address: account.address, checked: account.checked })));
expect(store.accounts.find((account) => account.address === '456').default).to.be.true;
expect(store.accounts.find((account) => account.address === '456').checked).to.be.true;
});
}); });
describe('setDefaultAccount', () => { describe('setDefaultAccount', () => {

View File

@ -50,18 +50,11 @@ export default class AccountStore {
this.isLoading = isLoading; this.isLoading = isLoading;
} }
makeDefaultAccount = (address) => { makeDefaultAccount = (defaultAddress) => {
const accounts = [address].concat( this.setDefaultAccount(defaultAddress);
this.accounts
.filter((account) => account.address !== address)
.map((account) => account.address)
);
// Have optimistic UI: https://www.smashingmagazine.com/2016/11/true-lies-of-optimistic-user-interfaces/?utm_source=codropscollective
this.setDefaultAccount(address);
return this._api.parity return this._api.parity
.setNewDappsAddresses(accounts) .setNewDappsDefaultAddress(defaultAddress)
.catch((error) => { .catch((error) => {
console.warn('makeDefaultAccount', error); console.warn('makeDefaultAccount', error);
}); });

View File

@ -18,7 +18,7 @@ import sinon from 'sinon';
import AccountStore from './accountStore'; import AccountStore from './accountStore';
import { ACCOUNT_DEFAULT, ACCOUNT_FIRST, ACCOUNT_NEW, createApi } from './parityBar.test.js'; import { ACCOUNT_DEFAULT, ACCOUNT_NEW, createApi } from './parityBar.test.js';
let api; let api;
let store; let store;
@ -104,10 +104,8 @@ describe('views/ParityBar/AccountStore', () => {
return store.makeDefaultAccount(ACCOUNT_NEW); return store.makeDefaultAccount(ACCOUNT_NEW);
}); });
it('calls into parity_setNewDappsAddresses (with ordering)', () => { it('calls into parity_setNewDappsDefaultAddress', () => {
expect(api.parity.setNewDappsAddresses).to.have.been.calledWith([ expect(api.parity.setNewDappsDefaultAddress).to.have.been.calledWith(ACCOUNT_NEW);
ACCOUNT_NEW, ACCOUNT_FIRST, ACCOUNT_DEFAULT
]);
}); });
}); });
}); });

View File

@ -37,7 +37,8 @@ function createApi () {
defaultAccount: sinon.stub().resolves(ACCOUNT_DEFAULT), defaultAccount: sinon.stub().resolves(ACCOUNT_DEFAULT),
allAccountsInfo: sinon.stub().resolves(ACCOUNTS), allAccountsInfo: sinon.stub().resolves(ACCOUNTS),
getNewDappsAddresses: sinon.stub().resolves(null), getNewDappsAddresses: sinon.stub().resolves(null),
setNewDappsAddresses: sinon.stub().resolves(true) setNewDappsAddresses: sinon.stub().resolves(true),
setNewDappsDefaultAddress: sinon.stub().resolves(true)
} }
}; };