Show disappointed elephant if web UI crashes (#10275)
* Do not crash the whole UI when loading an invalid column * Add error boundary component to catch Web UI crashes * Add stack trace on supported browsers * Add component stack info, pre-format everything for github * Make “Reload” a clickable link that calls window.location.reload() * Remove elephant friend from error boundary, make title stand out more * Simplify error boundary to only a graphic
This commit is contained in:
		
							parent
							
								
									ff565524aa
								
							
						
					
					
						commit
						c20d096e6a
					
				
							
								
								
									
										39
									
								
								app/javascript/mastodon/components/error_boundary.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/javascript/mastodon/components/error_boundary.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | import React from 'react'; | ||||||
|  | import PropTypes from 'prop-types'; | ||||||
|  | import illustration from '../../images/elephant_ui_disappointed.svg'; | ||||||
|  | 
 | ||||||
|  | export default class ErrorBoundary extends React.PureComponent { | ||||||
|  | 
 | ||||||
|  |   static propTypes = { | ||||||
|  |     children: PropTypes.node, | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   state = { | ||||||
|  |     hasError: false, | ||||||
|  |     stackTrace: undefined, | ||||||
|  |     componentStack: undefined, | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   componentDidCatch(error, info) { | ||||||
|  |     this.setState({ | ||||||
|  |       hasError: true, | ||||||
|  |       stackTrace: error.stack, | ||||||
|  |       componentStack: info && info.componentStack, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   render() { | ||||||
|  |     const { hasError } = this.state; | ||||||
|  | 
 | ||||||
|  |     if (!hasError) { | ||||||
|  |       return this.props.children; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return ( | ||||||
|  |       <div> | ||||||
|  |         <img src={illustration} alt='' /> | ||||||
|  |       </div> | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -13,6 +13,7 @@ import { connectUserStream } from '../actions/streaming'; | |||||||
| import { IntlProvider, addLocaleData } from 'react-intl'; | import { IntlProvider, addLocaleData } from 'react-intl'; | ||||||
| import { getLocale } from '../locales'; | import { getLocale } from '../locales'; | ||||||
| import initialState from '../initial_state'; | import initialState from '../initial_state'; | ||||||
|  | import ErrorBoundary from '../components/error_boundary'; | ||||||
| 
 | 
 | ||||||
| const { localeData, messages } = getLocale(); | const { localeData, messages } = getLocale(); | ||||||
| addLocaleData(localeData); | addLocaleData(localeData); | ||||||
| @ -75,7 +76,9 @@ export default class Mastodon extends React.PureComponent { | |||||||
|     return ( |     return ( | ||||||
|       <IntlProvider locale={locale} messages={messages}> |       <IntlProvider locale={locale} messages={messages}> | ||||||
|         <Provider store={store}> |         <Provider store={store}> | ||||||
|           <MastodonMount /> |           <ErrorBoundary> | ||||||
|  |             <MastodonMount /> | ||||||
|  |           </ErrorBoundary> | ||||||
|         </Provider> |         </Provider> | ||||||
|       </IntlProvider> |       </IntlProvider> | ||||||
|     ); |     ); | ||||||
|  | |||||||
| @ -53,6 +53,11 @@ class Bundle extends React.PureComponent { | |||||||
|     const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props; |     const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props; | ||||||
|     const cachedMod = Bundle.cache.get(fetchComponent); |     const cachedMod = Bundle.cache.get(fetchComponent); | ||||||
| 
 | 
 | ||||||
|  |     if (fetchComponent === undefined) { | ||||||
|  |       this.setState({ mod: null }); | ||||||
|  |       return Promise.resolve(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     onFetch(); |     onFetch(); | ||||||
| 
 | 
 | ||||||
|     if (cachedMod) { |     if (cachedMod) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user