From bac0f094f3a9a96e120380f88743a06d317c060e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 22 Jun 2018 13:04:54 +0200 Subject: [PATCH 1/9] Add a logger.critical for raising exception to Sentry --- src/components/ThrowBlock.js | 2 +- src/logger.js | 16 ++++++++++++++++ src/renderer/init.js | 2 +- src/sentry/browser.js | 4 ++++ src/sentry/node.js | 4 ++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/components/ThrowBlock.js b/src/components/ThrowBlock.js index 89b0d497..195ee000 100644 --- a/src/components/ThrowBlock.js +++ b/src/components/ThrowBlock.js @@ -17,7 +17,7 @@ class ThrowBlock extends PureComponent { } componentDidCatch(error: Error) { - logger.error(error) + logger.critical(error) this.setState({ error }) } diff --git a/src/logger.js b/src/logger.js index cc6cfc82..0036f0fc 100644 --- a/src/logger.js +++ b/src/logger.js @@ -134,15 +134,31 @@ export default { console.log(...args) addLog('log', ...args) }, + warn: (...args: any) => { console.warn(...args) addLog('warn', ...args) }, + error: (...args: any) => { console.error(...args) addLog('error', ...args) }, + critical: (error: Error) => { + addLog('critical', error) + console.error(error) + try { + if (typeof window !== 'undefined') { + require('sentry/browser').captureException(error) + } else { + require('sentry/node').captureException(error) + } + } catch (e) { + console.warn("Can't send to sentry", error, e) + } + }, + exportLogs: (): Array<{ type: string, date: Date, args: Array }> => logs.map(({ type, date, args }) => ({ type, diff --git a/src/renderer/init.js b/src/renderer/init.js index a91a2087..6d711bf3 100644 --- a/src/renderer/init.js +++ b/src/renderer/init.js @@ -99,6 +99,6 @@ function r(Comp) { init().catch(e => { // for now we make the app crash instead of pending forever. later we can render the error OR try to recover, but probably this is unrecoverable cases. - logger.error(e) + logger.critical(e) r() }) diff --git a/src/sentry/browser.js b/src/sentry/browser.js index ac5fc55c..8b4b60d9 100644 --- a/src/sentry/browser.js +++ b/src/sentry/browser.js @@ -7,3 +7,7 @@ import install from './install' export default (shouldSendCallback: () => boolean) => { install(Raven, shouldSendCallback, user().id) } + +export const captureException = (e: Error) => { + Raven.captureException(e) +} diff --git a/src/sentry/node.js b/src/sentry/node.js index a617487b..bf19a6e3 100644 --- a/src/sentry/node.js +++ b/src/sentry/node.js @@ -6,3 +6,7 @@ import install from './install' export default (shouldSendCallback: () => boolean, userId: string) => { install(Raven, shouldSendCallback, userId) } + +export const captureException = (e: Error) => { + Raven.captureException(e) +} From 18529b02745b9be4e2b028a15e1500138969a647 Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 22 Jun 2018 14:39:34 +0200 Subject: [PATCH 2/9] Dont cache manager applications Because if you plug another device which have different firmware version, it will list incompatible apps. --- src/components/ManagerPage/AppsList.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index ba343b78..ce5c1c18 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -37,8 +37,6 @@ const List = styled(Box).attrs({ flex-wrap: wrap; ` -let CACHED_APPS = null - const ICONS_FALLBACK = { bitcoin_testnet: 'bitcoin', } @@ -85,8 +83,7 @@ class AppsList extends PureComponent { async fetchAppList() { try { const { targetId, version } = this.props - const appsList = CACHED_APPS || (await listApps.send({ targetId, version }).toPromise()) - CACHED_APPS = appsList + const appsList = await listApps.send({ targetId, version }).toPromise() if (!this._unmounted) { this.setState({ appsList, status: 'idle', appsLoaded: true }) } From a544f3cc856ef9ebfed5b0fa24c7634087c14479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 22 Jun 2018 14:40:15 +0200 Subject: [PATCH 3/9] Always show error in the RenderError --- src/components/RenderError.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/components/RenderError.js b/src/components/RenderError.js index 1ffa1b80..464b7674 100644 --- a/src/components/RenderError.js +++ b/src/components/RenderError.js @@ -10,7 +10,6 @@ import hardReset from 'helpers/hardReset' import type { T } from 'types/common' -import Spoiler from 'components/base/Spoiler' import ExportLogsBtn from 'components/ExportLogsBtn' import Box from 'components/base/Box' import Space from 'components/base/Space' @@ -94,17 +93,14 @@ ${error.stack} {t('app:crash.reset')} - - + - + + + +
{error.stack}
-
- - - {error.stack} - - + {children} ) @@ -114,14 +110,14 @@ ${error.stack} const ErrContainer = ({ children }: { children: any }) => (
     {children}

From 808716ab90d6eee2a6a90fc96026fe1678568376 Mon Sep 17 00:00:00 2001
From: meriadec 
Date: Fri, 22 Jun 2018 14:44:18 +0200
Subject: [PATCH 4/9] Display device informations and enable/disable firmware
 update based on env

---
 src/components/ManagerPage/Dashboard.js            | 14 ++++----------
 src/components/ManagerPage/UpdateFirmwareButton.js |  4 +++-
 2 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/src/components/ManagerPage/Dashboard.js b/src/components/ManagerPage/Dashboard.js
index 5b4eb971..f64df243 100644
--- a/src/components/ManagerPage/Dashboard.js
+++ b/src/components/ManagerPage/Dashboard.js
@@ -2,7 +2,6 @@
 import React from 'react'
 import { translate } from 'react-i18next'
 
-import { EXPERIMENTAL_FIRMWARE_UPDATE } from 'config/constants'
 import type { T, Device } from 'types/common'
 
 import Box from 'components/base/Box'
@@ -35,15 +34,10 @@ const Dashboard = ({ device, deviceInfo, t }: Props) => (
       
     
     
-      {EXPERIMENTAL_FIRMWARE_UPDATE ? (
-        
-      ) : null}
+      
     
     
       
diff --git a/src/components/ManagerPage/UpdateFirmwareButton.js b/src/components/ManagerPage/UpdateFirmwareButton.js
index 6f9cedcb..ebeb884c 100644
--- a/src/components/ManagerPage/UpdateFirmwareButton.js
+++ b/src/components/ManagerPage/UpdateFirmwareButton.js
@@ -4,6 +4,8 @@ import { translate } from 'react-i18next'
 
 import type { T } from 'types/common'
 
+import { EXPERIMENTAL_FIRMWARE_UPDATE } from 'config/constants'
+
 import Button from 'components/base/Button'
 import Text from 'components/base/Text'
 import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate'
@@ -25,7 +27,7 @@ const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) =>
       
         {t('app:manager.firmware.latest', { version: getCleanVersion(firmware.name) })}
       
-      
     

From f66530414e72317ccdae67c795254f1e1a087153 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= 
Date: Fri, 22 Jun 2018 15:30:11 +0200
Subject: [PATCH 5/9] also show the beta. don't use Translated to have the raw
 error

---
 src/components/RenderError.js | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/components/RenderError.js b/src/components/RenderError.js
index 464b7674..20f4f366 100644
--- a/src/components/RenderError.js
+++ b/src/components/RenderError.js
@@ -14,7 +14,6 @@ import ExportLogsBtn from 'components/ExportLogsBtn'
 import Box from 'components/base/Box'
 import Space from 'components/base/Space'
 import Button from 'components/base/Button'
-import TranslatedError from './TranslatedError'
 
 type Props = {
   error: Error,
@@ -95,12 +94,21 @@ ${error.stack}
         
         
           
-            
-              
-            
-            
{error.stack}
+ {String(error)} +
{error.stack || 'no stacktrace'}
+
+          {__APP_VERSION__}
+        
{children} ) From c1b5fe032d7c4ef8b7c66dc910515ed7f2a14eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 22 Jun 2018 15:41:13 +0200 Subject: [PATCH 6/9] old comment --- src/renderer/init.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/renderer/init.js b/src/renderer/init.js index 6d711bf3..065fde23 100644 --- a/src/renderer/init.js +++ b/src/renderer/init.js @@ -98,7 +98,6 @@ function r(Comp) { } init().catch(e => { - // for now we make the app crash instead of pending forever. later we can render the error OR try to recover, but probably this is unrecoverable cases. logger.critical(e) r() }) From c596982a576a87d32fdc562491769ce1c45ef206 Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 22 Jun 2018 15:22:20 +0200 Subject: [PATCH 7/9] Re-use our input component for apps list --- src/components/ManagerPage/AppSearchBar.js | 91 +++++++--------------- src/components/ManagerPage/AppsList.js | 28 +++---- 2 files changed, 43 insertions(+), 76 deletions(-) diff --git a/src/components/ManagerPage/AppSearchBar.js b/src/components/ManagerPage/AppSearchBar.js index e728a91a..7b33b49e 100644 --- a/src/components/ManagerPage/AppSearchBar.js +++ b/src/components/ManagerPage/AppSearchBar.js @@ -1,14 +1,12 @@ // @flow -import React, { PureComponent } from 'react' -import styled from 'styled-components' -import { color, fontSize, space } from 'styled-system' -import fontFamily from 'styles/styled/fontFamily' -import type { LedgerScriptParams } from 'helpers/common' +import React, { PureComponent, Fragment } from 'react' -import { ff } from 'styles/helpers' +import type { LedgerScriptParams } from 'helpers/common' import Box from 'components/base/Box' +import Space from 'components/base/Space' +import Input from 'components/base/Input' import Search from 'components/base/Search' import SearchIcon from 'icons/Search' @@ -24,53 +22,13 @@ type State = { focused: boolean, } -const SearchBarWrapper = styled(Box).attrs({ - horizontal: true, - borderRadius: 4, -})` - height: 42px; - width: 100%; - margin: 0 0 20px 0; - background-color: white; - padding: 0 13px; - - ${p => - p.focused - ? ` - border: 1px solid #6490f1; - ` - : 'border: 1px solid white;'}; -` - -const Input = styled.input.attrs({ - ff: 'Open Sans|SemiBold', - color: 'dark', - mx: 3, - fontSize: 4, -})` - ${space}; - ${fontFamily}; - ${fontSize}; - ${color}; - - border: 0; - flex: 1; - outline: none; - background: transparent; - - &::placeholder { - color: ${p => p.theme.colors.fog}; - ${() => ff('Open Sans|Regular')}; - } -` - class AppSearchBar extends PureComponent { state = { query: '', focused: false, } - handleChange = (e: any) => this.setState({ query: e.target.value }) + handleChange = (query: string) => this.setState({ query }) handleFocus = (bool: boolean) => () => this.setState({ focused: bool }) @@ -88,20 +46,29 @@ class AppSearchBar extends PureComponent { const color = focused ? 'black' : 'grey' return ( - - - - (this.input = c)} - type="text" - value={query} - onChange={this.handleChange} - onFocus={this.handleFocus(true)} - onBlur={this.handleFocus(false)} - placeholder={'Search app'} - /> - {!!query && } - + + (this.input = c)} + type="text" + value={query} + onChange={this.handleChange} + onFocus={this.handleFocus(true)} + onBlur={this.handleFocus(false)} + placeholder={'Search app'} + renderLeft={ + + + + } + renderRight={ + query ? ( + + + + ) : null + } + /> + { items={list} render={items => children(items)} /> - + ) } } diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index ce5c1c18..0ba3dea5 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -21,7 +21,7 @@ import Spinner from 'components/base/Spinner' import Button from 'components/base/Button' import TranslatedError from 'components/TranslatedError' -import ExclamationCircle from 'icons/ExclamationCircle' +import IconInfoCircle from 'icons/InfoCircle' import ExclamationCircleThin from 'icons/ExclamationCircleThin' import Update from 'icons/Update' import Trash from 'icons/Trash' @@ -246,19 +246,19 @@ class AppsList extends PureComponent { return ( - - {t('app:manager.apps.all')} - - ( - - {t('app:manager.apps.help')} - - )} - > - - - + + {t('app:manager.apps.all')} + ( + + {t('app:manager.apps.help')} + + )} + > + + + + {this.renderList()} From 89e9249b49db8a2b9dbd6c56fb70bcdc50ee6a63 Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 22 Jun 2018 15:45:04 +0200 Subject: [PATCH 8/9] More precise error messages on install/uninstall apps --- src/helpers/apps/installApp.js | 20 ++++++++++++++++---- src/helpers/apps/uninstallApp.js | 14 ++++++++++---- static/i18n/en/errors.yml | 10 ++++++++-- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/helpers/apps/installApp.js b/src/helpers/apps/installApp.js index 96f1af75..00dfb4fd 100644 --- a/src/helpers/apps/installApp.js +++ b/src/helpers/apps/installApp.js @@ -9,14 +9,26 @@ import type { LedgerScriptParams } from 'helpers/common' import createCustomErrorClass from '../createCustomErrorClass' -const CannotInstall = createCustomErrorClass('CannotInstall') +const ManagerUnexpectedError = createCustomErrorClass('ManagerUnexpected') +const ManagerNotEnoughSpaceError = createCustomErrorClass('ManagerNotEnoughSpace') +const ManagerDeviceLockedError = createCustomErrorClass('ManagerDeviceLocked') +const ManagerAppAlreadyInstalledError = createCustomErrorClass('ManagerAppAlreadyInstalled') +const ManagerAppRelyOnBTCError = createCustomErrorClass('ManagerAppRelyOnBTC') function remapError(promise) { return promise.catch((e: Error) => { - if (e.message.endsWith('6982')) { - throw new CannotInstall() + switch (true) { + case e.message.endsWith('6982'): + throw new ManagerDeviceLockedError() + case e.message.endsWith('6a84') || e.message.endsWith('6a85'): + throw new ManagerNotEnoughSpaceError() + case e.message.endsWith('6a80') || e.message.endsWith('6a81'): + throw new ManagerAppAlreadyInstalledError() + case e.message.endsWith('6a83'): + throw new ManagerAppRelyOnBTCError() + default: + throw new ManagerUnexpectedError(e.message, { msg: e.message }) } - throw e }) } diff --git a/src/helpers/apps/uninstallApp.js b/src/helpers/apps/uninstallApp.js index 6ead5304..1611a1b4 100644 --- a/src/helpers/apps/uninstallApp.js +++ b/src/helpers/apps/uninstallApp.js @@ -8,14 +8,20 @@ import { createDeviceSocket } from 'helpers/socket' import type { LedgerScriptParams } from 'helpers/common' import createCustomErrorClass from '../createCustomErrorClass' -const CannotUninstall = createCustomErrorClass('CannotUninstall') +const ManagerUnexpectedError = createCustomErrorClass('ManagerUnexpectedError') +const ManagerDeviceLockedError = createCustomErrorClass('ManagerDeviceLocked') +const ManagerUninstallBTCDep = createCustomErrorClass('ManagerUninstallBTCDep') function remapError(promise) { return promise.catch((e: Error) => { - if (e.message.endsWith('6a83')) { - throw new CannotUninstall() + switch (true) { + case e.message.endsWith('6982'): + throw new ManagerDeviceLockedError() + case e.message.endsWith('6a83'): + throw new ManagerUninstallBTCDep() + default: + throw new ManagerUnexpectedError(e.message, { msg: e.message }) } - throw e }) } diff --git a/static/i18n/en/errors.yml b/static/i18n/en/errors.yml index 95ce4465..640ff96d 100644 --- a/static/i18n/en/errors.yml +++ b/static/i18n/en/errors.yml @@ -21,5 +21,11 @@ DeviceSocketNoBulkStatus: Oops, device connection failed. Please try again [bulk DeviceSocketNoHandler: Oops, device connection failed (handler {{query}}). Please try again. LatestMCUInstalledError: MCU on device already up to date. HardResetFail: Reset failed. Please try again. -CannotUninstall: Cannot uninstall app. -CannotInstall: Not enough room left on your device. Please uninstall some apps and try again. + +ManagerAPIsFail: Our services are currently unavailable. Please try again later. +ManagerUnexpected: Unexpected error occurred ({{msg}}). Please try again later. +ManagerNotEnoughSpace: Not enough room left on your device. Please uninstall some apps and try again. +ManagerDeviceLocked: Device is locked +ManagerAppAlreadyInstalled: App is already installed +ManagerAppRelyOnBTC: You must install Bitcoin application first +ManagerUninstallBTCDep: You must uninstall other altcoins first From 03d488d1c75961926e491c297e3fbbf7744a902a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 22 Jun 2018 16:07:39 +0200 Subject: [PATCH 9/9] add clubcoin --- src/config/cryptocurrencies.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/cryptocurrencies.js b/src/config/cryptocurrencies.js index 0b097368..894cdeef 100644 --- a/src/config/cryptocurrencies.js +++ b/src/config/cryptocurrencies.js @@ -26,6 +26,7 @@ const supported: CryptoCurrencyIds[] = [ 'viacoin', 'stealthcoin', 'poswallet', + 'clubcoin', 'bitcoin_testnet', ]