Browse Source

Onboarding subtitle

master
ddasilva 7 years ago
parent
commit
b360ab53aa
  1. 321
      src/components/DeviceConnect/index.js
  2. 2
      static/i18n/en/onboarding.yml

321
src/components/DeviceConnect/index.js

@ -0,0 +1,321 @@
// @flow
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { Trans, translate } from 'react-i18next'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { T, Device } from 'types/common'
import noop from 'lodash/noop'
import Box from 'components/base/Box'
import Spinner from 'components/base/Spinner'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
import TranslatedError from 'components/TranslatedError'
import IconCheck from 'icons/Check'
import IconExclamationCircle from 'icons/ExclamationCircle'
import IconInfoCircle from 'icons/InfoCircle'
import IconUsb from 'icons/Usb'
import IconHome from 'icons/Home'
import * as IconDevice from 'icons/device'
// TODO: CHECK IF COMPONENT CAN BE REMOVED
const Step = styled(Box).attrs({
borderRadius: 1,
justifyContent: 'center',
fontSize: 4,
})`
border: 1px solid
${p =>
p.validated
? p.theme.colors.wallet
: p.hasErrors
? p.theme.colors.alertRed
: p.theme.colors.fog};
`
const StepIcon = styled(Box).attrs({
alignItems: 'center',
justifyContent: 'center',
})`
width: 64px;
`
const StepContent = styled(Box).attrs({
color: 'dark',
horizontal: true,
alignItems: 'center',
})`
height: 60px;
line-height: 1.2;
strong {
font-weight: 600;
}
`
const ListDevices = styled(Box).attrs({
p: 3,
pt: 1,
flow: 2,
})``
const DeviceItem = styled(Box).attrs({
bg: 'lightGrey',
borderRadius: 1,
alignItems: 'center',
color: 'dark',
ff: 'Open Sans|SemiBold',
fontSize: 4,
horizontal: true,
pr: 3,
pl: 0,
})`
cursor: pointer;
height: 54px;
`
const DeviceIcon = styled(Box).attrs({
alignItems: 'center',
justifyContent: 'center',
color: 'graphite',
})`
width: 55px;
`
const DeviceSelected = styled(Box).attrs({
alignItems: 'center',
bg: p => (p.selected ? 'wallet' : 'white'),
color: 'white',
justifyContent: 'center',
})`
border-radius: 50%;
border: 1px solid ${p => (p.selected ? p.theme.colors.wallet : p.theme.colors.fog)};
height: 18px;
width: 18px;
`
const WrapperIconCurrency = styled(Box).attrs({
alignItems: 'center',
justifyContent: 'center',
})`
border: 1px solid ${p => p.theme.colors[p.color]};
border-radius: 8px;
height: 24px;
width: 24px;
`
const Info = styled(Box).attrs({
alignItems: 'center',
color: p => (p.hasErrors ? 'alertRed' : 'grey'),
flow: 2,
fontSize: 3,
horizontal: true,
ml: 1,
})`
strong {
font-weight: 600;
}
`
const StepCheck = ({ checked, hasErrors }: { checked: boolean, hasErrors?: boolean }) => (
<Box pr={5}>
{checked ? (
<Box color="wallet">
<IconCheck size={16} />
</Box>
) : hasErrors ? (
<Box color="alertRed">
<IconExclamationCircle size={16} />
</Box>
) : (
<Spinner color="grey" size={16} />
)}
</Box>
)
StepCheck.defaultProps = {
hasErrors: false,
}
type Props = {
appOpened: null | 'success' | 'fail',
genuineCheckStatus: null | 'success' | 'fail',
withGenuineCheck: boolean,
currency: CryptoCurrency,
devices: Device[],
deviceSelected: ?Device,
onChangeDevice: Device => void,
t: T,
error: ?Error,
}
const emitChangeDevice = props => {
const { onChangeDevice, deviceSelected, devices } = props
if (deviceSelected === null && devices.length > 0) {
onChangeDevice(devices[0])
}
}
class DeviceConnect extends PureComponent<Props> {
static defaultProps = {
accountName: null,
appOpened: null,
devices: [],
deviceSelected: null,
onChangeDevice: noop,
withGenuineCheck: false,
}
componentDidMount() {
emitChangeDevice(this.props)
}
componentWillReceiveProps(nextProps) {
emitChangeDevice(nextProps)
}
getStepState = stepStatus => ({
success: stepStatus === 'success',
fail: stepStatus === 'fail',
})
render() {
const {
deviceSelected,
genuineCheckStatus,
withGenuineCheck,
appOpened,
error,
currency,
t,
onChangeDevice,
devices,
} = this.props
const appState = this.getStepState(appOpened)
const genuineCheckState = this.getStepState(genuineCheckStatus)
const hasDevice = devices.length > 0
const hasMultipleDevices = devices.length > 1
// TODO: place custom wording in trans tags into yml file
/* eslint-disable react/jsx-no-literals */
return (
<Box flow={4} ff="Open Sans">
<Step validated={hasDevice}>
<StepContent>
<StepIcon>
<IconUsb size={36} />
</StepIcon>
<Box grow shrink>
<Trans i18nKey="app:deviceConnect.step1.connect" parent="div">
Connect and unlock your <strong>Ledger device</strong>
</Trans>
</Box>
<StepCheck checked={hasDevice} />
</StepContent>
{hasMultipleDevices && (
<ListDevices>
<Box color="graphite" fontSize={3}>
{t('app:deviceConnect.step1.choose', { count: devices.length })}
</Box>
<Box flow={2}>
{devices.map(d => {
const Icon = IconDevice[d.product.replace(/\s/g, '')]
return (
<DeviceItem key={d.path} onClick={() => onChangeDevice(d)}>
<DeviceIcon>
<Icon size={28} />
</DeviceIcon>
<Box grow noShrink>
{`${d.manufacturer} ${d.product}`}
</Box>
<Box>
<DeviceSelected selected={d === deviceSelected}>
<IconCheck size={10} />
</DeviceSelected>
</Box>
</DeviceItem>
)
})}
</Box>
</ListDevices>
)}
</Step>
<Step validated={appState.success} hasErrors={appState.fail}>
{currency ? (
<StepContent>
<StepIcon>
<WrapperIconCurrency>
<CryptoCurrencyIcon currency={currency} size={12} />
</WrapperIconCurrency>
</StepIcon>
<Box grow shrink>
<Trans i18nKey="deviceConnect:step2.open" parent="div">
{'Open the '}
<strong>{currency.name}</strong>
{' app on your device'}
</Trans>
</Box>
<StepCheck checked={appState.success} hasErrors={appState.fail} />
</StepContent>
) : (
<StepContent>
<StepIcon>
<WrapperIconCurrency>
<IconHome size={12} />
</WrapperIconCurrency>
</StepIcon>
<Box grow shrink>
<Trans i18nKey="app:dashboard.open" parent="div">
{'Navigate to the '}
<strong>{'dashboard'}</strong>
{' on your device'}
</Trans>
</Box>
<StepCheck checked={appState.success} hasErrors={appState.fail} />
</StepContent>
)}
</Step>
{/* GENUINE CHECK */}
{/* ------------- */}
{withGenuineCheck && (
<Step validated={genuineCheckState.success} hasErrors={genuineCheckState.fail}>
<StepContent>
<StepIcon>
<WrapperIconCurrency>
<IconCheck size={12} />
</WrapperIconCurrency>
</StepIcon>
<Box grow shrink>
<Trans i18nKey="deviceConnect:stepGenuine.open" parent="div">
{'Allow '}
<strong>{'Ledger Manager'}</strong>
{' on your device'}
</Trans>
</Box>
<StepCheck checked={genuineCheckState.success} hasErrors={genuineCheckState.fail} />
</StepContent>
</Step>
)}
{error ? (
<Info hasErrors>
<IconInfoCircle size={12} />
<Box shrink selectable>
<TranslatedError error={error} />
</Box>
</Info>
) : null}
</Box>
)
}
}
export default translate()(DeviceConnect)

2
static/i18n/en/onboarding.yml

@ -66,8 +66,6 @@ writeSeed:
initialize:
title: Save your recovery phrase
desc: Your device will generate a 24-word recovery phrase to back up your private keys
#Save the 24-word recovery phrase on your device to back up your private keys
# Your device will generate a 24-word recovery phrase to back up your private keys
nano:
step1: 'Copy the word displayed below <1><0>Word #1</0></1> in position 1 on a blank Recovery sheet.'
step2: 'Press the right button to display <1><0>Word #2</0></1> and repeat the process until all 24 words are copied on the Recovery sheet.' #<italic>Recovery sheet</italic>

Loading…
Cancel
Save