mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop: Resolves #5273: Prevent plugins from crashing the application
This commit is contained in:
parent
e9d590169b
commit
f9cfefdb29
@ -23,13 +23,17 @@ interface State {
|
||||
pluginInfos: PluginInfo[];
|
||||
}
|
||||
|
||||
interface Props {}
|
||||
interface Props {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export default class ErrorBoundary extends React.Component<Props, State> {
|
||||
|
||||
public state: State = { error: null, errorInfo: null, pluginInfos: [] };
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
componentDidCatch(error: any, errorInfo: ErrorInfo) {
|
||||
if (typeof error === 'string') error = { message: error };
|
||||
|
||||
const pluginInfos: PluginInfo[] = [];
|
||||
try {
|
||||
const service = PluginService.instance();
|
||||
@ -61,6 +65,11 @@ export default class ErrorBoundary extends React.Component<Props, State> {
|
||||
ipcRenderer.on('appClose', onAppClose);
|
||||
}
|
||||
|
||||
renderMessage() {
|
||||
const message = this.props.message || 'Joplin encountered a fatal error and could not continue.';
|
||||
return <p>{message}</p>;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
const safeMode_click = async () => {
|
||||
@ -118,8 +127,9 @@ export default class ErrorBoundary extends React.Component<Props, State> {
|
||||
return (
|
||||
<div style={{ overflow: 'auto', fontFamily: 'sans-serif', padding: '5px 20px' }}>
|
||||
<h1>Error</h1>
|
||||
<p>Joplin encountered a fatal error and could not continue. To report the error, please copy the *entire content* of this page and post it on Joplin forum or GitHub.</p>
|
||||
<p>To continue you may close the app. Alternatively, if the error persists you may try to <a href="#" onClick={safeMode_click}>restart in safe mode</a>, which will temporarily disable all plugins.</p>
|
||||
{this.renderMessage()}
|
||||
<p>To report the error, please copy the *entire content* of this page and post it on Joplin forum or GitHub.</p>
|
||||
<p>If the error persists you may try to <a href="#" onClick={safeMode_click}>restart in safe mode</a>, which will temporarily disable all plugins.</p>
|
||||
{output}
|
||||
</div>
|
||||
);
|
||||
|
@ -32,6 +32,7 @@ const shared = require('@joplin/lib/components/shared/note-screen-shared.js');
|
||||
const Menu = bridge().Menu;
|
||||
const MenuItem = bridge().MenuItem;
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import ErrorBoundary from '../../../ErrorBoundary';
|
||||
|
||||
const menuUtils = new MenuUtils(CommandService.instance());
|
||||
|
||||
@ -599,7 +600,16 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
pluginAssets: renderedBody.pluginAssets,
|
||||
downloadResources: Setting.value('sync.resourceDownloadMode'),
|
||||
};
|
||||
webviewRef.current.wrappedInstance.send('setHtml', renderedBody.html, options);
|
||||
|
||||
// It seems when there's an error immediately when the component is
|
||||
// mounted, webviewReady might be true, but webviewRef.current will be
|
||||
// undefined. Maybe due to the error boundary that unmount components.
|
||||
// Since we can't do much about it we just print an error.
|
||||
if (webviewRef.current && webviewRef.current.wrappedInstance) {
|
||||
webviewRef.current.wrappedInstance.send('setHtml', renderedBody.html, options);
|
||||
} else {
|
||||
console.error('Trying to set HTML on an undefined webview ref');
|
||||
}
|
||||
}, [renderedBody, webviewReady]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -791,16 +801,18 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={styles.root} ref={rootRef}>
|
||||
<div style={styles.rowToolbar}>
|
||||
<Toolbar themeId={props.themeId} />
|
||||
{props.noteToolbar}
|
||||
<ErrorBoundary message="The text editor encountered a fatal error and could not continue. The error might be due to a plugin, so please try to disable some of them and try again.">
|
||||
<div style={styles.root} ref={rootRef}>
|
||||
<div style={styles.rowToolbar}>
|
||||
<Toolbar themeId={props.themeId} />
|
||||
{props.noteToolbar}
|
||||
</div>
|
||||
<div style={styles.rowEditorViewer}>
|
||||
{renderEditor()}
|
||||
{renderViewer()}
|
||||
</div>
|
||||
</div>
|
||||
<div style={styles.rowEditorViewer}>
|
||||
{renderEditor()}
|
||||
{renderViewer()}
|
||||
</div>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -545,7 +545,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
onTitleChange={onTitleChange}
|
||||
/>
|
||||
{renderSearchInfo()}
|
||||
<div style={{ display: 'flex', flex: 1, paddingLeft: theme.editorPaddingLeft }}>
|
||||
<div style={{ display: 'flex', flex: 1, paddingLeft: theme.editorPaddingLeft, maxHeight: '100%' }}>
|
||||
{editor}
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
||||
|
Loading…
Reference in New Issue
Block a user