diff --git a/src/actions/accounts.js b/src/actions/accounts.js index d5b58660..9551145c 100644 --- a/src/actions/accounts.js +++ b/src/actions/accounts.js @@ -16,12 +16,6 @@ export const removeAccount: RemoveAccount = payload => ({ payload, }) -export type ReorderAccounts = (string[]) => { type: string, payload: string[] } -export const reorderAccounts: ReorderAccounts = payload => ({ - type: 'DB:REORDER_ACCOUNTS', - payload, -}) - export type FetchAccounts = () => * export const fetchAccounts: FetchAccounts = () => { db.init('accounts', []) // FIXME the "init" pattern to drop imo. a simple get()||[] is enough diff --git a/src/actions/general.js b/src/actions/general.js new file mode 100644 index 00000000..02e6d7fb --- /dev/null +++ b/src/actions/general.js @@ -0,0 +1,43 @@ +// @flow + +import { createSelector, createStructuredSelector } from 'reselect' +import CounterValues from 'helpers/countervalues' +import { + intermediaryCurrency, + currencySettingsForAccountSelector, + getOrderAccounts, +} from 'reducers/settings' +import { accountsSelector } from 'reducers/accounts' +import { sortAccounts } from 'helpers/accountOrdering' + +const accountsBtcBalanceSelector = createSelector( + accountsSelector, + state => state, + (accounts, state) => + accounts.map(account => { + const { exchange } = currencySettingsForAccountSelector(state, { account }) + return CounterValues.calculateSelector(state, { + from: account.currency, + to: intermediaryCurrency, + exchange, + value: account.balance, + }) + }), +) + +const selectAccountsBalanceAndOrder = createStructuredSelector({ + accounts: accountsSelector, + accountsBtcBalance: accountsBtcBalanceSelector, + orderAccounts: getOrderAccounts, +}) + +export const refreshAccountsOrdering = () => (dispatch: *, getState: *) => { + const all = selectAccountsBalanceAndOrder(getState()) + const allRatesAvailable = all.accountsBtcBalance.every(b => typeof b === 'number') + if (allRatesAvailable) { + dispatch({ + type: 'DB:REORDER_ACCOUNTS', + payload: sortAccounts(all), + }) + } +} diff --git a/src/components/DashboardPage/AccountsOrder.js b/src/components/DashboardPage/AccountsOrder.js index 5d1b33f4..37492d11 100644 --- a/src/components/DashboardPage/AccountsOrder.js +++ b/src/components/DashboardPage/AccountsOrder.js @@ -1,32 +1,21 @@ // @flow -import logger from 'logger' import React, { Component } from 'react' import styled from 'styled-components' import { compose } from 'redux' import { translate } from 'react-i18next' import { connect } from 'react-redux' -import type { Account } from '@ledgerhq/live-common/lib/types' -import CounterValues from 'helpers/countervalues' +import { createStructuredSelector } from 'reselect' import type { T } from 'types/common' - -import { - getOrderAccounts, - intermediaryCurrency, - currencySettingsForAccountSelector, -} from 'reducers/settings' -import { createStructuredSelector, createSelector } from 'reselect' -import { reorderAccounts } from 'actions/accounts' -import { accountsSelector } from 'reducers/accounts' +import { refreshAccountsOrdering } from 'actions/general' import { saveSettings } from 'actions/settings' - +import { getOrderAccounts } from 'reducers/settings' import Track from 'analytics/Track' import BoldToggle from 'components/base/BoldToggle' import Box from 'components/base/Box' import DropDown, { DropDownItem } from 'components/base/DropDown' import Text from 'components/base/Text' - import IconAngleDown from 'icons/AngleDown' import IconArrowDown from 'icons/ArrowDown' import IconArrowUp from 'icons/ArrowUp' @@ -34,41 +23,10 @@ import IconArrowUp from 'icons/ArrowUp' type Props = { t: T, orderAccounts: string, - accounts: Account[], - accountsBtcBalance: number[], // eslint-disable-line - reorderAccounts: (string[]) => *, + refreshAccountsOrdering: () => *, saveSettings: (*) => *, } -type SortMethod = 'name' | 'balance' - -const sortMethod: { [_: SortMethod]: (Account[], Props) => string[] } = { - balance: (accounts, { accountsBtcBalance }: Props) => - accounts - .map((a, i) => [a.id, accountsBtcBalance[i]]) - .sort((a, b) => a[1] - b[1]) - .map(o => o[0]), - - name: accounts => - accounts - .slice(0) - .sort((a, b) => a.name.localeCompare(b.name)) - .map(a => a.id), -} - -function sortAccounts(accounts: Account[], orderAccounts: string, props: Props) { - const [order, sort] = orderAccounts.split('|') - if (order === 'name' || order === 'balance') { - const ids = sortMethod[order](accounts, props) - if (sort === 'asc') { - ids.reverse() - } - return ids - } - logger.warn(`sortAccounts not implemented for ${orderAccounts}`) - return null -} - const OrderIcon = styled(Box).attrs({ alignItems: 'center', justifyContent: 'center', @@ -77,31 +35,12 @@ const OrderIcon = styled(Box).attrs({ opacity: ${p => (p.isActive ? 1 : 0)}; ` -const accountsBtcBalanceSelector = createSelector( - accountsSelector, - state => state, - (accounts, state) => - accounts.map(account => { - const { exchange } = currencySettingsForAccountSelector(state, { account }) - return ( - CounterValues.calculateSelector(state, { - from: account.currency, - to: intermediaryCurrency, - exchange, - value: account.balance, - }) || 0 - ) - }), -) - const mapStateToProps = createStructuredSelector({ orderAccounts: getOrderAccounts, - accounts: accountsSelector, - accountsBtcBalance: accountsBtcBalanceSelector, }) const mapDispatchToProps = { - reorderAccounts, + refreshAccountsOrdering, saveSettings, } @@ -120,12 +59,9 @@ class AccountsOrder extends Component { } setAccountOrder = order => { - const { saveSettings, reorderAccounts } = this.props - const maybeIds = sortAccounts(this.props.accounts, order, this.props) - if (maybeIds) { - reorderAccounts(maybeIds) - saveSettings({ orderAccounts: order }) - } + const { saveSettings, refreshAccountsOrdering } = this.props + saveSettings({ orderAccounts: order }) + refreshAccountsOrdering() } getCurrentOrder = () => { diff --git a/src/components/DashboardPage/index.js b/src/components/DashboardPage/index.js index f652cb31..384f6d71 100644 --- a/src/components/DashboardPage/index.js +++ b/src/components/DashboardPage/index.js @@ -24,10 +24,10 @@ import { } from 'reducers/settings' import type { TimeRange } from 'reducers/settings' -import { reorderAccounts } from 'actions/accounts' import { saveSettings } from 'actions/settings' import TrackPage from 'analytics/TrackPage' +import RefreshAccountsOrdering from 'components/RefreshAccountsOrdering' import UpdateNotifier from 'components/UpdateNotifier' import BalanceInfos from 'components/BalanceSummary/BalanceInfos' import BalanceSummary from 'components/BalanceSummary' @@ -51,7 +51,6 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = { push, - reorderAccounts, saveSettings, openModal, } @@ -102,6 +101,7 @@ class DashboardPage extends PureComponent { return ( + *, + onMount?: boolean, + onUnmount?: boolean, +}> { + componentDidMount() { + if (this.props.onMount) { + this.props.refreshAccountsOrdering() + } + } + + componentWillUnmount() { + if (this.props.onUnmount) { + this.props.refreshAccountsOrdering() + } + } + + render() { + return null + } +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(RefreshAccountsOrdering) diff --git a/src/components/modals/AddAccounts/steps/04-step-finish.js b/src/components/modals/AddAccounts/steps/04-step-finish.js index 77e410c7..6dfc7afc 100644 --- a/src/components/modals/AddAccounts/steps/04-step-finish.js +++ b/src/components/modals/AddAccounts/steps/04-step-finish.js @@ -6,6 +6,7 @@ import styled from 'styled-components' import TrackPage from 'analytics/TrackPage' import Box from 'components/base/Box' import Button from 'components/base/Button' +import RefreshAccountsOrdering from 'components/RefreshAccountsOrdering' import IconCheckFull from 'icons/CheckFull' import { CurrencyCircleIcon } from '../../../base/CurrencyBadge' import type { StepProps } from '../index' @@ -30,6 +31,10 @@ const Text = styled(Box).attrs({ function StepFinish({ currency, t, checkedAccountsIds }: StepProps) { return ( + + {/* onMount because if we already have the countervalues we want to sort it straightaway + onUnmount because if not, it is useful to trigger a second refresh to ensure it get sorted */} + {currency ? ( diff --git a/src/helpers/accountOrdering.js b/src/helpers/accountOrdering.js new file mode 100644 index 00000000..df303bb8 --- /dev/null +++ b/src/helpers/accountOrdering.js @@ -0,0 +1,37 @@ +// @flow + +import type { Account } from '@ledgerhq/live-common/lib/types' + +type Param = { + accounts: Account[], + accountsBtcBalance: number[], + orderAccounts: string, +} + +type SortMethod = 'name' | 'balance' + +const sortMethod: { [_: SortMethod]: (Param) => string[] } = { + balance: ({ accounts, accountsBtcBalance }) => + accounts + .map((a, i) => [a.id, accountsBtcBalance[i]]) + .sort((a, b) => a[1] - b[1]) + .map(o => o[0]), + + name: ({ accounts }) => + accounts + .slice(0) + .sort((a, b) => a.name.localeCompare(b.name)) + .map(a => a.id), +} + +export function sortAccounts(param: Param) { + const [order, sort] = param.orderAccounts.split('|') + if (order === 'name' || order === 'balance') { + const ids = sortMethod[order](param) + if (sort === 'asc') { + ids.reverse() + } + return ids + } + return null +}