Browse Source

fix firmware steps order

master
Valentin D. Pinkman 7 years ago
parent
commit
879963f75e
No known key found for this signature in database GPG Key ID: E7D110669FFB8D3E
  1. 4
      src/commands/installOsuFirmware.js
  2. 16
      src/components/ManagerPage/FirmwareUpdate.js
  3. 104
      src/components/modals/UpdateFirmware/index.js
  4. 79
      src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js
  5. 85
      src/components/modals/UpdateFirmware/steps/01-step-osu-installer.js
  6. 38
      src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js
  7. 10
      src/helpers/common.js
  8. 3
      src/helpers/firmware/installMcu.js
  9. 4
      src/helpers/firmware/installOsuFirmware.js

4
src/commands/installOsuFirmware.js

@ -6,12 +6,12 @@ import { fromPromise } from 'rxjs/observable/fromPromise'
import { withDevice } from 'helpers/deviceAccess' import { withDevice } from 'helpers/deviceAccess'
import installOsuFirmware from 'helpers/firmware/installOsuFirmware' import installOsuFirmware from 'helpers/firmware/installOsuFirmware'
import type { LedgerScriptParams } from 'helpers/common' import type { Firmware } from 'components/modals/UpdateFirmware'
type Input = { type Input = {
devicePath: string, devicePath: string,
targetId: string | number, targetId: string | number,
firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, firmware: Firmware,
} }
type Result = * type Result = *

16
src/components/ManagerPage/FirmwareUpdate.js

@ -37,7 +37,6 @@ export type ModalStatus = 'closed' | 'disclaimer' | 'install' | 'error' | 'succe
type Props = { type Props = {
t: T, t: T,
device: Device,
deviceInfo: DeviceInfo, deviceInfo: DeviceInfo,
} }
@ -80,18 +79,15 @@ class FirmwareUpdate extends PureComponent<Props, State> {
} }
} }
installOsuFirmware = async () => { installOsuFirmware = async (device: Device) => {
try { try {
const { latestFirmware } = this.state const { latestFirmware } = this.state
const { const { deviceInfo } = this.props
deviceInfo,
device: { path: devicePath },
} = this.props
invariant(latestFirmware, 'did not find a new firmware or firmware is not set') invariant(latestFirmware, 'did not find a new firmware or firmware is not set')
this.setState({ modal: 'install' }) this.setState({ modal: 'install' })
const { success } = await installOsuFirmware const { success } = await installOsuFirmware
.send({ devicePath, firmware: latestFirmware, targetId: deviceInfo.targetId }) .send({ devicePath: device.path, firmware: latestFirmware, targetId: deviceInfo.targetId })
.toPromise() .toPromise()
return success return success
} catch (err) { } catch (err) {
@ -100,9 +96,8 @@ class FirmwareUpdate extends PureComponent<Props, State> {
} }
} }
installFinalFirmware = async () => { installFinalFirmware = async (device: Device) => {
try { try {
const { device } = this.props
const { success } = await installFinalFirmware.send({ devicePath: device.path }).toPromise() const { success } = await installFinalFirmware.send({ devicePath: device.path }).toPromise()
return success return success
} catch (err) { } catch (err) {
@ -111,8 +106,7 @@ class FirmwareUpdate extends PureComponent<Props, State> {
} }
} }
flashMCU = async () => { flashMCU = async (device: Device) => {
const { device } = this.props
await installMcu.send({ devicePath: device.path }).toPromise() await installMcu.send({ devicePath: device.path }).toPromise()
} }

104
src/components/modals/UpdateFirmware/index.js

@ -1,50 +1,43 @@
// @flow // @flow
import React, { PureComponent, Fragment } from 'react' import React, { PureComponent } from 'react'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
import type { T } from 'types/common' import type { T, Device } from 'types/common'
import Modal from 'components/base/Modal' import Modal from 'components/base/Modal'
import Stepper from 'components/base/Stepper' import Stepper from 'components/base/Stepper'
import Button from 'components/base/Button'
import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority' import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority'
import type { StepProps as DefaultStepProps, Step } from 'components/base/Stepper' import type { StepProps as DefaultStepProps, Step } from 'components/base/Stepper'
import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate'
import type { LedgerScriptParams } from 'helpers/common' import type { LedgerScriptParams } from 'helpers/common'
import StepOSUInstaller from './steps/01-step-osu-installer'
import StepFullFirmwareInstall from './steps/01-step-install-full-firmware' import StepFullFirmwareInstall from './steps/01-step-install-full-firmware'
import StepFlashMcu from './steps/02-step-flash-mcu' import StepFlashMcu from './steps/02-step-flash-mcu'
import StepConfirmation, { StepConfirmFooter } from './steps/03-step-confirmation' import StepConfirmation, { StepConfirmFooter } from './steps/03-step-confirmation'
export type Firmware = LedgerScriptParams & { shouldUpdateMcu: boolean }
export type StepProps = DefaultStepProps & { export type StepProps = DefaultStepProps & {
firmware: ?LedgerScriptParams, firmware: Firmware,
onCloseModal: () => void, onCloseModal: () => void,
installOsuFirmware: () => void, installOsuFirmware: (device: Device) => void,
installFinalFirmware: () => void, installFinalFirmware: (device: Device) => void,
flashMcu: () => void, flashMCU: (device: Device) => void,
} }
type StepId = 'idCheck' | 'updateMCU' | 'finish' type StepId = 'idCheck' | 'updateMCU' | 'finish'
function DebugFooter({ const createSteps = ({ t, firmware }: { t: T, firmware: Firmware }): Array<*> => {
transitionTo, const updateStep = {
where, id: 'idCheck',
}: { label: t('app:manager.modal.steps.idCheck'),
where: string, component: StepFullFirmwareInstall,
transitionTo: (where: string) => void, footer: null,
}) { onBack: null,
return <Button onClick={() => transitionTo(where)}>{where}</Button> hideFooter: true,
} }
const createSteps = ({
t,
firmware,
}: {
t: T,
firmware: LedgerScriptParams & { shouldUpdateMcu: boolean },
}): Array<*> => {
const finalStep = { const finalStep = {
id: 'finish', id: 'finish',
label: t('app:addAccounts.breadcrumb.finish'), label: t('app:addAccounts.breadcrumb.finish'),
@ -54,58 +47,35 @@ const createSteps = ({
hideFooter: false, hideFooter: false,
} }
if (firmware.shouldUpdateMcu) { const mcuStep = {
return [
{
id: 'idCheck',
label: t('app:manager.modal.steps.idCheck'),
component: StepOSUInstaller,
footer: ({ firmware, ...props }: StepProps) => (
<DebugFooter firmware={firmware} {...props} where="updateMCU" />
),
onBack: null,
hideFooter: false,
},
{
id: 'updateMCU', id: 'updateMCU',
label: t('app:manager.modal.steps.updateMCU'), label: t('app:manager.modal.steps.updateMCU'),
component: StepFlashMcu, component: StepFlashMcu,
footer: ({ firmware, ...props }: StepProps) => ( footer: null,
<Fragment>
<DebugFooter firmware={firmware} {...props} where="idCheck" />
<DebugFooter firmware={firmware} {...props} where="finish" />
</Fragment>
),
onBack: null, onBack: null,
hideFooter: false, hideFooter: true,
},
finalStep,
]
} }
return [ const steps = [updateStep]
{
id: 'idCheck', if (firmware.shouldUpdateMcu) {
label: t('app:manager.modal.steps.idCheck'), steps.push(mcuStep)
component: StepFullFirmwareInstall, }
footer: ({ firmware, ...props }: StepProps) => (
<DebugFooter firmware={firmware} {...props} where="finish" /> steps.push(finalStep)
),
onBack: null, return steps
hideFooter: false,
},
finalStep,
]
} }
type Props = { type Props = {
t: T, t: T,
status: ModalStatus, status: ModalStatus,
onClose: () => void, onClose: () => void,
firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, firmware: Firmware,
installOsuFirmware: () => void, installOsuFirmware: (device: Device) => void,
installFinalFirmware: () => void, installFinalFirmware: (device: Device) => void,
flashMcu: () => void, flashMCU: (device: Device) => void,
stepId: StepId | string,
} }
type State = { type State = {
@ -113,10 +83,14 @@ type State = {
} }
class UpdateModal extends PureComponent<Props, State> { class UpdateModal extends PureComponent<Props, State> {
state = { static defaultProps = {
stepId: 'idCheck', stepId: 'idCheck',
} }
state = {
stepId: this.props.stepId,
}
STEPS = createSteps({ t: this.props.t, firmware: this.props.firmware }) STEPS = createSteps({ t: this.props.t, firmware: this.props.firmware })
handleStepChange = (step: Step) => this.setState({ stepId: step.id }) handleStepChange = (step: Step) => this.setState({ stepId: step.id })

79
src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js

@ -2,12 +2,21 @@
import React, { PureComponent, Fragment } from 'react' import React, { PureComponent, Fragment } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { connect } from 'react-redux'
import { timeout } from 'rxjs/operators/timeout'
import { DEVICE_INFOS_TIMEOUT } from 'config/constants'
import getDeviceInfo from 'commands/getDeviceInfo'
import { getCurrentDevice } from 'reducers/devices'
import { createCancelablePolling } from 'helpers/promise'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Text from 'components/base/Text' import Text from 'components/base/Text'
import Progress from 'components/base/Progress' import Progress from 'components/base/Progress'
import DeviceConfirm from 'components/DeviceConfirm' import DeviceConfirm from 'components/DeviceConfirm'
import type { Device } from 'types/common'
import type { StepProps } from '../' import type { StepProps } from '../'
const Container = styled(Box).attrs({ const Container = styled(Box).attrs({
@ -46,22 +55,74 @@ const Ellipsis = styled.span`
width: 100%; width: 100%;
` `
class StepFullFirmwareInstall extends PureComponent<StepProps, *> { type Props = StepProps & {
device: Device,
}
type State = {
installing: boolean,
}
class StepFullFirmwareInstall extends PureComponent<Props, State> {
state = {
installing: false,
}
componentDidMount() { componentDidMount() {
this.install() this.install()
} }
componentWillUnmount() {
if (this._unsubConnect) this._unsubConnect()
}
ensureDevice = () => {
const { unsubscribe, promise } = createCancelablePolling(async () => {
const { device } = this.props
if (!device) {
throw new Error('No device')
}
const deviceInfo = await getDeviceInfo
.send({ devicePath: device.path })
.pipe(timeout(DEVICE_INFOS_TIMEOUT))
.toPromise()
return { device, deviceInfo }
})
this._unsubConnect = unsubscribe
return promise
}
install = async () => { install = async () => {
const { installOsuFirmware, installFinalFirmware, transitionTo } = this.props const { installOsuFirmware, installFinalFirmware } = this.props
const success = await installOsuFirmware() const { device, deviceInfo } = await this.ensureDevice()
if (deviceInfo.isOSU) {
this.setState({ installing: true })
const finalSuccess = await installFinalFirmware(device)
if (finalSuccess) this.transitionTo()
}
const success = await installOsuFirmware(device)
if (success) { if (success) {
const finalSuccess = await installFinalFirmware() this.setState({ installing: true })
if (this._unsubConnect) this._unsubConnect()
const { device: cleanDevice } = await this.ensureDevice()
const finalSuccess = await installFinalFirmware(cleanDevice)
if (finalSuccess) { if (finalSuccess) {
transitionTo('finish') this.transitionTo()
} }
} }
} }
transitionTo = () => {
const { firmware, transitionTo } = this.props
if (firmware.shouldUpdateMcu) {
transitionTo('updateMCU')
} else {
transitionTo('finish')
}
}
renderBody = () => { renderBody = () => {
const { installing } = this.state const { installing } = this.state
const { firmware, t } = this.props const { firmware, t } = this.props
@ -91,6 +152,8 @@ class StepFullFirmwareInstall extends PureComponent<StepProps, *> {
) )
} }
_unsubConnect: *
render() { render() {
const { t } = this.props const { t } = this.props
return ( return (
@ -105,4 +168,8 @@ class StepFullFirmwareInstall extends PureComponent<StepProps, *> {
} }
} }
export default StepFullFirmwareInstall const mapStateToProps = state => ({
device: getCurrentDevice(state),
})
export default connect(mapStateToProps)(StepFullFirmwareInstall)

85
src/components/modals/UpdateFirmware/steps/01-step-osu-installer.js

@ -1,85 +0,0 @@
// @flow
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import DeviceConfirm from 'components/DeviceConfirm'
import type { StepProps } from '../'
const Container = styled(Box).attrs({
alignItems: 'center',
fontSize: 4,
color: 'dark',
px: 7,
})``
const Title = styled(Box).attrs({
ff: 'Museo Sans|Regular',
fontSize: 5,
mb: 3,
})``
const Address = styled(Box).attrs({
bg: p => (p.notValid ? 'transparent' : p.withQRCode ? 'white' : 'lightGrey'),
borderRadius: 1,
color: 'dark',
ff: 'Open Sans|SemiBold',
fontSize: 4,
mt: 2,
px: p => (p.notValid ? 0 : 4),
py: p => (p.notValid ? 0 : 3),
})`
border: ${p => (p.notValid ? 'none' : `1px dashed ${p.theme.colors.fog}`)};
cursor: text;
user-select: text;
width: 325px;
`
const Ellipsis = styled.span`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
`
class StepOSUInstaller extends PureComponent<StepProps, *> {
componentDidMount() {
this.install()
}
install = async () => {
const { installOsuFirmware, transitionTo } = this.props
const success = await installOsuFirmware()
if (success) {
transitionTo('updateMCU')
}
}
render() {
const { t, firmware } = this.props
return (
<Container>
<Title>{t('app:manager.modal.confirmIdentifier')}</Title>
<Text ff="Open Sans|Regular" align="center" color="smoke">
{t('app:manager.modal.confirmIdentifierText')}
</Text>
<Box mx={7} mt={5}>
<Text ff="Open Sans|SemiBold" align="center" color="smoke">
{t('app:manager.modal.identifier')}
</Text>
<Address>
<Ellipsis>{firmware && firmware.hash}</Ellipsis>
</Address>
</Box>
<Box mt={5}>
<DeviceConfirm />
</Box>
</Container>
)
}
}
export default StepOSUInstaller

38
src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js

@ -64,7 +64,8 @@ class StepFlashMcu extends PureComponent<Props, State> {
} }
componentWillUnmount() { componentWillUnmount() {
this._unsubConnect() if (this._unsubConnect) this._unsubConnect()
if (this._unsubDeviceInfo) this._unsubDeviceInfo()
} }
waitForDeviceInBootloader = () => { waitForDeviceInBootloader = () => {
@ -86,14 +87,38 @@ class StepFlashMcu extends PureComponent<Props, State> {
return promise return promise
} }
install = async () => { getDeviceInfo = () => {
const { unsubscribe, promise } = createCancelablePolling(async () => {
const { device } = this.props
if (!device) {
throw new Error('No device')
}
const deviceInfo = await getDeviceInfo
.send({ devicePath: device.path })
.pipe(timeout(DEVICE_INFOS_TIMEOUT))
.toPromise()
return { device, deviceInfo }
})
this._unsubDeviceInfo = unsubscribe
return promise
}
flash = async () => {
await this.waitForDeviceInBootloader() await this.waitForDeviceInBootloader()
const { flashMcu, installFinalFirmware, transitionTo } = this.props const { flashMCU, device } = this.props
if (device) {
this.setState({ installing: true }) this.setState({ installing: true })
await flashMcu() await flashMCU(device)
const finalSuccess = await installFinalFirmware() }
}
if (finalSuccess) { install = async () => {
const { transitionTo } = this.props
this.flash()
const deviceInfo = await this.getDeviceInfo()
if (deviceInfo.isBootloader) {
this.flash()
} else {
transitionTo('finish') transitionTo('finish')
} }
} }
@ -140,6 +165,7 @@ class StepFlashMcu extends PureComponent<Props, State> {
} }
_unsubConnect: * _unsubConnect: *
_unsubDeviceInfo: *
render() { render() {
const { t } = this.props const { t } = this.props

10
src/helpers/common.js

@ -51,6 +51,16 @@ export async function getFirmwareInfo(transport: Transport<*>) {
mcuVersion = mcuVersion.slice(0, mcuVersion.length - 1) mcuVersion = mcuVersion.slice(0, mcuVersion.length - 1)
} }
mcuVersion = mcuVersion.toString() mcuVersion = mcuVersion.toString()
if (!seVersionLength) {
return {
targetId,
seVersion: '0.0.0',
flags: '',
mcuVersion: '',
}
}
return { targetId, seVersion, flags, mcuVersion } return { targetId, seVersion, flags, mcuVersion }
} catch (err) { } catch (err) {
const error = new Error(err.message) const error = new Error(err.message)

3
src/helpers/firmware/installMcu.js

@ -9,7 +9,8 @@ import getDeviceInfo from 'helpers/devices/getDeviceInfo'
type Result = Promise<*> type Result = Promise<*>
export default async (transport: Transport<*>): Result => { export default async (transport: Transport<*>): Result => {
const { seVersion: version, targetId } = await getDeviceInfo(transport) const deviceInfo = await getDeviceInfo(transport)
const { seVersion: version, targetId } = deviceInfo
const nextVersion = await getNextMCU(version) const nextVersion = await getNextMCU(version)
const params = { const params = {
targetId, targetId,

4
src/helpers/firmware/installOsuFirmware.js

@ -4,7 +4,7 @@ import type Transport from '@ledgerhq/hw-transport'
import { WS_INSTALL } from 'helpers/urls' import { WS_INSTALL } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket' import { createDeviceSocket } from 'helpers/socket'
import type { LedgerScriptParams } from 'helpers/common' import type { Firmware } from 'components/modals/UpdateFirmware'
import { createCustomErrorClass } from '../errors' import { createCustomErrorClass } from '../errors'
@ -30,7 +30,7 @@ type Result = Promise<{ success: boolean, error?: any }>
export default async ( export default async (
transport: Transport<*>, transport: Transport<*>,
targetId: string | number, targetId: string | number,
firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, firmware: Firmware,
): Result => { ): Result => {
try { try {
const params = { const params = {

Loading…
Cancel
Save