Browse Source

wip update firmware final

master
Valentin D. Pinkman 7 years ago
parent
commit
c876e4e162
No known key found for this signature in database GPG Key ID: E7D110669FFB8D3E
  1. 12
      src/commands/installFinalFirmware.js
  2. 17
      src/components/ManagerPage/AppsList.js
  3. 30
      src/components/ManagerPage/FirmwareFinalUpdate.js
  4. 61
      src/components/ManagerPage/FirmwareUpdate.js
  5. 4
      src/components/ManagerPage/UpdateFirmwareButton.js
  6. 66
      src/components/ManagerPage/index.js
  7. 26
      src/helpers/devices/getOsuFirmware.js
  8. 15
      src/helpers/firmware/getFinalFirmwareById.js
  9. 24
      src/helpers/firmware/installFinalFirmware.js
  10. 2
      src/helpers/urls.js
  11. 4
      static/i18n/en/app.yml

12
src/commands/installFinalFirmware.js

@ -8,20 +8,18 @@ import installFinalFirmware from 'helpers/firmware/installFinalFirmware'
type Input = {
devicePath: string,
firmware: Object,
targetId: string | number,
version: string,
}
type Result = {
targetId: number | string,
version: string,
final: boolean,
mcu: boolean,
success: boolean,
}
const cmd: Command<Input, Result> = createCommand(
'installFinalFirmware',
({ devicePath, firmware }) =>
fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, firmware))),
({ devicePath, ...rest }) =>
fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, { ...rest }))),
)
export default cmd

17
src/components/ManagerPage/AppsList.js

@ -53,8 +53,9 @@ type Props = {
type State = {
status: Status,
error: string | null,
appsList: LedgerScriptParams[] | Array<*>,
error: ?Error,
appsList: LedgerScriptParams[],
appsLoaded: boolean,
app: string,
mode: Mode,
}
@ -64,6 +65,7 @@ class AppsList extends PureComponent<Props, State> {
status: 'loading',
error: null,
appsList: [],
appsLoaded: false,
app: '',
mode: 'home',
}
@ -84,7 +86,7 @@ class AppsList extends PureComponent<Props, State> {
const appsList = CACHED_APPS || (await listApps.send({ targetId, version }).toPromise())
CACHED_APPS = appsList
if (!this._unmounted) {
this.setState({ appsList, status: 'idle' })
this.setState({ appsList, status: 'idle', appsLoaded: true })
}
} catch (err) {
this.setState({ status: 'error', error: err.message })
@ -100,9 +102,9 @@ class AppsList extends PureComponent<Props, State> {
} = this.props
const data = { app, devicePath, targetId }
await installApp.send(data).toPromise()
this.setState({ status: 'success', app: '' })
this.setState({ status: 'success' })
} catch (err) {
this.setState({ status: 'error', error: err.message, app: '', mode: 'home' })
this.setState({ status: 'error', error: err, mode: 'home' })
}
}
@ -126,7 +128,6 @@ class AppsList extends PureComponent<Props, State> {
renderModal = () => {
const { t } = this.props
const { app, status, error, mode } = this.state
return (
<Modal
isOpened={status !== 'idle' && status !== 'loading'}
@ -175,8 +176,8 @@ class AppsList extends PureComponent<Props, State> {
}
renderList() {
const { appsList, status } = this.state
return status === 'idle' ? (
const { appsList, appsLoaded } = this.state
return appsLoaded ? (
<Box>
<AppSearchBar list={appsList}>
{items => (

30
src/components/ManagerPage/FinalFirmwareUpdate.js → src/components/ManagerPage/FirmwareFinalUpdate.js

@ -2,8 +2,12 @@
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import logger from 'logger'
import type { Device, T } from 'types/common'
import installFinalFirmware from 'commands/installFinalFirmware'
import Box, { Card } from 'components/base/Box'
// import Button from 'components/base/Button'
@ -18,15 +22,9 @@ type Props = {
infos: DeviceInfos,
}
type State = {
// latestFirmware: ?FirmwareInfos,
}
class FirmwareUpdate extends PureComponent<Props, State> {
state = {
// latestFirmware: null,
}
type State = {}
class FirmwareFinalUpdate extends PureComponent<Props, State> {
componentDidMount() {}
componentWillUnmount() {
@ -35,6 +33,20 @@ class FirmwareUpdate extends PureComponent<Props, State> {
_unmounting = false
installFinalFirmware = async () => {
try {
const { device, infos } = this.props
const { success } = await installFinalFirmware
.send({ devicePath: device.path, targetId: infos.targetId, version: infos.version })
.toPromise()
if (success) {
this.setState()
}
} catch (err) {
logger.log(err)
}
}
render() {
const { t, ...props } = this.props
@ -51,4 +63,4 @@ class FirmwareUpdate extends PureComponent<Props, State> {
}
}
export default translate()(FirmwareUpdate)
export default translate()(FirmwareFinalUpdate)

61
src/components/ManagerPage/FirmwareUpdate.js

@ -1,8 +1,8 @@
// @flow
/* eslint-disable react/jsx-no-literals */ // FIXME
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import React, { PureComponent, Fragment } from 'react'
import { translate, Trans } from 'react-i18next'
import isEqual from 'lodash/isEqual'
import isEmpty from 'lodash/isEmpty'
import invariant from 'invariant'
@ -17,6 +17,9 @@ import installOsuFirmware from 'commands/installOsuFirmware'
import Box, { Card } from 'components/base/Box'
import Text from 'components/base/Text'
import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal'
import Button from 'components/base/Button'
// import Progress from 'components/base/Progress'
import NanoS from 'icons/device/NanoS'
import CheckFull from 'icons/CheckFull'
@ -25,11 +28,16 @@ import UpdateFirmwareButton from './UpdateFirmwareButton'
let CACHED_LATEST_FIRMWARE = null
export const getCleanVersion = (input: string): string =>
input.endsWith('-osu') ? input.replace('-osu', '') : input
type DeviceInfos = {
targetId: number | string,
version: string,
}
type ModalStatus = 'closed' | 'disclaimer' | 'installing' | 'error' | 'success'
type Props = {
t: T,
device: Device,
@ -38,11 +46,13 @@ type Props = {
type State = {
latestFirmware: ?LedgerScriptParams,
modal: ModalStatus,
}
class FirmwareUpdate extends PureComponent<Props, State> {
state = {
latestFirmware: null,
modal: 'closed',
}
componentDidMount() {
@ -86,6 +96,7 @@ class FirmwareUpdate extends PureComponent<Props, State> {
const {
device: { path: devicePath },
} = this.props
this.setState({ modal: 'installing' })
const { success } = await installOsuFirmware
.send({ devicePath, firmware: latestFirmware, targetId: infos.targetId })
.toPromise()
@ -97,6 +108,46 @@ class FirmwareUpdate extends PureComponent<Props, State> {
}
}
handleCloseModal = () => this.setState({ modal: 'closed' })
handleInstallModal = () => this.setState({ modal: 'disclaimer' })
renderModal = () => {
const { t } = this.props
const { modal, latestFirmware } = this.state
return (
<Modal
isOpened={modal !== 'closed'}
render={() => (
<ModalBody grow align="center" justify="center" mt={3}>
<Fragment>
<ModalTitle>{t('app:manager.firmware.update')}</ModalTitle>
<ModalContent>
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center">
<Trans i18nKey="app:manager.firmware.disclaimerTitle">
You are about to install the latest
<Text ff="Open Sans|SemiBold" color="dark">
{`firmware ${latestFirmware ? getCleanVersion(latestFirmware.name) : ''}`}
</Text>
</Trans>
</Text>
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center">
{t('app:manager.firmware.disclaimerAppDelete')}
{t('app:manager.firmware.disclaimerAppReinstall')}
</Text>
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end" style={{ width: '100%' }}>
<Button primary padded onClick={this.installFirmware}>
{t('app:manager.firmware.continue')}
</Button>
</ModalFooter>
</Fragment>
</ModalBody>
)}
/>
)
}
render() {
const { infos, t } = this.props
const { latestFirmware } = this.state
@ -122,8 +173,12 @@ class FirmwareUpdate extends PureComponent<Props, State> {
})}
</Text>
</Box>
<UpdateFirmwareButton firmware={latestFirmware} installFirmware={this.installFirmware} />
<UpdateFirmwareButton
firmware={latestFirmware}
installFirmware={this.handleInstallModal}
/>
</Box>
{this.renderModal()}
</Card>
)
}

4
src/components/ManagerPage/UpdateFirmwareButton.js

@ -6,6 +6,7 @@ import type { T } from 'types/common'
import Button from 'components/base/Button'
import Text from 'components/base/Text'
import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate'
type FirmwareInfos = {
name: string,
@ -18,9 +19,6 @@ type Props = {
installFirmware: () => void,
}
const getCleanVersion = (input: string): string =>
input.endsWith('-osu') ? input.replace('-osu', '') : input
const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) =>
firmware ? (
<Fragment>

66
src/components/ManagerPage/index.js

@ -1,7 +1,7 @@
// @flow
/* eslint-disable react/jsx-no-literals */ // FIXME
/* eslint-disable react/jsx-no-literals */ // FIXME: remove
import React from 'react'
import React, { PureComponent } from 'react'
import type { Node } from 'react'
import type { Device } from 'types/common'
@ -23,36 +23,38 @@ type Error = {
stack: string,
}
function ManagerPage(): Node {
return (
<Workflow
renderFinalUpdate={(device: Device, deviceInfo: DeviceInfo) => (
<p>UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.final}</p>
)}
renderMcuUpdate={(device: Device, deviceInfo: DeviceInfo) => (
<FlashMcu device={device} deviceInfo={deviceInfo} />
)}
renderDashboard={(device: Device, deviceInfo: DeviceInfo) => (
<Dashboard device={device} deviceInfo={deviceInfo} />
)}
renderDefault={(
device: ?Device,
deviceInfo: ?DeviceInfo,
isGenuine: ?boolean,
errors: {
dashboardError: ?Error,
genuineError: ?Error,
},
) => (
<WorkflowWithIcon
device={device}
deviceInfo={deviceInfo}
errors={errors}
isGenuine={isGenuine}
/>
)}
/>
)
class ManagerPage extends PureComponent<*, *> {
render() {
return (
<Workflow
renderFinalUpdate={(device: Device, deviceInfo: DeviceInfo) => (
<p>UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.final}</p>
)}
renderMcuUpdate={(device: Device, deviceInfo: DeviceInfo) => (
<FlashMcu device={device} deviceInfo={deviceInfo} />
)}
renderDashboard={(device: Device, deviceInfo: DeviceInfo) => (
<Dashboard device={device} deviceInfo={deviceInfo} />
)}
renderDefault={(
device: ?Device,
deviceInfo: ?DeviceInfo,
isGenuine: ?boolean,
errors: {
dashboardError: ?Error,
genuineError: ?Error,
},
) => (
<WorkflowWithIcon
device={device}
deviceInfo={deviceInfo}
errors={errors}
isGenuine={isGenuine}
/>
)}
/>
)
}
}
export default ManagerPage

26
src/helpers/devices/getOsuFirmware.js

@ -0,0 +1,26 @@
// @flow
import axios from 'axios'
import { GET_CURRENT_OSU } from 'helpers/urls'
type Input = {
version: string,
deviceId: string | number,
}
let error
export default async (input: Input): Promise<*> => {
try {
const provider = 1
const { data } = await axios.post(GET_CURRENT_OSU, {
device_version: input.deviceId,
version_name: input.version,
provider,
})
return data
} catch (err) {
error = Error(err.message)
error.stack = err.stack
throw error
}
}

15
src/helpers/firmware/getFinalFirmwareById.js

@ -0,0 +1,15 @@
// @flow
import axios from 'axios'
import { GET_FINAL_FIRMWARE } from 'helpers/urls'
export default async (id: number) => {
try {
const { data } = await axios.get(`${GET_FINAL_FIRMWARE}/${id}`)
return data
} catch (err) {
const error = Error(err.message)
error.stack = err.stack
throw err
}
}

24
src/helpers/firmware/installFinalFirmware.js

@ -3,13 +3,31 @@ import type Transport from '@ledgerhq/hw-transport'
import { WS_INSTALL } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket'
import getDeviceVersion from 'helpers/devices/getDeviceVersion'
import getOsuFirmware from 'helpers/devices/getOsuFirmware'
import getFinalFirmwareById from './getFinalFirmwareById'
type Input = Object
type Input = {
targetId: number | string,
version: string,
}
type Result = *
export default async (transport: Transport<*>, firmware: Input): Result => {
export default async (transport: Transport<*>, app: Input): Result => {
try {
const url = WS_INSTALL(firmware)
const { targetId, version } = app
const device = await getDeviceVersion(targetId)
const firmware = await getOsuFirmware({ deviceId: device.id, version })
const { next_se_firmware_final_version } = firmware
const nextFirmware = await getFinalFirmwareById(next_se_firmware_final_version)
const params = {
targetId,
...nextFirmware,
firmwareKey: nextFirmware.firmware_key,
}
const url = WS_INSTALL(params)
await createDeviceSocket(transport, url).toPromise()
return { success: true }
} catch (err) {

2
src/helpers/urls.js

@ -14,9 +14,11 @@ const wsURLBuilder = (endpoint: string) => (params?: Object) =>
// const wsURLBuilderProxy = (endpoint: string) => (params?: Object) =>
// `ws://manager.ledger.fr:3501/${endpoint}${params ? `?${qs.stringify(params)}` : ''}`
export const GET_FINAL_FIRMWARE: string = managerUrlbuilder('firmware_final_versions')
export const GET_DEVICE_VERSION: string = managerUrlbuilder('get_device_version')
export const APPLICATIONS_BY_DEVICE: string = managerUrlbuilder('get_apps')
export const GET_CURRENT_FIRMWARE: string = managerUrlbuilder('get_firmware_version')
export const GET_CURRENT_OSU: string = managerUrlbuilder('get_osu_version')
export const GET_LATEST_FIRMWARE: string = managerUrlbuilder('get_latest_firmware')
export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader')

4
static/i18n/en/app.yml

@ -187,7 +187,11 @@ manager:
installed: 'Firmware {{version}}'
update: Update firmware
updateTitle: Firmware update
continue: Continue update
latest: 'A new firmware {{version}} is available'
disclaimerTitle: 'You are about to install the latest <1><0>firmware {{version}}</0></1>'
disclaimerAppDelete: Please note that all the apps installed on your device will be deleted.
disclaimerAppReinstall: You will be able to re-install your apps after the firmware update
title: Manager
subtitle: Get all your apps here
device:

Loading…
Cancel
Save