diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index f8feb6f7..ba343b78 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -1,7 +1,7 @@ // @flow /* eslint-disable react/jsx-no-literals */ // FIXME -import React, { PureComponent } from 'react' +import React, { PureComponent, Fragment } from 'react' import styled from 'styled-components' import { translate } from 'react-i18next' @@ -11,17 +11,18 @@ import type { LedgerScriptParams } from 'helpers/common' import listApps from 'commands/listApps' import installApp from 'commands/installApp' import uninstallApp from 'commands/uninstallApp' -import TranslatedError from 'components/TranslatedError' 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 Text from 'components/base/Text' import Progress from 'components/base/Progress' import Spinner from 'components/base/Spinner' import Button from 'components/base/Button' +import TranslatedError from 'components/TranslatedError' import ExclamationCircle from 'icons/ExclamationCircle' +import ExclamationCircleThin from 'icons/ExclamationCircleThin' import Update from 'icons/Update' import Trash from 'icons/Trash' import CheckCircle from 'icons/CheckCircle' @@ -133,41 +134,80 @@ class AppsList extends PureComponent { ( - + {status === 'busy' || status === 'idle' ? ( - - {mode === 'installing' ? : } - - {t(`app:manager.apps.${mode}`, { app })} - - - - - + + + {mode === 'installing' ? ( + + + + ) : ( + + + + )} + + + + {t(`app:manager.apps.${mode}`, { app })} + + + + + + ) : status === 'error' ? ( - - - - + + + + + + + + + + + + + ) : status === 'success' ? ( - - - - - - {t( - `app:manager.apps.${ - mode === 'installing' ? 'installSuccess' : 'uninstallSuccess' - }`, - { app }, - )} - - - + + + + + + + {t( + `app:manager.apps.${ + mode === 'installing' ? 'installSuccess' : 'uninstallSuccess' + }`, + { app }, + )} + + + + + + ) : null} )} diff --git a/src/helpers/apps/installApp.js b/src/helpers/apps/installApp.js index 2183d639..96f1af75 100644 --- a/src/helpers/apps/installApp.js +++ b/src/helpers/apps/installApp.js @@ -7,6 +7,19 @@ import { createDeviceSocket } from 'helpers/socket' 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 */ @@ -21,5 +34,5 @@ export default async function installApp( firmwareKey: app.firmware_key, } const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}` - return createDeviceSocket(transport, url).toPromise() + return remapError(createDeviceSocket(transport, url).toPromise()) } diff --git a/src/helpers/apps/uninstallApp.js b/src/helpers/apps/uninstallApp.js index 570e361c..6ead5304 100644 --- a/src/helpers/apps/uninstallApp.js +++ b/src/helpers/apps/uninstallApp.js @@ -6,6 +6,18 @@ import { BASE_SOCKET_URL_SECURE } from 'config/constants' import { createDeviceSocket } from 'helpers/socket' 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 @@ -22,5 +34,5 @@ export default async function uninstallApp( firmwareKey: app.delete_key, } const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}` - return createDeviceSocket(transport, url).toPromise() + return remapError(createDeviceSocket(transport, url).toPromise()) } diff --git a/src/icons/Trash.js b/src/icons/Trash.js index a6630967..992d7349 100644 --- a/src/icons/Trash.js +++ b/src/icons/Trash.js @@ -5,6 +5,7 @@ import React from 'react' const path = ( diff --git a/static/i18n/en/errors.yml b/static/i18n/en/errors.yml index 768cd711..9e24e1f5 100644 --- a/static/i18n/en/errors.yml +++ b/static/i18n/en/errors.yml @@ -16,8 +16,10 @@ NoAddressesFound: 'No accounts found' UserRefusedOnDevice: Transaction have been aborted WebsocketConnectionError: An error occurred with the socket connection WebsocketConnectionFailed: Failed to establish a socket connection -DeviceSocketFail: Device socket failure +DeviceSocketFail: 'Device socket failure ({{message}})' DeviceSocketNoBulkStatus: Device socket failure (bulk) DeviceSocketNoHandler: Device socket failure (handler {{query}}) LatestMCUInstalledError: The latest MCU is already installed on the Device HardResetFail: Hard reset failure +CannotUninstall: Cannot uninstall app +CannotInstall: Cannot install app