meriadec
7 years ago
5 changed files with 0 additions and 627 deletions
@ -1,81 +0,0 @@ |
|||||
// @flow
|
|
||||
import { PureComponent } from 'react' |
|
||||
import isEqual from 'lodash/isEqual' |
|
||||
|
|
||||
import type { Node } from 'react' |
|
||||
import type { Device } from 'types/common' |
|
||||
|
|
||||
import getDeviceInfo from 'commands/getDeviceInfo' |
|
||||
|
|
||||
import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' |
|
||||
|
|
||||
type Error = { |
|
||||
message: string, |
|
||||
stack: string, |
|
||||
} |
|
||||
|
|
||||
type Props = { |
|
||||
device: ?Device, |
|
||||
children: (deviceInfo: ?DeviceInfo, error: ?Error) => Node, |
|
||||
} |
|
||||
|
|
||||
type State = { |
|
||||
deviceInfo: ?DeviceInfo, |
|
||||
error: ?Error, |
|
||||
} |
|
||||
|
|
||||
class EnsureDashboard extends PureComponent<Props, State> { |
|
||||
static defaultProps = { |
|
||||
children: null, |
|
||||
device: null, |
|
||||
} |
|
||||
|
|
||||
state = { |
|
||||
deviceInfo: null, |
|
||||
error: null, |
|
||||
} |
|
||||
|
|
||||
componentDidMount() { |
|
||||
this.checkForDashboard() |
|
||||
} |
|
||||
|
|
||||
componentDidUpdate({ device }: Props) { |
|
||||
if (this.props.device !== device && this.props.device) { |
|
||||
this.checkForDashboard() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
componentWillUnmount() { |
|
||||
this._unmounting = true |
|
||||
} |
|
||||
|
|
||||
_checking = false |
|
||||
_unmounting = false |
|
||||
|
|
||||
checkForDashboard = async () => { |
|
||||
const { device } = this.props |
|
||||
if (device && !this._checking) { |
|
||||
this._checking = true |
|
||||
try { |
|
||||
const deviceInfo = await getDeviceInfo.send({ devicePath: device.path }).toPromise() |
|
||||
if (!isEqual(this.state.deviceInfo, deviceInfo) || this.state.error) { |
|
||||
!this._unmounting && this.setState({ deviceInfo, error: null }) |
|
||||
} |
|
||||
} catch (err) { |
|
||||
if (!isEqual(err, this.state.error)) { |
|
||||
!this._unmounting && this.setState({ error: err, deviceInfo: null }) |
|
||||
} |
|
||||
} |
|
||||
this._checking = false |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
render() { |
|
||||
const { deviceInfo, error } = this.state |
|
||||
const { children } = this.props |
|
||||
|
|
||||
return children(deviceInfo, error) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default EnsureDashboard |
|
@ -1,88 +0,0 @@ |
|||||
// @flow
|
|
||||
import { timeout } from 'rxjs/operators/timeout' |
|
||||
import { PureComponent } from 'react' |
|
||||
import isEqual from 'lodash/isEqual' |
|
||||
|
|
||||
import { GENUINE_TIMEOUT } from 'config/constants' |
|
||||
import type { Device } from 'types/common' |
|
||||
import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' |
|
||||
|
|
||||
import getIsGenuine from 'commands/getIsGenuine' |
|
||||
|
|
||||
type Error = { |
|
||||
message: string, |
|
||||
stack: string, |
|
||||
} |
|
||||
|
|
||||
type Props = { |
|
||||
device: ?Device, |
|
||||
deviceInfo: ?DeviceInfo, |
|
||||
children: (isGenuine: ?boolean, error: ?Error) => *, |
|
||||
} |
|
||||
|
|
||||
type State = { |
|
||||
genuine: ?boolean, |
|
||||
error: ?Error, |
|
||||
} |
|
||||
|
|
||||
class EnsureGenuine extends PureComponent<Props, State> { |
|
||||
static defaultProps = { |
|
||||
children: () => null, |
|
||||
firmwareInfo: null, |
|
||||
} |
|
||||
|
|
||||
state = { |
|
||||
error: null, |
|
||||
genuine: null, |
|
||||
} |
|
||||
|
|
||||
componentDidMount() { |
|
||||
this.checkIsGenuine() |
|
||||
} |
|
||||
|
|
||||
componentDidUpdate() { |
|
||||
this.checkIsGenuine() |
|
||||
} |
|
||||
|
|
||||
componentWillUnmount() { |
|
||||
this._unmounting = true |
|
||||
} |
|
||||
|
|
||||
_checking = false |
|
||||
_unmounting = false |
|
||||
|
|
||||
async checkIsGenuine() { |
|
||||
const { device, deviceInfo } = this.props |
|
||||
if (device && deviceInfo && !this._checking) { |
|
||||
this._checking = true |
|
||||
try { |
|
||||
const res = await getIsGenuine |
|
||||
.send({ |
|
||||
devicePath: device.path, |
|
||||
deviceInfo, |
|
||||
}) |
|
||||
.pipe(timeout(GENUINE_TIMEOUT)) |
|
||||
.toPromise() |
|
||||
if (this._unmounting) return |
|
||||
const isGenuine = res === '0000' |
|
||||
if (!this.state.genuine || this.state.error) { |
|
||||
this.setState({ genuine: isGenuine, error: null }) |
|
||||
} |
|
||||
} catch (err) { |
|
||||
if (!isEqual(this.state.error, err)) { |
|
||||
this.setState({ genuine: null, error: err }) |
|
||||
} |
|
||||
} |
|
||||
this._checking = false |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
render() { |
|
||||
const { error, genuine } = this.state |
|
||||
const { children } = this.props |
|
||||
|
|
||||
return children(genuine, error) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default EnsureGenuine |
|
@ -1,171 +0,0 @@ |
|||||
// @flow
|
|
||||
/* eslint-disable react/jsx-no-literals */ |
|
||||
|
|
||||
import React from 'react' |
|
||||
import { Trans, translate } from 'react-i18next' |
|
||||
import styled from 'styled-components' |
|
||||
import isNull from 'lodash/isNull' |
|
||||
import type { Device } from 'types/common' |
|
||||
|
|
||||
import Box from 'components/base/Box' |
|
||||
import Spinner from 'components/base/Spinner' |
|
||||
|
|
||||
import IconCheck from 'icons/Check' |
|
||||
import IconExclamationCircle from 'icons/ExclamationCircle' |
|
||||
import IconUsb from 'icons/Usb' |
|
||||
import IconHome from 'icons/Home' |
|
||||
|
|
||||
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 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 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 size={16} /> |
|
||||
)} |
|
||||
</Box> |
|
||||
) |
|
||||
|
|
||||
StepCheck.defaultProps = { |
|
||||
hasErrors: false, |
|
||||
} |
|
||||
|
|
||||
type DeviceInfo = { |
|
||||
targetId: number | string, |
|
||||
version: string, |
|
||||
final: boolean, |
|
||||
mcu: boolean, |
|
||||
} |
|
||||
|
|
||||
type Error = { |
|
||||
message: string, |
|
||||
stack: string, |
|
||||
} |
|
||||
|
|
||||
type Props = { |
|
||||
// t: T,
|
|
||||
device: ?Device, |
|
||||
deviceInfo: ?DeviceInfo, |
|
||||
errors: { |
|
||||
dashboardError: ?Error, |
|
||||
genuineError: ?Error, |
|
||||
}, |
|
||||
isGenuine: boolean, |
|
||||
} |
|
||||
|
|
||||
const WorkflowDefault = ({ device, deviceInfo, errors, isGenuine }: Props) => ( |
|
||||
<Box flow={4} ff="Open Sans"> |
|
||||
<Step validated={!!device}> |
|
||||
<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> <strong /> |
|
||||
</Trans> |
|
||||
</Box> |
|
||||
<StepCheck checked={!!device} /> |
|
||||
</StepContent> |
|
||||
</Step> |
|
||||
|
|
||||
<Step validated={!!device && !!deviceInfo} hasErrors={!!device && !!errors.dashboardError}> |
|
||||
<StepContent> |
|
||||
<StepIcon> |
|
||||
<WrapperIconCurrency> |
|
||||
<IconHome size={12} /> |
|
||||
</WrapperIconCurrency> |
|
||||
</StepIcon> |
|
||||
<Box grow shrink> |
|
||||
<Trans i18nKey="deviceConnect:dashboard.open" parent="div"> |
|
||||
{'Navigate to the '} |
|
||||
<strong>{'dashboard'}</strong> |
|
||||
{' on your device'} |
|
||||
</Trans> |
|
||||
</Box> |
|
||||
<StepCheck |
|
||||
checked={!!device && !!deviceInfo} |
|
||||
hasErrors={!!device && !!errors.dashboardError} |
|
||||
/> |
|
||||
</StepContent> |
|
||||
</Step> |
|
||||
|
|
||||
{/* GENUINE CHECK */} |
|
||||
{/* ------------- */} |
|
||||
|
|
||||
<Step |
|
||||
validated={(!!device && !isNull(isGenuine) && isGenuine && !errors.genuineError) || undefined} |
|
||||
hasErrors={(!!device && !isNull(isGenuine) && !isGenuine) || errors.genuineError || undefined} |
|
||||
> |
|
||||
<StepContent> |
|
||||
<StepIcon> |
|
||||
<WrapperIconCurrency> |
|
||||
<IconCheck size={12} /> |
|
||||
</WrapperIconCurrency> |
|
||||
</StepIcon> |
|
||||
<Box grow shrink> |
|
||||
<Trans i18nKey="deviceConnect:stepGenuine.open" parent="div"> |
|
||||
{'Allow the '} |
|
||||
<strong>{'Ledger Manager'}</strong> |
|
||||
{' on your device'} |
|
||||
</Trans> |
|
||||
</Box> |
|
||||
<StepCheck |
|
||||
checked={!!device && !isNull(isGenuine) && isGenuine} |
|
||||
hasErrors={(!!device && !isNull(isGenuine) && !isGenuine) || undefined} |
|
||||
/> |
|
||||
</StepContent> |
|
||||
</Step> |
|
||||
</Box> |
|
||||
) |
|
||||
|
|
||||
export default translate()(WorkflowDefault) |
|
@ -1,194 +0,0 @@ |
|||||
// @flow
|
|
||||
/* eslint-disable react/jsx-no-literals */ // FIXME
|
|
||||
|
|
||||
import React from 'react' |
|
||||
import { Trans, translate } from 'react-i18next' |
|
||||
import styled from 'styled-components' |
|
||||
import isNull from 'lodash/isNull' |
|
||||
import type { Device, T } from 'types/common' |
|
||||
|
|
||||
import { i } from 'helpers/staticPath' |
|
||||
|
|
||||
import Box from 'components/base/Box' |
|
||||
import Text from 'components/base/Text' |
|
||||
import Spinner from 'components/base/Spinner' |
|
||||
|
|
||||
import IconCheck from 'icons/Check' |
|
||||
import IconExclamationCircle from 'icons/ExclamationCircle' |
|
||||
import IconUsb from 'icons/Usb' |
|
||||
import IconHome from 'icons/Home' |
|
||||
|
|
||||
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 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 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 size={16} /> |
|
||||
)} |
|
||||
</Box> |
|
||||
) |
|
||||
|
|
||||
StepCheck.defaultProps = { |
|
||||
hasErrors: false, |
|
||||
} |
|
||||
|
|
||||
type DeviceInfo = { |
|
||||
targetId: number | string, |
|
||||
version: string, |
|
||||
final: boolean, |
|
||||
mcu: boolean, |
|
||||
} |
|
||||
|
|
||||
type Error = { |
|
||||
message: string, |
|
||||
stack: string, |
|
||||
} |
|
||||
|
|
||||
type Props = { |
|
||||
t: T, |
|
||||
device: ?Device, |
|
||||
deviceInfo: ?DeviceInfo, |
|
||||
errors: { |
|
||||
dashboardError: ?Error, |
|
||||
genuineError: ?Error, |
|
||||
}, |
|
||||
isGenuine: boolean, |
|
||||
} |
|
||||
|
|
||||
const WorkflowWithIcon = ({ device, deviceInfo, errors, isGenuine, t }: Props) => ( |
|
||||
<Box align="center" justify="center" sticky> |
|
||||
<Box align="center" style={{ maxWidth: 460, padding: '0 10px' }}> |
|
||||
<img |
|
||||
src={i('logos/connectDevice.png')} |
|
||||
alt="connect your device" |
|
||||
style={{ marginBottom: 30, maxWidth: 362, width: '100%' }} |
|
||||
/> |
|
||||
<Text ff="Museo Sans|Regular" fontSize={7} color="black" style={{ marginBottom: 10 }}> |
|
||||
{t('app:manager.device.title')} |
|
||||
</Text> |
|
||||
<Text ff="Museo Sans|Light" fontSize={5} color="grey" align="center"> |
|
||||
{t('app:manager.device.desc')} |
|
||||
</Text> |
|
||||
</Box> |
|
||||
<Box flow={4} style={{ maxWidth: 460, padding: '60px 10px 0' }} ff="Open Sans|Regular"> |
|
||||
{/* DEVICE CHECK */} |
|
||||
<Step validated={!!device}> |
|
||||
<StepContent> |
|
||||
<StepIcon> |
|
||||
<IconUsb size={36} /> |
|
||||
</StepIcon> |
|
||||
<Box grow shrink> |
|
||||
<Trans i18nKey="deviceConnect:step1.connect" parent="div"> |
|
||||
{'Connect and unlock your '} |
|
||||
<strong>Ledger device</strong> |
|
||||
</Trans> |
|
||||
</Box> |
|
||||
<StepCheck checked={!!device} /> |
|
||||
</StepContent> |
|
||||
</Step> |
|
||||
|
|
||||
{/* DASHBOARD CHECK */} |
|
||||
<Step validated={!!device && !!deviceInfo} hasErrors={!!device && !!errors.dashboardError}> |
|
||||
<StepContent> |
|
||||
<StepIcon> |
|
||||
<WrapperIconCurrency> |
|
||||
<IconHome size={12} /> |
|
||||
</WrapperIconCurrency> |
|
||||
</StepIcon> |
|
||||
<Box grow shrink> |
|
||||
<Trans i18nKey="deviceConnect:dashboard.open" parent="div"> |
|
||||
{'Navigate to the '} |
|
||||
<strong>{'dashboard'}</strong> |
|
||||
{' on your device'} |
|
||||
</Trans> |
|
||||
</Box> |
|
||||
<StepCheck |
|
||||
checked={!!device && !!deviceInfo} |
|
||||
hasErrors={!!device && !!errors.dashboardError} |
|
||||
/> |
|
||||
</StepContent> |
|
||||
</Step> |
|
||||
|
|
||||
{/* GENUINE CHECK */} |
|
||||
<Step |
|
||||
validated={ |
|
||||
(!!device && !isNull(isGenuine) && isGenuine && !errors.genuineError) || undefined |
|
||||
} |
|
||||
hasErrors={ |
|
||||
(!!device && !isNull(isGenuine) && !isGenuine) || errors.genuineError || undefined |
|
||||
} |
|
||||
> |
|
||||
<StepContent> |
|
||||
<StepIcon> |
|
||||
<WrapperIconCurrency> |
|
||||
<IconCheck size={12} /> |
|
||||
</WrapperIconCurrency> |
|
||||
</StepIcon> |
|
||||
<Box grow shrink> |
|
||||
<Trans i18nKey="deviceConnect:stepGenuine.open" parent="div"> |
|
||||
{'Allow the '} |
|
||||
<strong>{'Ledger Manager'}</strong> |
|
||||
{' on your device'} |
|
||||
</Trans> |
|
||||
</Box> |
|
||||
<StepCheck |
|
||||
checked={(!!device && !isNull(isGenuine) && isGenuine) || undefined} |
|
||||
hasErrors={(!!device && !isNull(isGenuine) && !isGenuine) || undefined} |
|
||||
/> |
|
||||
</StepContent> |
|
||||
</Step> |
|
||||
</Box> |
|
||||
</Box> |
|
||||
) |
|
||||
|
|
||||
export default translate()(WorkflowWithIcon) |
|
@ -1,93 +0,0 @@ |
|||||
// @flow
|
|
||||
|
|
||||
import React, { PureComponent } from 'react' |
|
||||
import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' |
|
||||
|
|
||||
import type { Node } from 'react' |
|
||||
import type { Device } from 'types/common' |
|
||||
|
|
||||
import EnsureDevice from 'components/EnsureDevice' |
|
||||
import EnsureDashboard from './EnsureDashboard' |
|
||||
import EnsureGenuine from './EnsureGenuine' |
|
||||
|
|
||||
type Error = { |
|
||||
message: string, |
|
||||
stack: string, |
|
||||
} |
|
||||
|
|
||||
type Props = { |
|
||||
renderDefault: ( |
|
||||
device: ?Device, |
|
||||
deviceInfo: ?DeviceInfo, |
|
||||
isGenuine: ?boolean, |
|
||||
error: { |
|
||||
dashboardError: ?Error, |
|
||||
genuineError: ?Error, |
|
||||
}, |
|
||||
) => Node, |
|
||||
renderMcuUpdate?: (device: Device, deviceInfo: DeviceInfo) => Node, |
|
||||
renderFinalUpdate?: (device: Device, deviceInfo: DeviceInfo) => Node, |
|
||||
renderDashboard?: (device: Device, deviceInfo: DeviceInfo, isGenuine: boolean) => Node, |
|
||||
onGenuineCheck?: (isGenuine: boolean) => void, |
|
||||
renderError?: (dashboardError: ?Error, genuineError: ?Error) => Node, |
|
||||
} |
|
||||
type State = {} |
|
||||
|
|
||||
// In future, move to meri's approach; this code is way too much specific
|
|
||||
class Workflow extends PureComponent<Props, State> { |
|
||||
render() { |
|
||||
const { |
|
||||
renderDashboard, |
|
||||
renderFinalUpdate, |
|
||||
renderMcuUpdate, |
|
||||
renderError, |
|
||||
renderDefault, |
|
||||
onGenuineCheck, |
|
||||
} = this.props |
|
||||
return ( |
|
||||
<EnsureDevice> |
|
||||
{(device: Device) => ( |
|
||||
<EnsureDashboard device={device}> |
|
||||
{(deviceInfo: ?DeviceInfo, dashboardError: ?Error) => { |
|
||||
if (deviceInfo && deviceInfo.isBootloader && renderMcuUpdate) { |
|
||||
return renderMcuUpdate(device, deviceInfo) |
|
||||
} |
|
||||
|
|
||||
if (deviceInfo && deviceInfo.isOSU && renderFinalUpdate) { |
|
||||
return renderFinalUpdate(device, deviceInfo) |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<EnsureGenuine device={device} deviceInfo={deviceInfo}> |
|
||||
{(isGenuine: ?boolean, genuineError: ?Error) => { |
|
||||
if (dashboardError || genuineError) { |
|
||||
return renderError |
|
||||
? renderError(dashboardError, genuineError) |
|
||||
: renderDefault(device, deviceInfo, isGenuine, { |
|
||||
genuineError, |
|
||||
dashboardError, |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
if (isGenuine && deviceInfo && device && !dashboardError && !genuineError) { |
|
||||
if (onGenuineCheck) onGenuineCheck(isGenuine) |
|
||||
|
|
||||
if (renderDashboard) return renderDashboard(device, deviceInfo, isGenuine) |
|
||||
} |
|
||||
|
|
||||
return renderDefault(device, deviceInfo, isGenuine, { |
|
||||
genuineError, |
|
||||
dashboardError, |
|
||||
}) |
|
||||
}} |
|
||||
</EnsureGenuine> |
|
||||
) |
|
||||
}} |
|
||||
</EnsureDashboard> |
|
||||
)} |
|
||||
</EnsureDevice> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default Workflow |
|
Loading…
Reference in new issue