diff options
author | Stefan Malzner <stefan@adlk.io> | 2018-12-09 13:24:17 +0100 |
---|---|---|
committer | Stefan Malzner <stefan@adlk.io> | 2018-12-09 13:24:17 +0100 |
commit | 898d54cd0034bbb2727bc5b5eaf9d5a4f2a852de (patch) | |
tree | 9816c013f9a9453dae07d9dd8d4a862c77c23064 /src/components | |
parent | Upgrade to react 16 (diff) | |
download | ferdium-app-898d54cd0034bbb2727bc5b5eaf9d5a4f2a852de.tar.gz ferdium-app-898d54cd0034bbb2727bc5b5eaf9d5a4f2a852de.tar.zst ferdium-app-898d54cd0034bbb2727bc5b5eaf9d5a4f2a852de.zip |
Add React 16 didCatch/ErrorBoundary component
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/layout/AppLayout.js | 134 | ||||
-rw-r--r-- | src/components/services/content/ServiceWebview.js | 1 | ||||
-rw-r--r-- | src/components/settings/SettingsLayout.js | 21 | ||||
-rw-r--r-- | src/components/util/ErrorBoundary/index.js | 54 | ||||
-rw-r--r-- | src/components/util/ErrorBoundary/styles.js | 13 |
5 files changed, 149 insertions, 74 deletions
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 3ababe54a..e526f6b1f 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -6,6 +6,8 @@ import { TitleBar } from 'electron-react-titlebar'; | |||
6 | 6 | ||
7 | import InfoBar from '../ui/InfoBar'; | 7 | import InfoBar from '../ui/InfoBar'; |
8 | import { Component as DelayApp } from '../../features/delayApp'; | 8 | import { Component as DelayApp } from '../../features/delayApp'; |
9 | import ErrorBoundary from '../util/ErrorBoundary'; | ||
10 | |||
9 | import globalMessages from '../../i18n/globalMessages'; | 11 | import globalMessages from '../../i18n/globalMessages'; |
10 | 12 | ||
11 | import { isWindows } from '../../environment'; | 13 | import { isWindows } from '../../environment'; |
@@ -94,74 +96,76 @@ export default @observer class AppLayout extends Component { | |||
94 | const { intl } = this.context; | 96 | const { intl } = this.context; |
95 | 97 | ||
96 | return ( | 98 | return ( |
97 | <div className={(darkMode ? 'theme__dark' : '')}> | 99 | <ErrorBoundary> |
98 | <div className="app"> | 100 | <div className={(darkMode ? 'theme__dark' : '')}> |
99 | {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />} | 101 | <div className="app"> |
100 | <div className="app__content"> | 102 | {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />} |
101 | {sidebar} | 103 | <div className="app__content"> |
102 | <div className="app__service"> | 104 | {sidebar} |
103 | {news.length > 0 && news.map(item => ( | 105 | <div className="app__service"> |
104 | <InfoBar | 106 | {news.length > 0 && news.map(item => ( |
105 | key={item.id} | 107 | <InfoBar |
106 | position="top" | 108 | key={item.id} |
107 | type={item.type} | 109 | position="top" |
108 | sticky={item.sticky} | 110 | type={item.type} |
109 | onHide={() => removeNewsItem({ newsId: item.id })} | 111 | sticky={item.sticky} |
110 | > | 112 | onHide={() => removeNewsItem({ newsId: item.id })} |
111 | <span dangerouslySetInnerHTML={createMarkup(item.message)} /> | 113 | > |
112 | </InfoBar> | 114 | <span dangerouslySetInnerHTML={createMarkup(item.message)} /> |
113 | ))} | 115 | </InfoBar> |
114 | {!isOnline && ( | 116 | ))} |
115 | <InfoBar | 117 | {!isOnline && ( |
116 | type="danger" | 118 | <InfoBar |
117 | > | 119 | type="danger" |
118 | <span className="mdi mdi-flash" /> | 120 | > |
119 | {intl.formatMessage(globalMessages.notConnectedToTheInternet)} | 121 | <span className="mdi mdi-flash" /> |
120 | </InfoBar> | 122 | {intl.formatMessage(globalMessages.notConnectedToTheInternet)} |
121 | )} | 123 | </InfoBar> |
122 | {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( | 124 | )} |
123 | <InfoBar | 125 | {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( |
124 | type="danger" | 126 | <InfoBar |
125 | ctaLabel="Try again" | 127 | type="danger" |
126 | ctaLoading={areRequiredRequestsLoading} | 128 | ctaLabel="Try again" |
127 | sticky | 129 | ctaLoading={areRequiredRequestsLoading} |
128 | onClick={retryRequiredRequests} | 130 | sticky |
129 | > | 131 | onClick={retryRequiredRequests} |
130 | <span className="mdi mdi-flash" /> | 132 | > |
131 | {intl.formatMessage(messages.requiredRequestsFailed)} | 133 | <span className="mdi mdi-flash" /> |
132 | </InfoBar> | 134 | {intl.formatMessage(messages.requiredRequestsFailed)} |
133 | )} | 135 | </InfoBar> |
134 | {showServicesUpdatedInfoBar && ( | 136 | )} |
135 | <InfoBar | 137 | {showServicesUpdatedInfoBar && ( |
136 | type="primary" | 138 | <InfoBar |
137 | ctaLabel={intl.formatMessage(messages.buttonReloadServices)} | 139 | type="primary" |
138 | onClick={reloadServicesAfterUpdate} | 140 | ctaLabel={intl.formatMessage(messages.buttonReloadServices)} |
139 | sticky | 141 | onClick={reloadServicesAfterUpdate} |
140 | > | 142 | sticky |
141 | <span className="mdi mdi-power-plug" /> | 143 | > |
142 | {intl.formatMessage(messages.servicesUpdated)} | 144 | <span className="mdi mdi-power-plug" /> |
143 | </InfoBar> | 145 | {intl.formatMessage(messages.servicesUpdated)} |
144 | )} | 146 | </InfoBar> |
145 | {appUpdateIsDownloaded && ( | 147 | )} |
146 | <InfoBar | 148 | {appUpdateIsDownloaded && ( |
147 | type="primary" | 149 | <InfoBar |
148 | ctaLabel={intl.formatMessage(messages.buttonInstallUpdate)} | 150 | type="primary" |
149 | onClick={installAppUpdate} | 151 | ctaLabel={intl.formatMessage(messages.buttonInstallUpdate)} |
150 | sticky | 152 | onClick={installAppUpdate} |
151 | > | 153 | sticky |
152 | <span className="mdi mdi-information" /> | 154 | > |
153 | {intl.formatMessage(messages.updateAvailable)} <a href="https://meetfranz.com/changelog" target="_blank"> | 155 | <span className="mdi mdi-information" /> |
154 | <u>{intl.formatMessage(messages.changelog)}</u> | 156 | {intl.formatMessage(messages.updateAvailable)} <a href="https://meetfranz.com/changelog" target="_blank"> |
155 | </a> | 157 | <u>{intl.formatMessage(messages.changelog)}</u> |
156 | </InfoBar> | 158 | </a> |
157 | )} | 159 | </InfoBar> |
158 | {isDelayAppScreenVisible && (<DelayApp />)} | 160 | )} |
159 | {services} | 161 | {isDelayAppScreenVisible && (<DelayApp />)} |
162 | {services} | ||
163 | </div> | ||
160 | </div> | 164 | </div> |
161 | </div> | 165 | </div> |
166 | {children} | ||
162 | </div> | 167 | </div> |
163 | {children} | 168 | </ErrorBoundary> |
164 | </div> | ||
165 | ); | 169 | ); |
166 | } | 170 | } |
167 | } | 171 | } |
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index f59205c0e..98daf9b9f 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js | |||
@@ -59,6 +59,7 @@ export default @observer class ServiceWebview extends Component { | |||
59 | } | 59 | } |
60 | 60 | ||
61 | autorunDisposer = null; | 61 | autorunDisposer = null; |
62 | |||
62 | webview = null; | 63 | webview = null; |
63 | 64 | ||
64 | render() { | 65 | render() { |
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js index 3cb08feb1..d5d8f0bb0 100644 --- a/src/components/settings/SettingsLayout.js +++ b/src/components/settings/SettingsLayout.js | |||
@@ -2,6 +2,7 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | 4 | ||
5 | import ErrorBoundary from '../util/ErrorBoundary'; | ||
5 | import { oneOrManyChildElements } from '../../prop-types'; | 6 | import { oneOrManyChildElements } from '../../prop-types'; |
6 | import Appear from '../ui/effects/Appear'; | 7 | import Appear from '../ui/effects/Appear'; |
7 | 8 | ||
@@ -36,18 +37,20 @@ export default @observer class SettingsLayout extends Component { | |||
36 | return ( | 37 | return ( |
37 | <Appear transitionName="fadeIn-fast"> | 38 | <Appear transitionName="fadeIn-fast"> |
38 | <div className="settings-wrapper"> | 39 | <div className="settings-wrapper"> |
39 | <button | 40 | <ErrorBoundary> |
40 | className="settings-wrapper__action" | ||
41 | onClick={closeSettings} | ||
42 | /> | ||
43 | <div className="settings franz-form"> | ||
44 | {navigation} | ||
45 | {children} | ||
46 | <button | 41 | <button |
47 | className="settings__close mdi mdi-close" | 42 | className="settings-wrapper__action" |
48 | onClick={closeSettings} | 43 | onClick={closeSettings} |
49 | /> | 44 | /> |
50 | </div> | 45 | <div className="settings franz-form"> |
46 | {navigation} | ||
47 | {children} | ||
48 | <button | ||
49 | className="settings__close mdi mdi-close" | ||
50 | onClick={closeSettings} | ||
51 | /> | ||
52 | </div> | ||
53 | </ErrorBoundary> | ||
51 | </div> | 54 | </div> |
52 | </Appear> | 55 | </Appear> |
53 | ); | 56 | ); |
diff --git a/src/components/util/ErrorBoundary/index.js b/src/components/util/ErrorBoundary/index.js new file mode 100644 index 000000000..def01c74f --- /dev/null +++ b/src/components/util/ErrorBoundary/index.js | |||
@@ -0,0 +1,54 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import injectSheet from 'react-jss'; | ||
3 | import { defineMessages, intlShape } from 'react-intl'; | ||
4 | |||
5 | import Button from '../../ui/Button'; | ||
6 | |||
7 | import styles from './styles'; | ||
8 | |||
9 | const messages = defineMessages({ | ||
10 | headline: { | ||
11 | id: 'app.errorHandler.headline', | ||
12 | defaultMessage: '!!!Something went wrong.', | ||
13 | }, | ||
14 | action: { | ||
15 | id: 'app.errorHandler.action', | ||
16 | defaultMessage: '!!!Reload', | ||
17 | }, | ||
18 | }); | ||
19 | |||
20 | export default @injectSheet(styles) class ErrorBoundary extends Component { | ||
21 | state = { | ||
22 | hasError: false, | ||
23 | } | ||
24 | |||
25 | static contextTypes = { | ||
26 | intl: intlShape, | ||
27 | }; | ||
28 | |||
29 | componentDidCatch(error, info) { | ||
30 | this.setState({ hasError: true }); | ||
31 | } | ||
32 | |||
33 | render() { | ||
34 | const { classes } = this.props; | ||
35 | const { intl } = this.context; | ||
36 | |||
37 | if (this.state.hasError) { | ||
38 | return ( | ||
39 | <div className={classes.component}> | ||
40 | <h1 className={classes.title}> | ||
41 | {intl.formatMessage(messages.headline)} | ||
42 | </h1> | ||
43 | <Button | ||
44 | label={intl.formatMessage(messages.action)} | ||
45 | buttonType="inverted" | ||
46 | onClick={() => location.reload()} | ||
47 | /> | ||
48 | </div> | ||
49 | ); | ||
50 | } | ||
51 | |||
52 | return this.props.children; | ||
53 | } | ||
54 | } \ No newline at end of file | ||
diff --git a/src/components/util/ErrorBoundary/styles.js b/src/components/util/ErrorBoundary/styles.js new file mode 100644 index 000000000..8d62767f6 --- /dev/null +++ b/src/components/util/ErrorBoundary/styles.js | |||
@@ -0,0 +1,13 @@ | |||
1 | export default (theme) => ({ | ||
2 | component: { | ||
3 | display: 'flex', | ||
4 | width: '100%', | ||
5 | alignItems: 'center', | ||
6 | justifyContent: 'center', | ||
7 | flexDirection: 'column', | ||
8 | }, | ||
9 | title: { | ||
10 | fontSize: 20, | ||
11 | color: theme.colorText, | ||
12 | } | ||
13 | }); | ||