diff --git a/desktop/app/src/init.tsx b/desktop/app/src/init.tsx
index a9132fa7f..c67ec37e9 100644
--- a/desktop/app/src/init.tsx
+++ b/desktop/app/src/init.tsx
@@ -40,8 +40,15 @@ import {
_setGlobalInteractionReporter,
Logger,
_LoggerContext,
+ Layout,
+ theme,
} from 'flipper-plugin';
import isProduction from './utils/isProduction';
+import {Button, Input, Result, Typography} from 'antd';
+import constants from './fb-stubs/constants';
+import styled from '@emotion/styled';
+import {CopyOutlined} from '@ant-design/icons';
+import {clipboard} from 'electron/common';
if (process.env.NODE_ENV === 'development' && os.platform() === 'darwin') {
// By default Node.JS has its internal certificate storage and doesn't use
@@ -58,23 +65,93 @@ enableMapSet();
GK.init();
-const AppFrame = ({logger}: {logger: Logger}) => (
- <_LoggerContext.Provider value={logger}>
-
-
-
-
-
- <_NuxManagerContext.Provider value={_createNuxManager()}>
-
-
-
-
-
-
-
-
-);
+class AppFrame extends React.Component<
+ {logger: Logger},
+ {error: any; errorInfo: any}
+> {
+ state = {error: undefined as any, errorInfo: undefined as any};
+
+ getError() {
+ return this.state.error
+ ? `${this.state.error}\n\nComponent stack:\n${this.state.errorInfo?.componentStack}\n\nError stacktrace:\n${this.state.error?.stack}`
+ : '';
+ }
+
+ render() {
+ const {logger} = this.props;
+ return this.state.error ? (
+
+
+
+ A crash was detected in the Flipper chrome. Filing a{' '}
+
+ bug report
+ {' '}
+ would be appreciated! Please include the details below.
+
+ }
+ extra={[
+ }
+ onClick={() => {
+ clipboard.writeText(this.getError());
+ }}>
+ Copy error
+ ,
+ ,
+ ]}
+ />
+
+
+
+ ) : (
+ <_LoggerContext.Provider value={logger}>
+
+
+
+
+
+ <_NuxManagerContext.Provider value={_createNuxManager()}>
+
+
+
+
+
+
+
+
+ );
+ }
+
+ componentDidCatch(error: any, errorInfo: any) {
+ console.error(
+ `Flipper chrome crash: ${error}`,
+ error,
+ '\nComponents: ' + errorInfo?.componentStack,
+ );
+ this.setState({
+ error,
+ errorInfo,
+ });
+ }
+}
function setProcessState(store: Store) {
const settings = store.getState().settingsState;
@@ -146,3 +223,10 @@ const persistor = persistStore(store, undefined, () => {
});
setPersistor(persistor);
+
+const CodeBlock = styled(Input.TextArea)({
+ fontFamily:
+ 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;',
+ fontSize: '0.8em',
+ color: theme.textColorSecondary,
+});
diff --git a/desktop/flipper-plugin/src/ui/Layout.tsx b/desktop/flipper-plugin/src/ui/Layout.tsx
index df20f0ff4..1b82e0982 100644
--- a/desktop/flipper-plugin/src/ui/Layout.tsx
+++ b/desktop/flipper-plugin/src/ui/Layout.tsx
@@ -139,6 +139,7 @@ type SplitLayoutProps = {
*/
center?: boolean;
children: [React.ReactNode, React.ReactNode];
+ style?: React.HTMLAttributes['style'];
};
function renderSplitLayout(