diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-04-10 15:58:29 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-04-11 14:30:26 +0200 |
| commit | 1741fc096f01abc5fe5c1b5de84f8f504ed1615b (patch) | |
| tree | fe02b281e42564fd4fc9990e12b824fa93e56641 | |
| parent | 336ca26d259d81d189faee521f4fd2cfa7d13f7e (diff) | |
| download | mullvadvpn-1741fc096f01abc5fe5c1b5de84f8f504ed1615b.tar.xz mullvadvpn-1741fc096f01abc5fe5c1b5de84f8f504ed1615b.zip | |
Add error boundary
| -rw-r--r-- | gui/locales/messages.pot | 72 | ||||
| -rw-r--r-- | gui/src/config.json | 2 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 15 | ||||
| -rw-r--r-- | gui/src/renderer/components/ErrorBoundary.tsx | 93 | ||||
| -rw-r--r-- | gui/src/renderer/components/Support.tsx | 13 |
5 files changed, 154 insertions, 41 deletions
diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot index 12c9f9b326..dd776a08ea 100644 --- a/gui/locales/messages.pot +++ b/gui/locales/messages.pot @@ -12,8 +12,8 @@ msgstr "" #: src/renderer/components/SecuredLabel.tsx:37 #: src/renderer/components/Support.tsx:284 -#: src/renderer/components/Support.tsx:318 -#: src/renderer/components/Support.tsx:345 +#: src/renderer/components/Support.tsx:319 +#: src/renderer/components/Support.tsx:346 msgid "SECURE CONNECTION" msgstr "" @@ -174,7 +174,7 @@ msgstr "" #. Available placeholders: #. %(city)s - a city name #. %(hostname)s - a hostname -#: src/renderer/containers/ConnectPage.tsx:54 +#: src/renderer/containers/ConnectPage.tsx:56 msgctxt "connect-container" msgid "%(city)s (%(hostname)s)" msgstr "" @@ -210,6 +210,19 @@ msgctxt "connect-view" msgid "You have no more VPN time left on this account. To buy more credit on our website, you will need to access the Internet with an unsecured connection." msgstr "" +#: src/renderer/components/ErrorBoundary.tsx:81 +msgctxt "error-boundary-view" +msgid "MULLVAD VPN" +msgstr "" + +#. The message displayed to the user in case of critical error in the GUI +#. Available placeholders: +#. %(email)s - support email +#: src/renderer/components/ErrorBoundary.tsx:69 +msgctxt "error-boundary-view" +msgid "Something went wrong. Please contact us at %(email)s" +msgstr "" + #: src/renderer/components/NotificationArea.tsx:284 msgctxt "in-app-notifications" msgid "ACCOUNT CREDIT EXPIRES SOON" @@ -462,78 +475,78 @@ msgid "Use a monochromatic tray icon instead of a colored one." msgstr "" #. Title label in navigation bar -#: src/renderer/components/SelectLocation.tsx:119 +#: src/renderer/components/SelectLocation.tsx:118 msgctxt "select-location-nav" msgid "Select location" msgstr "" -#: src/renderer/components/SelectLocation.tsx:127 +#: src/renderer/components/SelectLocation.tsx:126 msgctxt "select-location-view" msgid "Select location" msgstr "" -#: src/renderer/components/SelectLocation.tsx:130 +#: src/renderer/components/SelectLocation.tsx:129 msgctxt "select-location-view" msgid "While connected, your real location is masked with a private and secure location in the selected region" msgstr "" -#: src/renderer/components/Settings.tsx:104 +#: src/renderer/components/Settings.tsx:105 msgctxt "settings-view" msgid "Account" msgstr "" -#: src/renderer/components/Settings.tsx:119 +#: src/renderer/components/Settings.tsx:120 msgctxt "settings-view" msgid "Advanced" msgstr "" -#: src/renderer/components/Settings.tsx:165 +#: src/renderer/components/Settings.tsx:166 msgctxt "settings-view" msgid "App version" msgstr "" -#: src/renderer/components/Settings.tsx:186 +#: src/renderer/components/Settings.tsx:187 msgctxt "settings-view" msgid "FAQs & Guides" msgstr "" -#: src/renderer/components/Settings.tsx:131 +#: src/renderer/components/Settings.tsx:132 msgctxt "settings-view" msgid "Inconsistent internal version information, please restart the app." msgstr "" -#: src/renderer/components/Settings.tsx:98 +#: src/renderer/components/Settings.tsx:99 msgctxt "settings-view" msgid "OUT OF TIME" msgstr "" -#: src/renderer/components/Settings.tsx:114 +#: src/renderer/components/Settings.tsx:115 msgctxt "settings-view" msgid "Preferences" msgstr "" -#: src/renderer/components/Settings.tsx:80 +#: src/renderer/components/Settings.tsx:81 msgctxt "settings-view" msgid "Quit app" msgstr "" -#: src/renderer/components/Settings.tsx:181 +#: src/renderer/components/Settings.tsx:182 msgctxt "settings-view" msgid "Report a problem" msgstr "" -#: src/renderer/components/Settings.tsx:58 +#: src/renderer/components/Settings.tsx:59 msgctxt "settings-view" msgid "Settings" msgstr "" -#: src/renderer/components/Settings.tsx:136 +#: src/renderer/components/Settings.tsx:137 msgctxt "settings-view" msgid "Update available, download to remain safe." msgstr "" #. Title label in navigation bar -#: src/renderer/components/Settings.tsx:50 +#: src/renderer/components/Settings.tsx:51 msgctxt "settings-view-nav" msgid "Settings" msgstr "" @@ -544,7 +557,7 @@ msgctxt "support-nav" msgid "Settings" msgstr "" -#: src/renderer/components/Support.tsx:395 +#: src/renderer/components/Support.tsx:396 msgctxt "support-view" msgid "Back" msgstr "" @@ -554,17 +567,20 @@ msgctxt "support-view" msgid "Describe your problem" msgstr "" -#: src/renderer/components/Support.tsx:360 +#: src/renderer/components/Support.tsx:361 msgctxt "support-view" msgid "Edit message" msgstr "" -#: src/renderer/components/Support.tsx:348 +#: src/renderer/components/Support.tsx:349 msgctxt "support-view" msgid "Failed to send" msgstr "" -#: src/renderer/components/Support.tsx:299 +#. The message displayed to the user after submitting the problem report, given that the user left his or her email for us to reach back. +#. Available placeholders: +#. %(email)s +#: src/renderer/components/Support.tsx:300 msgctxt "support-view" msgid "If needed we will contact you on %(email)s" msgstr "" @@ -579,7 +595,7 @@ msgctxt "support-view" msgid "Send" msgstr "" -#: src/renderer/components/Support.tsx:392 +#: src/renderer/components/Support.tsx:393 msgctxt "support-view" msgid "Send anyway" msgstr "" @@ -589,12 +605,12 @@ msgctxt "support-view" msgid "Sending..." msgstr "" -#: src/renderer/components/Support.tsx:321 +#: src/renderer/components/Support.tsx:322 msgctxt "support-view" msgid "Sent" msgstr "" -#: src/renderer/components/Support.tsx:325 +#: src/renderer/components/Support.tsx:326 msgctxt "support-view" msgid "Thanks! We will look into this." msgstr "" @@ -604,7 +620,7 @@ msgctxt "support-view" msgid "To help you more effectively, your app's log file will be attached to this message. Your data will remain secure and private, as it is anonymised before being sent over an encrypted channel." msgstr "" -#: src/renderer/components/Support.tsx:363 +#: src/renderer/components/Support.tsx:364 msgctxt "support-view" msgid "Try again" msgstr "" @@ -614,12 +630,12 @@ msgctxt "support-view" msgid "View app logs" msgstr "" -#: src/renderer/components/Support.tsx:386 +#: src/renderer/components/Support.tsx:387 msgctxt "support-view" msgid "You are about to send the problem report without a way for us to get back to you. If you want an answer to your report you will have to enter an email address." msgstr "" -#: src/renderer/components/Support.tsx:351 +#: src/renderer/components/Support.tsx:352 msgctxt "support-view" msgid "You may need to go back to the app's main screen and click Disconnect before trying again. Don't worry, the information you entered will remain in the form." msgstr "" diff --git a/gui/src/config.json b/gui/src/config.json index e3f340ec96..54eca6000b 100644 --- a/gui/src/config.json +++ b/gui/src/config.json @@ -4,7 +4,7 @@ "purchase": "https://mullvad.net/account/login/", "faq": "https://mullvad.net/faq/", "download": "https://mullvad.net/download/", - "supportEmail": "mailto:support@mullvad.net" + "supportEmail": "support@mullvad.net" }, "colors": { "darkBlue": "rgb(25, 46, 69)", diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index 96d0b3e43d..2549404e20 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -11,6 +11,7 @@ import { Provider } from 'react-redux'; import { bindActionCreators } from 'redux'; import { InvalidAccountError } from '../main/errors'; +import ErrorBoundary from './components/ErrorBoundary'; import AppRoutes from './routes'; import accountActions from './redux/account/actions'; @@ -185,12 +186,14 @@ export default class AppRenderer { return ( <Provider store={this.reduxStore}> <ConnectedRouter history={this.memoryHistory}> - <AppRoutes - sharedProps={{ - app: this, - locale: this.locale, - }} - /> + <ErrorBoundary> + <AppRoutes + sharedProps={{ + app: this, + locale: this.locale, + }} + /> + </ErrorBoundary> </ConnectedRouter> </Provider> ); diff --git a/gui/src/renderer/components/ErrorBoundary.tsx b/gui/src/renderer/components/ErrorBoundary.tsx new file mode 100644 index 0000000000..07bc839bce --- /dev/null +++ b/gui/src/renderer/components/ErrorBoundary.tsx @@ -0,0 +1,93 @@ +import log from 'electron-log'; +import * as React from 'react'; +import { Component, Styles, Text, View } from 'reactxp'; +import { colors, links } from '../../config.json'; +import { messages } from '../../shared/gettext'; +import PlatformWindowContainer from '../containers/PlatformWindowContainer'; +import ImageView from './ImageView'; +import { Container, Layout } from './Layout'; + +interface IProps { + children?: React.ReactNode; +} + +interface IState { + hasError: boolean; +} + +const styles = { + container: Styles.createViewStyle({ + flex: 1, + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: colors.blue, + }), + logo: Styles.createViewStyle({ + marginBottom: 4, + }), + title: Styles.createTextStyle({ + fontFamily: 'DINPro', + fontSize: 24, + fontWeight: '900', + lineHeight: 30, + letterSpacing: -0.5, + color: colors.white60, + marginBottom: 4, + }), + subtitle: Styles.createTextStyle({ + fontFamily: 'Open Sans', + fontSize: 14, + lineHeight: 20, + color: colors.white40, + marginHorizontal: 20, + textAlign: 'center', + }), + email: Styles.createTextStyle({ + fontWeight: '900', + }), +}; + +export default class ErrorBoundary extends Component<IProps, IState> { + public state = { hasError: false }; + + public componentDidCatch(error: Error, info: React.ErrorInfo) { + this.setState({ hasError: true }); + + log.error( + `The error boundary caught an error: ${error.message}\nError stack: ${error.stack || + 'Not available'}\nComponent stack: ${info.componentStack}`, + ); + } + + public render() { + if (this.state.hasError) { + const reachBackMessage: React.ReactNodeArray = + // TRANSLATORS: The message displayed to the user in case of critical error in the GUI + // TRANSLATORS: Available placeholders: + // TRANSLATORS: %(email)s - support email + messages + .pgettext('error-boundary-view', 'Something went wrong. Please contact us at %(email)s') + .split('%(email)s', 2); + reachBackMessage.splice(1, 0, <Text style={styles.email}>{links.supportEmail}</Text>); + + return ( + <PlatformWindowContainer> + <Layout> + <Container> + <View style={styles.container}> + <ImageView height={120} width={120} source="logo-icon" style={styles.logo} /> + <Text style={styles.title}> + {messages.pgettext('error-boundary-view', 'MULLVAD VPN')} + </Text> + <Text style={styles.subtitle}>{reachBackMessage}</Text> + </View> + </Container> + </Layout> + </PlatformWindowContainer> + ); + } else { + return this.props.children; + } + } +} diff --git a/gui/src/renderer/components/Support.tsx b/gui/src/renderer/components/Support.tsx index 439b229dfc..fd9241bbf8 100644 --- a/gui/src/renderer/components/Support.tsx +++ b/gui/src/renderer/components/Support.tsx @@ -293,12 +293,13 @@ export default class Support extends Component<ISupportProps, ISupportState> { } private renderSent() { - // TRANSLATORS: The message displayed to the user after submitting the problem report, given that the user left his or her email for us to reach back. - // TRANSLATORS: Available placeholders: - // TRANSLATORS: %(email)s - const reachBackMessage: React.ReactNodeArray = messages - .pgettext('support-view', 'If needed we will contact you on %(email)s') - .split('%(email)s', 2); + const reachBackMessage: React.ReactNodeArray = + // TRANSLATORS: The message displayed to the user after submitting the problem report, given that the user left his or her email for us to reach back. + // TRANSLATORS: Available placeholders: + // TRANSLATORS: %(email)s + messages + .pgettext('support-view', 'If needed we will contact you on %(email)s') + .split('%(email)s', 2); reachBackMessage.splice( 1, 0, |
