|
|
@ -1,7 +1,9 @@ |
|
|
|
// @flow
|
|
|
|
|
|
|
|
import React, { PureComponent } from 'react' |
|
|
|
import styled from 'styled-components' |
|
|
|
import type { Account } from '@ledgerhq/live-common/lib/types' |
|
|
|
import uniq from 'lodash/uniq' |
|
|
|
|
|
|
|
import { getBridgeForCurrency } from 'bridge' |
|
|
|
|
|
|
@ -48,10 +50,16 @@ class StepImport extends PureComponent<StepProps> { |
|
|
|
|
|
|
|
this.scanSubscription = bridge.scanAccountsOnDevice(currency, devicePath, { |
|
|
|
next: account => { |
|
|
|
const { scannedAccounts } = this.props |
|
|
|
const { scannedAccounts, checkedAccountsIds } = this.props |
|
|
|
const hasAlreadyBeenScanned = !!scannedAccounts.find(a => account.id === a.id) |
|
|
|
if (!hasAlreadyBeenScanned) { |
|
|
|
setState({ scannedAccounts: [...scannedAccounts, account] }) |
|
|
|
setState({ |
|
|
|
scannedAccounts: [...scannedAccounts, account], |
|
|
|
checkedAccountsIds: |
|
|
|
account.operations.length > 0 |
|
|
|
? uniq([...checkedAccountsIds, account.id]) |
|
|
|
: checkedAccountsIds, |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
complete: () => setState({ scanStatus: 'finished' }), |
|
|
@ -105,57 +113,100 @@ class StepImport extends PureComponent<StepProps> { |
|
|
|
|
|
|
|
handleToggleSelectAll = () => { |
|
|
|
const { scannedAccounts, setState } = this.props |
|
|
|
setState({ checkedAccountsIds: scannedAccounts.map(a => a.id) }) |
|
|
|
setState({ |
|
|
|
checkedAccountsIds: scannedAccounts.filter(a => a.operations.length > 0).map(a => a.id), |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
render() { |
|
|
|
const { scanStatus, err, scannedAccounts, checkedAccountsIds, existingAccounts } = this.props |
|
|
|
|
|
|
|
const importableAccounts = scannedAccounts.filter(acc => { |
|
|
|
if (acc.operations.length <= 0) { |
|
|
|
return false |
|
|
|
} |
|
|
|
return existingAccounts.find(a => a.id === acc.id) === undefined |
|
|
|
}) |
|
|
|
|
|
|
|
const creatableAccounts = scannedAccounts.filter(acc => { |
|
|
|
if (acc.operations.length > 0) { |
|
|
|
return false |
|
|
|
} |
|
|
|
return existingAccounts.find(a => a.id === acc.id) === undefined |
|
|
|
}) |
|
|
|
|
|
|
|
return ( |
|
|
|
<Box> |
|
|
|
{err && <Box shrink>{err.message}</Box>} |
|
|
|
|
|
|
|
{!!scannedAccounts.length && ( |
|
|
|
<Box horizontal justify="flex-end" mb={2}> |
|
|
|
<FakeLink onClick={this.handleToggleSelectAll} fontSize={3}> |
|
|
|
{'Select all'} |
|
|
|
</FakeLink> |
|
|
|
<Box flow={5}> |
|
|
|
<Box> |
|
|
|
{!!importableAccounts.length && ( |
|
|
|
<Box horizontal mb={3} align="center"> |
|
|
|
<Box |
|
|
|
ff="Open Sans|Bold" |
|
|
|
color="dark" |
|
|
|
fontSize={2} |
|
|
|
style={{ textTransform: 'uppercase' }} |
|
|
|
> |
|
|
|
{`Account(s) to import (${importableAccounts.length})`} |
|
|
|
</Box> |
|
|
|
<FakeLink ml="auto" onClick={this.handleToggleSelectAll} fontSize={3}> |
|
|
|
{'Select all'} |
|
|
|
</FakeLink> |
|
|
|
</Box> |
|
|
|
)} |
|
|
|
|
|
|
|
<Box flow={2}> |
|
|
|
{importableAccounts.map(account => { |
|
|
|
const isChecked = checkedAccountsIds.find(id => id === account.id) !== undefined |
|
|
|
const existingAccount = existingAccounts.find(a => a.id === account.id) |
|
|
|
const isDisabled = existingAccount !== undefined |
|
|
|
return ( |
|
|
|
<AccountRow |
|
|
|
key={account.id} |
|
|
|
account={existingAccount || account} |
|
|
|
isChecked={isChecked} |
|
|
|
isDisabled={isDisabled} |
|
|
|
onClick={this.handleToggleAccount} |
|
|
|
onAccountUpdate={this.handleAccountUpdate} |
|
|
|
/> |
|
|
|
) |
|
|
|
})} |
|
|
|
|
|
|
|
{scanStatus === 'scanning' && ( |
|
|
|
<LoadingRow> |
|
|
|
<Spinner color="grey" size={16} /> |
|
|
|
</LoadingRow> |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
</Box> |
|
|
|
)} |
|
|
|
|
|
|
|
<Box flow={2}> |
|
|
|
{scannedAccounts.map(account => { |
|
|
|
const isChecked = checkedAccountsIds.find(id => id === account.id) !== undefined |
|
|
|
const existingAccount = existingAccounts.find(a => a.id === account.id) |
|
|
|
const isDisabled = existingAccount !== undefined |
|
|
|
return ( |
|
|
|
{creatableAccounts.length > 0 && ( |
|
|
|
<Box> |
|
|
|
<Box horizontal mb={3} align="center"> |
|
|
|
<Box |
|
|
|
ff="Open Sans|Bold" |
|
|
|
color="dark" |
|
|
|
fontSize={2} |
|
|
|
style={{ textTransform: 'uppercase' }} |
|
|
|
> |
|
|
|
{'Create account'} |
|
|
|
</Box> |
|
|
|
</Box> |
|
|
|
<AccountRow |
|
|
|
key={account.id} |
|
|
|
account={existingAccount || account} |
|
|
|
isChecked={isChecked} |
|
|
|
isDisabled={isDisabled} |
|
|
|
account={creatableAccounts[0]} |
|
|
|
isChecked={ |
|
|
|
checkedAccountsIds.find(id => id === creatableAccounts[0].id) !== undefined |
|
|
|
} |
|
|
|
onClick={this.handleToggleAccount} |
|
|
|
onAccountUpdate={this.handleAccountUpdate} |
|
|
|
/> |
|
|
|
) |
|
|
|
})} |
|
|
|
{scanStatus === 'scanning' && ( |
|
|
|
<Box |
|
|
|
horizontal |
|
|
|
bg="lightGrey" |
|
|
|
borderRadius={3} |
|
|
|
px={3} |
|
|
|
align="center" |
|
|
|
justify="center" |
|
|
|
style={{ height: 48 }} |
|
|
|
> |
|
|
|
<Spinner color="grey" size={24} /> |
|
|
|
</Box> |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
|
|
|
|
<Box horizontal mt={2}> |
|
|
|
{['error', 'finished'].includes(scanStatus) && ( |
|
|
|
{['error'].includes(scanStatus) && ( |
|
|
|
<Button small outline onClick={this.handleRetry}> |
|
|
|
<Box horizontal flow={2} align="center"> |
|
|
|
<IconExchange size={13} /> |
|
|
@ -171,6 +222,17 @@ class StepImport extends PureComponent<StepProps> { |
|
|
|
|
|
|
|
export default StepImport |
|
|
|
|
|
|
|
export const LoadingRow = styled(Box).attrs({ |
|
|
|
horizontal: true, |
|
|
|
borderRadius: 1, |
|
|
|
px: 3, |
|
|
|
align: 'center', |
|
|
|
justify: 'center', |
|
|
|
})` |
|
|
|
height: 48px; |
|
|
|
border: 1px dashed ${p => p.theme.colors.fog}; |
|
|
|
` |
|
|
|
|
|
|
|
export const StepImportFooter = ({ scanStatus, onClickImport, checkedAccountsIds }: StepProps) => ( |
|
|
|
<Button |
|
|
|
primary |
|
|
|