Browse Source

Merge branch 'polish/manager-modals' into fix/circular-ref-error

master
Gaëtan Renaudeau 7 years ago
parent
commit
fbf3ff0d13
  1. 110
      src/components/ManagerPage/AppsList.js
  2. 15
      src/helpers/apps/installApp.js
  3. 14
      src/helpers/apps/uninstallApp.js
  4. 1
      src/icons/Trash.js
  5. 4
      static/i18n/en/errors.yml

110
src/components/ManagerPage/AppsList.js

@ -1,7 +1,7 @@
// @flow // @flow
/* eslint-disable react/jsx-no-literals */ // FIXME /* eslint-disable react/jsx-no-literals */ // FIXME
import React, { PureComponent } from 'react' import React, { PureComponent, Fragment } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
@ -11,17 +11,18 @@ import type { LedgerScriptParams } from 'helpers/common'
import listApps from 'commands/listApps' import listApps from 'commands/listApps'
import installApp from 'commands/installApp' import installApp from 'commands/installApp'
import uninstallApp from 'commands/uninstallApp' import uninstallApp from 'commands/uninstallApp'
import TranslatedError from 'components/TranslatedError'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Modal, { ModalBody } from 'components/base/Modal' import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal'
import Tooltip from 'components/base/Tooltip' import Tooltip from 'components/base/Tooltip'
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 Spinner from 'components/base/Spinner' import Spinner from 'components/base/Spinner'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import TranslatedError from 'components/TranslatedError'
import ExclamationCircle from 'icons/ExclamationCircle' import ExclamationCircle from 'icons/ExclamationCircle'
import ExclamationCircleThin from 'icons/ExclamationCircleThin'
import Update from 'icons/Update' import Update from 'icons/Update'
import Trash from 'icons/Trash' import Trash from 'icons/Trash'
import CheckCircle from 'icons/CheckCircle' import CheckCircle from 'icons/CheckCircle'
@ -133,41 +134,80 @@ class AppsList extends PureComponent<Props, State> {
<Modal <Modal
isOpened={status !== 'idle' && status !== 'loading'} isOpened={status !== 'idle' && status !== 'loading'}
render={() => ( render={() => (
<ModalBody p={6} align="center" justify="center" style={{ height: 300 }}> <ModalBody align="center" justify="center" style={{ height: 300 }}>
{status === 'busy' || status === 'idle' ? ( {status === 'busy' || status === 'idle' ? (
<Box align="center" justify="center" flow={3}> <Fragment>
{mode === 'installing' ? <Update size={30} /> : <Trash size={30} />} <ModalTitle>
<Text ff="Museo Sans|Regular" fontSize={6} color="dark"> {mode === 'installing' ? (
{t(`app:manager.apps.${mode}`, { app })} <Box color="grey">
</Text> <Update size={30} />
<Box my={5} style={{ width: 250 }}> </Box>
<Progress style={{ width: '100%' }} infinite /> ) : (
</Box> <Box color="grey">
</Box> <Trash size={30} />
</Box>
)}
</ModalTitle>
<ModalContent>
<Text ff="Museo Sans|Regular" fontSize={6} color="dark">
{t(`app:manager.apps.${mode}`, { app })}
</Text>
<Box mt={6}>
<Progress style={{ width: '100%' }} infinite />
</Box>
</ModalContent>
</Fragment>
) : status === 'error' ? ( ) : status === 'error' ? (
<Box align="center" justify="center" flow={3}> <Fragment>
<TranslatedError error={error} /> <ModalContent grow align="center" justify="center" mt={3}>
<Button primary onClick={this.handleCloseModal}> <Box color="alertRed">
close <ExclamationCircleThin size={44} />
</Button> </Box>
</Box> <Box
color="black"
mt={4}
fontSize={6}
ff="Museo Sans|Regular"
textAlign="center"
style={{ maxWidth: 350 }}
>
<TranslatedError error={error} />
</Box>
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end" style={{ width: '100%' }}>
<Button primary padded onClick={this.handleCloseModal}>
{t('app:common.close')}
</Button>
</ModalFooter>
</Fragment>
) : status === 'success' ? ( ) : status === 'success' ? (
<Box align="center" justify="center" flow={3}> <Fragment>
<Box color="positiveGreen"> <ModalContent grow align="center" justify="center" mt={3}>
<CheckCircle size={30} /> <Box color="positiveGreen">
</Box> <CheckCircle size={44} />
<Text ff="Museo Sans|Regular" fontSize={6} color="dark"> </Box>
{t( <Box
`app:manager.apps.${ color="black"
mode === 'installing' ? 'installSuccess' : 'uninstallSuccess' mt={4}
}`, fontSize={6}
{ app }, ff="Museo Sans|Regular"
)} textAlign="center"
</Text> style={{ maxWidth: 350 }}
<Button primary onClick={this.handleCloseModal}> >
close {t(
</Button> `app:manager.apps.${
</Box> mode === 'installing' ? 'installSuccess' : 'uninstallSuccess'
}`,
{ app },
)}
</Box>
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end" style={{ width: '100%' }}>
<Button primary padded onClick={this.handleCloseModal}>
{t('app:common.close')}
</Button>
</ModalFooter>
</Fragment>
) : null} ) : null}
</ModalBody> </ModalBody>
)} )}

15
src/helpers/apps/installApp.js

@ -7,6 +7,19 @@ import { createDeviceSocket } from 'helpers/socket'
import type { LedgerScriptParams } from 'helpers/common' import type { LedgerScriptParams } from 'helpers/common'
import createCustomErrorClass from '../createCustomErrorClass'
const CannotInstall = createCustomErrorClass('CannotInstall')
function remapError(promise) {
return promise.catch((e: Error) => {
if (e.message.endsWith('6982')) {
throw new CannotInstall()
}
throw e
})
}
/** /**
* Install an app on the device * Install an app on the device
*/ */
@ -21,5 +34,5 @@ export default async function installApp(
firmwareKey: app.firmware_key, firmwareKey: app.firmware_key,
} }
const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}` const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}`
return createDeviceSocket(transport, url).toPromise() return remapError(createDeviceSocket(transport, url).toPromise())
} }

14
src/helpers/apps/uninstallApp.js

@ -6,6 +6,18 @@ import { BASE_SOCKET_URL_SECURE } from 'config/constants'
import { createDeviceSocket } from 'helpers/socket' import { createDeviceSocket } from 'helpers/socket'
import type { LedgerScriptParams } from 'helpers/common' import type { LedgerScriptParams } from 'helpers/common'
import createCustomErrorClass from '../createCustomErrorClass'
const CannotUninstall = createCustomErrorClass('CannotUninstall')
function remapError(promise) {
return promise.catch((e: Error) => {
if (e.message.endsWith('6a83')) {
throw new CannotUninstall()
}
throw e
})
}
/** /**
* Install an app on the device * Install an app on the device
@ -22,5 +34,5 @@ export default async function uninstallApp(
firmwareKey: app.delete_key, firmwareKey: app.delete_key,
} }
const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}` const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}`
return createDeviceSocket(transport, url).toPromise() return remapError(createDeviceSocket(transport, url).toPromise())
} }

1
src/icons/Trash.js

@ -5,6 +5,7 @@ import React from 'react'
const path = ( const path = (
<g transform="translate(670.57 190.38)"> <g transform="translate(670.57 190.38)">
<path <path
fill="currentColor"
d="m-658.54-187.18h3.2002a0.80037 0.80037 0 0 1 0 1.5993h-0.80049v10.4a2.3999 2.3999 0 0 1-2.3999 2.3999h-8.0001a2.3999 2.3999 0 0 1-2.3999-2.3999v-10.4h-0.79878a0.80037 0.80037 0 1 1 0-1.5993h3.1991v-0.80049a2.3999 2.3999 0 0 1 2.3999-2.3999h3.2003a2.3999 2.3999 0 0 1 2.3999 2.3999zm-1.5993 0v-0.80049a0.80037 0.80037 0 0 0-0.80049-0.80049h-3.2003a0.80037 0.80037 0 0 0-0.79878 0.80049v0.80049zm0.80049 1.5993a0.84357 0.84357 0 0 1-1e-3 0h-6.3995a0.84357 0.84357 0 0 1-2e-3 0h-1.5976v10.4c0 0.44224 0.35825 0.79877 0.79878 0.79877h8.0001a0.80037 0.80037 0 0 0 0.8005-0.79877v-10.4zm-5.6004 3.2003a0.80037 0.80037 0 1 1 1.5993 0v4.7997a0.80037 0.80037 0 0 1-1.5993 0zm3.1992 0a0.80049 0.80049 0 1 1 1.601 0v4.7997a0.80049 0.80049 0 0 1-1.601 0z" d="m-658.54-187.18h3.2002a0.80037 0.80037 0 0 1 0 1.5993h-0.80049v10.4a2.3999 2.3999 0 0 1-2.3999 2.3999h-8.0001a2.3999 2.3999 0 0 1-2.3999-2.3999v-10.4h-0.79878a0.80037 0.80037 0 1 1 0-1.5993h3.1991v-0.80049a2.3999 2.3999 0 0 1 2.3999-2.3999h3.2003a2.3999 2.3999 0 0 1 2.3999 2.3999zm-1.5993 0v-0.80049a0.80037 0.80037 0 0 0-0.80049-0.80049h-3.2003a0.80037 0.80037 0 0 0-0.79878 0.80049v0.80049zm0.80049 1.5993a0.84357 0.84357 0 0 1-1e-3 0h-6.3995a0.84357 0.84357 0 0 1-2e-3 0h-1.5976v10.4c0 0.44224 0.35825 0.79877 0.79878 0.79877h8.0001a0.80037 0.80037 0 0 0 0.8005-0.79877v-10.4zm-5.6004 3.2003a0.80037 0.80037 0 1 1 1.5993 0v4.7997a0.80037 0.80037 0 0 1-1.5993 0zm3.1992 0a0.80049 0.80049 0 1 1 1.601 0v4.7997a0.80049 0.80049 0 0 1-1.601 0z"
strokeWidth="1.2" strokeWidth="1.2"
/> />

4
static/i18n/en/errors.yml

@ -16,8 +16,10 @@ NoAddressesFound: 'No accounts found'
UserRefusedOnDevice: Transaction have been aborted UserRefusedOnDevice: Transaction have been aborted
WebsocketConnectionError: An error occurred with the socket connection WebsocketConnectionError: An error occurred with the socket connection
WebsocketConnectionFailed: Failed to establish a socket connection WebsocketConnectionFailed: Failed to establish a socket connection
DeviceSocketFail: Device socket failure DeviceSocketFail: 'Device socket failure ({{message}})'
DeviceSocketNoBulkStatus: Device socket failure (bulk) DeviceSocketNoBulkStatus: Device socket failure (bulk)
DeviceSocketNoHandler: Device socket failure (handler {{query}}) DeviceSocketNoHandler: Device socket failure (handler {{query}})
LatestMCUInstalledError: The latest MCU is already installed on the Device LatestMCUInstalledError: The latest MCU is already installed on the Device
HardResetFail: Hard reset failure HardResetFail: Hard reset failure
CannotUninstall: Cannot uninstall app
CannotInstall: Cannot install app

Loading…
Cancel
Save