From fa2e050e5c4f40d9cd3212b6b5f4a66c5beb1f15 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 18 Jun 2018 18:23:23 +0200 Subject: [PATCH 1/5] Add smoother transition when switching accounts (fix #37) --- packages/light-react/package.json | 2 +- .../src/Accounts/AccountsList/AccountsList.js | 27 ++++++++++++++++--- .../TokensList/TokenBalance/TokenBalance.js | 3 ++- .../src/Tokens/TokensList/TokensList.js | 4 +-- .../light-react/src/stores/tokensStore.js | 5 ++++ yarn.lock | 4 +-- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/packages/light-react/package.json b/packages/light-react/package.json index e927674b..81bcf63c 100644 --- a/packages/light-react/package.json +++ b/packages/light-react/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@parity/api": "^2.1.22", - "@parity/light.js": "https://github.com/parity-js/light.js#165a97deb86d7b77a96b324b7d42d04a27a43b0b", + "@parity/light.js": "https://github.com/parity-js/light.js#71bd8077a06ec2fe544650fdde56555d1921c0d4", "@parity/shared": "^3.0.2", "is-electron": "^2.1.0", "light-hoc": "^0.1.0", diff --git a/packages/light-react/src/Accounts/AccountsList/AccountsList.js b/packages/light-react/src/Accounts/AccountsList/AccountsList.js index b518fe39..a5983080 100644 --- a/packages/light-react/src/Accounts/AccountsList/AccountsList.js +++ b/packages/light-react/src/Accounts/AccountsList/AccountsList.js @@ -5,14 +5,15 @@ import React, { Component } from 'react'; import { AccountCard, Header } from 'light-ui'; -import { accountsInfo$ } from '@parity/light.js'; +import { accountsInfo$, defaultAccount$ } from '@parity/light.js'; import { inject, observer } from 'mobx-react'; import light from 'light-hoc'; import Health from '../../Health'; @light({ - accountsInfo: accountsInfo$ + accountsInfo: accountsInfo$, + defaultAccount: defaultAccount$ }) @inject('createAccountStore', 'parityStore') @observer @@ -23,16 +24,34 @@ class AccountsList extends Component { } }) => { const { + defaultAccount, history, parityStore: { api } } = this.props; + + // If we selected the same account, just go back to the tokens page + if (address === defaultAccount) { + history.push('/tokens'); + return; + } + + // We set the defaultAccount temporarily to null. The next + // `setNewDappsDefaultAddress` will change it back to the correct default + // account. The reason we do this is to show a loading state for + // defaultAccount. + defaultAccount$().next(null); + // Set default account to the clicked one, and go to Tokens on complete // TODO Not 100% clean, I don't want any api.abc.method() in any React // component. api.parity .setNewDappsDefaultAddress(address) - .then(() => history.push('/tokens')) - .catch(() => {}); // TODO do what? + .then(() => { + history.push('/tokens'); + }) + .catch(err => + console.error(`Error while selecting account, ${err.message}.`) + ); }; handleCreateAccount = () => { diff --git a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js index c5b8bc69..f507940c 100644 --- a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js +++ b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js @@ -6,10 +6,10 @@ import React, { Component } from 'react'; import abi from '@parity/shared/lib/contracts/abi/eip20'; import { defaultAccount$, makeContract$, myBalance$ } from '@parity/light.js'; +import { filter, map, switchMap } from 'rxjs/operators'; import { fromWei } from '@parity/api/lib/util/wei'; import { inject } from 'mobx-react'; import light from 'light-hoc'; -import { map, switchMap } from 'rxjs/operators'; import PropTypes from 'prop-types'; import { TokenCard } from 'light-ui'; import { withRouter } from 'react-router-dom'; @@ -19,6 +19,7 @@ import { withRouter } from 'react-router-dom'; address === 'ETH' ? myBalance$().pipe(map(value => +fromWei(value))) : defaultAccount$().pipe( + filter(x => x), switchMap(defaultAccount => makeContract$(address, abi).balanceOf$(defaultAccount) ), diff --git a/packages/light-react/src/Tokens/TokensList/TokensList.js b/packages/light-react/src/Tokens/TokensList/TokensList.js index f9718a18..a431b498 100644 --- a/packages/light-react/src/Tokens/TokensList/TokensList.js +++ b/packages/light-react/src/Tokens/TokensList/TokensList.js @@ -16,8 +16,8 @@ class Tokens extends Component { tokensStore: { tokensArray } } = this.props; - // Show empty 3 tokens placeholders if tokens have not been loaded yet - const shownArray = tokensArray.length ? tokensArray : Array(3).fill({}); + // Show empty token placeholder if tokens have not been loaded yet + const shownArray = tokensArray.length ? tokensArray : [{}]; return (
diff --git a/packages/light-react/src/stores/tokensStore.js b/packages/light-react/src/stores/tokensStore.js index c9d9c8b9..4e3fd242 100644 --- a/packages/light-react/src/stores/tokensStore.js +++ b/packages/light-react/src/stores/tokensStore.js @@ -33,6 +33,11 @@ class TokensStore { @action fetchTokensFromDb = async (chainName, defaultAccount) => { + if (!defaultAccount || !chainName) { + this.tokens = {}; + return; + } + // Set the localStorage key, we have one key per chain per account, in this // format: __paritylight::tokens::0x123::kovan this.lsKey = `${LS_KEY}::${defaultAccount}::${chainName}`; diff --git a/yarn.lock b/yarn.lock index 7f3d271a..a048b76a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -976,9 +976,9 @@ u2f-api "0.0.9" u2f-api-polyfill "0.4.3" -"@parity/light.js@https://github.com/parity-js/light.js#165a97deb86d7b77a96b324b7d42d04a27a43b0b": +"@parity/light.js@https://github.com/parity-js/light.js#71bd8077a06ec2fe544650fdde56555d1921c0d4": version "1.0.0" - resolved "https://github.com/parity-js/light.js#165a97deb86d7b77a96b324b7d42d04a27a43b0b" + resolved "https://github.com/parity-js/light.js#71bd8077a06ec2fe544650fdde56555d1921c0d4" dependencies: "@babel/runtime" "^7.0.0-beta.49" "@parity/api" "^2.1.23" -- GitLab From 8fb366206fe5486d1e2f3b534bf0990f9c2d0559 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Mon, 18 Jun 2018 18:38:19 +0200 Subject: [PATCH 2/5] Use address in location state for faster access --- .../src/Accounts/AccountsList/AccountsList.js | 2 +- packages/light-react/src/Tokens/Tokens.js | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/light-react/src/Accounts/AccountsList/AccountsList.js b/packages/light-react/src/Accounts/AccountsList/AccountsList.js index a5983080..164187e7 100644 --- a/packages/light-react/src/Accounts/AccountsList/AccountsList.js +++ b/packages/light-react/src/Accounts/AccountsList/AccountsList.js @@ -47,7 +47,7 @@ class AccountsList extends Component { api.parity .setNewDappsDefaultAddress(address) .then(() => { - history.push('/tokens'); + history.push('/tokens', { address }); }) .catch(err => console.error(`Error while selecting account, ${err.message}.`) diff --git a/packages/light-react/src/Tokens/Tokens.js b/packages/light-react/src/Tokens/Tokens.js index 31f9d177..52ff2bce 100644 --- a/packages/light-react/src/Tokens/Tokens.js +++ b/packages/light-react/src/Tokens/Tokens.js @@ -18,18 +18,27 @@ import TokensList from './TokensList'; }) class Tokens extends PureComponent { render () { - const { accountsInfo, defaultAccount } = this.props; + const { + accountsInfo, + defaultAccount, + location: { state } + } = this.props; + + // The address is defaultAccount, but if we are coming from the accounts + // page, then the address is also put inside the route state, for faster + // access. + const myAddress = (state && state.address) || defaultAccount; return (
-- GitLab From 906bc19c83290c054edc6167334ee199e5f4b75d Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 20 Jun 2018 11:53:06 +0200 Subject: [PATCH 3/5] Use latest version of light.js --- packages/light-react/package.json | 2 +- .../src/Accounts/AccountsList/AccountsList.js | 16 +++++++++------- .../TokensList/TokenBalance/TokenBalance.js | 15 ++++++++++++--- yarn.lock | 9 +++++++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/packages/light-react/package.json b/packages/light-react/package.json index 81bcf63c..54b6b94f 100644 --- a/packages/light-react/package.json +++ b/packages/light-react/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@parity/api": "^2.1.22", - "@parity/light.js": "https://github.com/parity-js/light.js#71bd8077a06ec2fe544650fdde56555d1921c0d4", + "@parity/light.js": "https://github.com/parity-js/light.js#9646ce15d9dd9c4cf11776ddd613d5bd86016f94", "@parity/shared": "^3.0.2", "is-electron": "^2.1.0", "light-hoc": "^0.1.0", diff --git a/packages/light-react/src/Accounts/AccountsList/AccountsList.js b/packages/light-react/src/Accounts/AccountsList/AccountsList.js index 164187e7..6e202719 100644 --- a/packages/light-react/src/Accounts/AccountsList/AccountsList.js +++ b/packages/light-react/src/Accounts/AccountsList/AccountsList.js @@ -15,7 +15,7 @@ import Health from '../../Health'; accountsInfo: accountsInfo$, defaultAccount: defaultAccount$ }) -@inject('createAccountStore', 'parityStore') +@inject('createAccountStore', 'parityStore', 'tokensStore') @observer class AccountsList extends Component { handleClick = ({ @@ -26,7 +26,8 @@ class AccountsList extends Component { const { defaultAccount, history, - parityStore: { api } + parityStore: { api }, + tokensStore } = this.props; // If we selected the same account, just go back to the tokens page @@ -35,11 +36,12 @@ class AccountsList extends Component { return; } - // We set the defaultAccount temporarily to null. The next - // `setNewDappsDefaultAddress` will change it back to the correct default - // account. The reason we do this is to show a loading state for - // defaultAccount. - defaultAccount$().next(null); + // We set the tokens in tokensStore to {}, to have a smooth transition (so + // that we don't see the tokens of the previous account for 1s). + tokensStore.fetchTokensFromDb(); + // TODO Ideally we would set the defaultAccount temporarily to null. Change + // light.js to support this. + // defaultAccount$().next(); // Set default account to the clicked one, and go to Tokens on complete // TODO Not 100% clean, I don't want any api.abc.method() in any React diff --git a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js index f507940c..ea9c27dc 100644 --- a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js +++ b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js @@ -5,7 +5,12 @@ import React, { Component } from 'react'; import abi from '@parity/shared/lib/contracts/abi/eip20'; -import { defaultAccount$, makeContract$, myBalance$ } from '@parity/light.js'; +import { + defaultAccount$, + isNullOrLoading, + makeContract$, + myBalance$ +} from '@parity/light.js'; import { filter, map, switchMap } from 'rxjs/operators'; import { fromWei } from '@parity/api/lib/util/wei'; import { inject } from 'mobx-react'; @@ -17,13 +22,17 @@ import { withRouter } from 'react-router-dom'; @light({ balance: ({ token: { address, decimals } }) => address === 'ETH' - ? myBalance$().pipe(map(value => +fromWei(value))) + ? myBalance$().pipe( + map(value => (isNullOrLoading(value) ? null : value)), + map(value => value && +fromWei(value)) + ) : defaultAccount$().pipe( filter(x => x), switchMap(defaultAccount => makeContract$(address, abi).balanceOf$(defaultAccount) ), - map(value => +value.div(10 ** decimals)) + map(value => (isNullOrLoading(value) ? null : value)), + map(value => value && +value.div(10 ** decimals)) ) }) @inject('sendStore') diff --git a/yarn.lock b/yarn.lock index a048b76a..f87b8cc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -976,12 +976,13 @@ u2f-api "0.0.9" u2f-api-polyfill "0.4.3" -"@parity/light.js@https://github.com/parity-js/light.js#71bd8077a06ec2fe544650fdde56555d1921c0d4": +"@parity/light.js@https://github.com/parity-js/light.js#9646ce15d9dd9c4cf11776ddd613d5bd86016f94": version "1.0.0" - resolved "https://github.com/parity-js/light.js#71bd8077a06ec2fe544650fdde56555d1921c0d4" + resolved "https://github.com/parity-js/light.js#9646ce15d9dd9c4cf11776ddd613d5bd86016f94" dependencies: "@babel/runtime" "^7.0.0-beta.49" "@parity/api" "^2.1.23" + json-prune "^1.1.0" memoizee "^0.4.12" "@parity/shared@^3.0.2": @@ -7230,6 +7231,10 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" +json-prune@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/json-prune/-/json-prune-1.1.0.tgz#23e2fad108932b255050e3f1a70500c2b4aa30c7" + json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" -- GitLab From 80b8636639aec48f7da4bb3b5b2808bea8261e1b Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 20 Jun 2018 12:13:35 +0200 Subject: [PATCH 4/5] Remove extra contract call --- .../Tokens/TokensList/TokenBalance/TokenBalance.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js index ea9c27dc..4d4406c1 100644 --- a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js +++ b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js @@ -5,6 +5,7 @@ import React, { Component } from 'react'; import abi from '@parity/shared/lib/contracts/abi/eip20'; +import { empty } from 'rxjs'; import { defaultAccount$, isNullOrLoading, @@ -20,8 +21,11 @@ import { TokenCard } from 'light-ui'; import { withRouter } from 'react-router-dom'; @light({ - balance: ({ token: { address, decimals } }) => - address === 'ETH' + balance: ({ token: { address, decimals } }) => { + if (!address) { + return empty(); + } + return address === 'ETH' ? myBalance$().pipe( map(value => (isNullOrLoading(value) ? null : value)), map(value => value && +fromWei(value)) @@ -33,7 +37,8 @@ import { withRouter } from 'react-router-dom'; ), map(value => (isNullOrLoading(value) ? null : value)), map(value => value && +value.div(10 ** decimals)) - ) + ); + } }) @inject('sendStore') @withRouter -- GitLab From dfb5b593bfb283ca7f2bb03fbe81efa49a1262ea Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 20 Jun 2018 12:20:27 +0200 Subject: [PATCH 5/5] Better loading page for accounts --- .../src/Accounts/AccountsList/AccountsList.js | 20 +++++++++---------- .../light-ui/src/AccountCard/AccountCard.js | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/light-react/src/Accounts/AccountsList/AccountsList.js b/packages/light-react/src/Accounts/AccountsList/AccountsList.js index 6e202719..f3d42635 100644 --- a/packages/light-react/src/Accounts/AccountsList/AccountsList.js +++ b/packages/light-react/src/Accounts/AccountsList/AccountsList.js @@ -77,9 +77,9 @@ class AccountsList extends Component {
- {accountsInfo ? ( -
    - {Object.keys(accountsInfo).map(address => ( +
      + {accountsInfo ? ( + Object.keys(accountsInfo).map(address => (
    • - ))} -
    - ) : ( -
    -

    Loading…

    -
    - )} + )) + ) : ( +
  • + +
  • + )} +
diff --git a/packages/light-ui/src/AccountCard/AccountCard.js b/packages/light-ui/src/AccountCard/AccountCard.js index c330272d..06108522 100644 --- a/packages/light-ui/src/AccountCard/AccountCard.js +++ b/packages/light-ui/src/AccountCard/AccountCard.js @@ -27,7 +27,7 @@ const AccountCard = ({ address, name, ...otherProps }) => ( )}
- {address || } + {address || }
-- GitLab