diff --git a/src/components/AppError.js b/src/components/AppError.js
new file mode 100644
index 00000000..7ae0ca90
--- /dev/null
+++ b/src/components/AppError.js
@@ -0,0 +1,23 @@
+// @flow
+
+import React from 'react'
+import { ThemeProvider } from 'styled-components'
+import { I18nextProvider } from 'react-i18next'
+import theme from 'styles/theme'
+import i18n from 'renderer/i18n/electron'
+import TriggerAppReady from './TriggerAppReady'
+import RenderError from './RenderError'
+
+// Like App except it just render an error
+
+const App = ({ language, error }: { error: Error, language: string }) => (
+
+
+
+
+
+
+
+)
+
+export default App
diff --git a/src/components/RenderError.js b/src/components/RenderError.js
new file mode 100644
index 00000000..f8fb8a42
--- /dev/null
+++ b/src/components/RenderError.js
@@ -0,0 +1,97 @@
+// @flow
+
+import React, { PureComponent } from 'react'
+import styled from 'styled-components'
+import { shell, remote } from 'electron'
+import qs from 'querystring'
+import { translate } from 'react-i18next'
+
+import { rgba } from 'styles/helpers'
+import db from 'helpers/db'
+
+import type { T } from 'types/common'
+
+import ExportLogsBtn from 'components/ExportLogsBtn'
+import Box from 'components/base/Box'
+import Button from 'components/base/Button'
+import TranslatedError from './TranslatedError'
+
+type Props = {
+ error: Error,
+ t: T,
+ disableExport?: boolean,
+ children?: *,
+}
+
+const Container = styled(Box).attrs({
+ grow: true,
+ align: 'center',
+ justify: 'center',
+ bg: 'lightGraphite',
+ color: 'alertRed',
+ ff: 'Museo Sans|Bold',
+ flow: 2,
+})``
+
+const Inner = styled(Box).attrs({
+ p: 2,
+ bg: p => rgba(p.theme.colors.alertRed, 0.05),
+ borderRadius: 1,
+})`
+ border: ${p => `1px solid ${rgba(p.theme.colors.alertRed, 0.1)}`};
+`
+
+class RenderError extends PureComponent {
+ handleCreateIssue = () => {
+ const { error } = this.props
+ if (!error) {
+ return
+ }
+ const q = qs.stringify({
+ title: `Error: ${error.message}`,
+ body: `Error was thrown:
+
+\`\`\`
+${error.stack}
+\`\`\`
+`,
+ })
+ shell.openExternal(`https://github.com/LedgerHQ/ledger-live-desktop/issues/new?${q}`)
+ }
+
+ handleRestart = () => {
+ remote.app.relaunch()
+ remote.app.exit()
+ }
+
+ handleReset = () => {
+ db.resetAll()
+ this.handleRestart()
+ }
+
+ render() {
+ const { error, t, disableExport, children } = this.props
+ return (
+
+
+
+
+
+
+
+ {!disableExport ? : null}
+
+
+ {children}
+
+ )
+ }
+}
+
+export default translate()(RenderError)
diff --git a/src/components/ThrowBlock.js b/src/components/ThrowBlock.js
index 4ca6a52e..89b0d497 100644
--- a/src/components/ThrowBlock.js
+++ b/src/components/ThrowBlock.js
@@ -1,49 +1,16 @@
// @flow
-
import logger from 'logger'
import React, { PureComponent } from 'react'
-import styled from 'styled-components'
-import { shell, remote } from 'electron'
-import qs from 'querystring'
-import { translate } from 'react-i18next'
-
-import { rgba } from 'styles/helpers'
-import db from 'helpers/db'
-
-import type { T } from 'types/common'
-
-import ExportLogsBtn from 'components/ExportLogsBtn'
-import Box from 'components/base/Box'
-import Button from 'components/base/Button'
-import TranslatedError from './TranslatedError'
+import RenderError from 'components/RenderError'
type Props = {
children: any,
- t: T,
}
type State = {
error: ?Error,
}
-const Container = styled(Box).attrs({
- grow: true,
- align: 'center',
- justify: 'center',
- bg: 'lightGraphite',
- color: 'alertRed',
- ff: 'Museo Sans|Bold',
- flow: 2,
-})``
-
-const Inner = styled(Box).attrs({
- p: 2,
- bg: p => rgba(p.theme.colors.alertRed, 0.05),
- borderRadius: 1,
-})`
- border: ${p => `1px solid ${rgba(p.theme.colors.alertRed, 0.1)}`};
-`
-
class ThrowBlock extends PureComponent {
state = {
error: null,
@@ -54,59 +21,13 @@ class ThrowBlock extends PureComponent {
this.setState({ error })
}
- handleCreateIssue = () => {
- const { error } = this.state
- if (!error) {
- return
- }
- const q = qs.stringify({
- title: `Error: ${error.message}`,
- body: `Error was thrown:
-
-\`\`\`
-${error.stack}
-\`\`\`
-`,
- })
- shell.openExternal(`https://github.com/LedgerHQ/ledger-live-desktop/issues/new?${q}`)
- }
-
- handleRestart = () => {
- remote.app.relaunch()
- remote.app.exit()
- }
-
- handleReset = () => {
- db.resetAll()
- this.handleRestart()
- }
-
render() {
const { error } = this.state
- const { t } = this.props
if (error) {
- return (
-
-
-
-
-
-
-
-
-
-
-
- )
+ return
}
return this.props.children
}
}
-export default translate()(ThrowBlock)
+export default ThrowBlock
diff --git a/src/components/TranslatedError.js b/src/components/TranslatedError.js
index d9d3f8b5..ff2ec07d 100644
--- a/src/components/TranslatedError.js
+++ b/src/components/TranslatedError.js
@@ -23,7 +23,7 @@ class TranslatedError extends PureComponent {
if (translation) {
return translation
}
- logger.warn('TranslatedError: no transation!', error.name, error)
+ logger.warn(`TranslatedError: no translation for '${error.name}'`, error)
return error.message || error.name || t('errors:generic')
}
}
diff --git a/src/components/TriggerAppReady.js b/src/components/TriggerAppReady.js
new file mode 100644
index 00000000..e47f2ed2
--- /dev/null
+++ b/src/components/TriggerAppReady.js
@@ -0,0 +1,16 @@
+// @flow
+
+import { PureComponent } from 'react'
+
+export default class TriggerAppReady extends PureComponent<{}> {
+ componentDidMount() {
+ window.requestAnimationFrame(() => (this._timeout = setTimeout(() => window.onAppReady(), 300)))
+ }
+ componentWillUnmount() {
+ clearTimeout(this._timeout)
+ }
+ _timeout: *
+ render() {
+ return null
+ }
+}
diff --git a/src/components/layout/Default.js b/src/components/layout/Default.js
index c9a16c8c..c107392e 100644
--- a/src/components/layout/Default.js
+++ b/src/components/layout/Default.js
@@ -19,6 +19,7 @@ import ExchangePage from 'components/ExchangePage'
import SettingsPage from 'components/SettingsPage'
import LibcoreBusyIndicator from 'components/LibcoreBusyIndicator'
import DeviceBusyIndicator from 'components/DeviceBusyIndicator'
+import TriggerAppReady from 'components/TriggerAppReady'
import AppRegionDrag from 'components/AppRegionDrag'
import IsUnlocked from 'components/IsUnlocked'
@@ -41,7 +42,6 @@ type Props = {
class Default extends Component {
componentDidMount() {
- window.requestAnimationFrame(() => (this._timeout = setTimeout(() => window.onAppReady(), 300)))
window.addEventListener('keydown', this.kbShortcut)
}
@@ -59,7 +59,6 @@ class Default extends Component {
}
componentWillUnmount() {
- clearTimeout(this._timeout)
window.removeEventListener('keydown', this.kbShortcut) // Prevents adding multiple listeners when hot reloading
}
@@ -69,12 +68,12 @@ class Default extends Component {
}
}
- _timeout = undefined
_scrollContainer = null
render() {
return (
+
{process.platform === 'darwin' && }
diff --git a/src/renderer/init.js b/src/renderer/init.js
index 0ad9407d..a91a2087 100644
--- a/src/renderer/init.js
+++ b/src/renderer/init.js
@@ -27,6 +27,7 @@ import hardReset from 'helpers/hardReset'
import sentry from 'sentry/browser'
import App from 'components/App'
+import AppError from 'components/AppError'
import 'styles/global'
@@ -99,5 +100,5 @@ 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)
- process.exit(1)
+ r()
})