Browse Source

Merge pull request #1649 from gre/coin-disruption-alert

Add disruption alert in Send/Receive/Add Account as well
gre-patch-1
Gaëtan Renaudeau 6 years ago
committed by GitHub
parent
commit
ddecc107c0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/bridge/BridgeSyncContext.js
  2. 69
      src/components/CurrencyDownStatusAlert.js
  3. 8
      src/components/modals/AddAccounts/steps/01-step-choose-currency.js
  4. 3
      src/components/modals/Receive/steps/01-step-account.js
  5. 16
      src/components/modals/Receive/steps/02-step-connect-device.js
  6. 3
      src/components/modals/Send/steps/01-step-amount.js
  7. 4
      src/reducers/accounts.js
  8. 20
      src/reducers/currenciesStatus.js

4
src/bridge/BridgeSyncContext.js

@ -16,7 +16,7 @@ import { setAccountSyncState } from 'actions/bridgeSync'
import { bridgeSyncSelector, syncStateLocalSelector } from 'reducers/bridgeSync' import { bridgeSyncSelector, syncStateLocalSelector } from 'reducers/bridgeSync'
import type { BridgeSyncState } from 'reducers/bridgeSync' import type { BridgeSyncState } from 'reducers/bridgeSync'
import { accountsSelector, isUpToDateSelector } from 'reducers/accounts' import { accountsSelector, isUpToDateSelector } from 'reducers/accounts'
import { currenciesStatusSelector, getIsCurrencyDown } from 'reducers/currenciesStatus' import { currenciesStatusSelector, currencyDownStatusLocal } from 'reducers/currenciesStatus'
import { SYNC_MAX_CONCURRENT, SYNC_TIMEOUT } from 'config/constants' import { SYNC_MAX_CONCURRENT, SYNC_TIMEOUT } from 'config/constants'
import type { CurrencyStatus } from 'reducers/currenciesStatus' import type { CurrencyStatus } from 'reducers/currenciesStatus'
import { getBridgeForCurrency } from '.' import { getBridgeForCurrency } from '.'
@ -77,7 +77,7 @@ class Provider extends Component<BridgeSyncProviderOwnProps, Sync> {
return return
} }
if (getIsCurrencyDown(this.props.currenciesStatus, account.currency)) { if (currencyDownStatusLocal(this.props.currenciesStatus, account.currency)) {
next() next()
return return
} }

69
src/components/CurrencyDownStatusAlert.js

@ -0,0 +1,69 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { CurrencyStatus } from 'reducers/currenciesStatus'
import { currencyDownStatus } from 'reducers/currenciesStatus'
import { openURL } from 'helpers/linking'
import Box from 'components/base/Box'
import IconTriangleWarning from 'icons/TriangleWarning'
import IconExternalLink from 'icons/ExternalLink'
type Props = {
t: *,
status: ?CurrencyStatus,
}
const CurrencyDownBox = styled(Box).attrs({
horizontal: true,
align: 'center',
color: 'white',
borderRadius: 1,
fontSize: 1,
px: 4,
py: 2,
mb: 4,
})`
background-color: ${p => p.theme.colors.alertRed};
`
const Link = styled.span`
margin-left: 5px;
margin-right: 5px;
text-decoration: underline;
cursor: pointer;
`
class CurrencyDownStatusAlert extends PureComponent<Props> {
onClick = () => {
const { status } = this.props
if (status) openURL(status.link)
}
render() {
const { status, t } = this.props
if (!status) return null
return (
<CurrencyDownBox>
<Box mr={2}>
<IconTriangleWarning height={16} width={16} />
</Box>
<Box style={{ display: 'block' }} ff="Open Sans|SemiBold" fontSize={3} horizontal shrink>
{status.message}
<Link onClick={this.onClick}>{t('common.learnMore')}</Link>
<IconExternalLink size={12} />
</Box>
</CurrencyDownBox>
)
}
}
export default connect(
createStructuredSelector({
status: currencyDownStatus,
}),
)(translate()(CurrencyDownStatusAlert))

8
src/components/modals/AddAccounts/steps/01-step-choose-currency.js

@ -5,12 +5,18 @@ import React, { Fragment } from 'react'
import TrackPage from 'analytics/TrackPage' import TrackPage from 'analytics/TrackPage'
import SelectCurrency from 'components/SelectCurrency' import SelectCurrency from 'components/SelectCurrency'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import CurrencyDownStatusAlert from 'components/CurrencyDownStatusAlert'
import CurrencyBadge from 'components/base/CurrencyBadge' import CurrencyBadge from 'components/base/CurrencyBadge'
import type { StepProps } from '../index' import type { StepProps } from '../index'
function StepChooseCurrency({ currency, setCurrency }: StepProps) { function StepChooseCurrency({ currency, setCurrency }: StepProps) {
return <SelectCurrency autoFocus onChange={setCurrency} value={currency} /> return (
<Fragment>
{currency ? <CurrencyDownStatusAlert currency={currency} /> : null}
<SelectCurrency autoFocus onChange={setCurrency} value={currency} />
</Fragment>
)
} }
export function StepChooseCurrencyFooter({ transitionTo, currency, t }: StepProps) { export function StepChooseCurrencyFooter({ transitionTo, currency, t }: StepProps) {

3
src/components/modals/Receive/steps/01-step-account.js

@ -7,6 +7,7 @@ import Box from 'components/base/Box'
import Label from 'components/base/Label' import Label from 'components/base/Label'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import SelectAccount from 'components/SelectAccount' import SelectAccount from 'components/SelectAccount'
import CurrencyDownStatusAlert from 'components/CurrencyDownStatusAlert'
import type { StepProps } from '../index' import type { StepProps } from '../index'
@ -14,6 +15,8 @@ export default function StepAccount({ t, account, onChangeAccount }: StepProps)
return ( return (
<Box flow={1}> <Box flow={1}>
<TrackPage category="Receive Flow" name="Step 1" /> <TrackPage category="Receive Flow" name="Step 1" />
{account ? <CurrencyDownStatusAlert currency={account.currency} /> : null}
<Label>{t('receive.steps.chooseAccount.label')}</Label> <Label>{t('receive.steps.chooseAccount.label')}</Label>
<SelectAccount autoFocus onChange={onChangeAccount} value={account} /> <SelectAccount autoFocus onChange={onChangeAccount} value={account} />
</Box> </Box>

16
src/components/modals/Receive/steps/02-step-connect-device.js

@ -1,21 +1,25 @@
// @flow // @flow
import React from 'react' import React, { Fragment } from 'react'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import EnsureDeviceApp from 'components/EnsureDeviceApp' import EnsureDeviceApp from 'components/EnsureDeviceApp'
import CurrencyDownStatusAlert from 'components/CurrencyDownStatusAlert'
import TrackPage from 'analytics/TrackPage' import TrackPage from 'analytics/TrackPage'
import type { StepProps } from '../index' import type { StepProps } from '../index'
export default function StepConnectDevice({ account, onChangeAppOpened }: StepProps) { export default function StepConnectDevice({ account, onChangeAppOpened }: StepProps) {
return ( return (
<EnsureDeviceApp <Fragment>
account={account} {account ? <CurrencyDownStatusAlert currency={account.currency} /> : null}
waitBeforeSuccess={200} <EnsureDeviceApp
onSuccess={() => onChangeAppOpened(true)} account={account}
/> waitBeforeSuccess={200}
onSuccess={() => onChangeAppOpened(true)}
/>
</Fragment>
) )
} }

3
src/components/modals/Send/steps/01-step-amount.js

@ -13,6 +13,7 @@ import Text from 'components/base/Text'
import CounterValue from 'components/CounterValue' import CounterValue from 'components/CounterValue'
import Spinner from 'components/base/Spinner' import Spinner from 'components/base/Spinner'
import TrackPage from 'analytics/TrackPage' import TrackPage from 'analytics/TrackPage'
import CurrencyDownStatusAlert from 'components/CurrencyDownStatusAlert'
import RecipientField from '../fields/RecipientField' import RecipientField from '../fields/RecipientField'
import AmountField from '../fields/AmountField' import AmountField from '../fields/AmountField'
@ -38,6 +39,8 @@ export default ({
return ( return (
<Box flow={4}> <Box flow={4}>
<TrackPage category="Send Flow" name="Step 1" /> <TrackPage category="Send Flow" name="Step 1" />
{account ? <CurrencyDownStatusAlert currency={account.currency} /> : null}
<Box flow={1}> <Box flow={1}>
<Label>{t('send.steps.amount.selectAccountDebit')}</Label> <Label>{t('send.steps.amount.selectAccountDebit')}</Label>
<SelectAccount autoFocus={!openedFromAccount} onChange={onChangeAccount} value={account} /> <SelectAccount autoFocus={!openedFromAccount} onChange={onChangeAccount} value={account} />

4
src/reducers/accounts.js

@ -6,7 +6,7 @@ import accountModel from 'helpers/accountModel'
import logger from 'logger' import logger from 'logger'
import type { Account, AccountRaw } from '@ledgerhq/live-common/lib/types' import type { Account, AccountRaw } from '@ledgerhq/live-common/lib/types'
import { OUTDATED_CONSIDERED_DELAY, DEBUG_SYNC } from 'config/constants' import { OUTDATED_CONSIDERED_DELAY, DEBUG_SYNC } from 'config/constants'
import { currenciesStatusSelector, getIsCurrencyDown } from './currenciesStatus' import { currenciesStatusSelector, currencyDownStatusLocal } from './currenciesStatus'
export type AccountsState = Account[] export type AccountsState = Account[]
const state: AccountsState = [] const state: AccountsState = []
@ -65,7 +65,7 @@ export const activeAccountsSelector = createSelector(
accountsSelector, accountsSelector,
currenciesStatusSelector, currenciesStatusSelector,
(accounts, currenciesStatus) => (accounts, currenciesStatus) =>
accounts.filter(a => !getIsCurrencyDown(currenciesStatus, a.currency)), accounts.filter(a => !currencyDownStatusLocal(currenciesStatus, a.currency)),
) )
export const isUpToDateSelector = createSelector(activeAccountsSelector, accounts => export const isUpToDateSelector = createSelector(activeAccountsSelector, accounts =>

20
src/reducers/currenciesStatus.js

@ -1,7 +1,8 @@
// @flow // @flow
import { handleActions, createAction } from 'redux-actions' import { handleActions, createAction } from 'redux-actions'
import type { Currency } from '@ledgerhq/live-common/lib/types' import { createSelector } from 'reselect'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import network from 'api/network' import network from 'api/network'
import { urls } from 'config/urls' import { urls } from 'config/urls'
@ -11,7 +12,6 @@ import type { State } from './index'
export type CurrencyStatus = { export type CurrencyStatus = {
id: string, // the currency id id: string, // the currency id
status: 'KO' | 'OK',
message: string, message: string,
link: string, link: string,
nonce: number, nonce: number,
@ -47,11 +47,17 @@ export const fetchCurrenciesStatus = () => async (dispatch: *) => {
export const currenciesStatusSelector = (state: State) => state.currenciesStatus export const currenciesStatusSelector = (state: State) => state.currenciesStatus
// It's not a *real* selector, but it's better than having this logic inside component // if there is a status, it means that currency is disrupted, the status is returned.
export const getIsCurrencyDown = (currenciesStatus: CurrenciesStatusState, currency: Currency) => { export const currencyDownStatusLocal = (
const item = currenciesStatus.find(c => c.id === currency.id) currenciesStatus: CurrenciesStatusState,
return !!item && item.status === 'KO' currency: CryptoCurrency,
} ): ?CurrencyStatus => currenciesStatus.find(c => c.id === currency.id)
export const currencyDownStatus = createSelector(
currenciesStatusSelector,
(_, { currency }) => currency,
currencyDownStatusLocal,
)
// Exporting reducer // Exporting reducer

Loading…
Cancel
Save