import * as React from 'react'; import versionInfo from '@joplin/lib/versionInfo'; import PluginService from '@joplin/lib/services/plugins/PluginService'; import Setting from '@joplin/lib/models/Setting'; import bridge from '../services/bridge'; const packageInfo = require('../packageInfo.js'); const ipcRenderer = require('electron').ipcRenderer; interface ErrorInfo { componentStack: string; } interface PluginInfo { id: string; name: string; enabled: boolean; version: string; } interface State { error: Error; errorInfo: ErrorInfo; pluginInfos: PluginInfo[]; } interface Props {} export default class ErrorBoundary extends React.Component { public state: State = { error: null, errorInfo: null, pluginInfos: [] }; componentDidCatch(error: Error, errorInfo: ErrorInfo) { const pluginInfos: PluginInfo[] = []; try { const service = PluginService.instance(); const pluginSettings = service.unserializePluginSettings(Setting.value('plugins.states')); for (const pluginId in pluginSettings) { const plugin = PluginService.instance().pluginById(pluginId); pluginInfos.push({ id: pluginId, name: plugin.manifest.name, enabled: pluginSettings[pluginId].enabled, version: plugin.manifest.version, }); } } catch (error) { console.error('Could not get plugin info:', error); } this.setState({ error, errorInfo, pluginInfos }); } componentDidMount() { const onAppClose = () => { ipcRenderer.send('asynchronous-message', 'appCloseReply', { canClose: true, }); }; ipcRenderer.on('appClose', onAppClose); } render() { if (this.state.error) { const safeMode_click = async () => { Setting.setValue('isSafeMode', true); await Setting.saveAll(); bridge().restart(); }; try { const output = []; output.push(

Message

{this.state.error.message}

); output.push(

Version info

{versionInfo(packageInfo).message}
); if (this.state.pluginInfos.length) { output.push(

Plugins

{JSON.stringify(this.state.pluginInfos, null, 4)}
); } if (this.state.error.stack) { output.push(

Stack trace

{this.state.error.stack}
); } if (this.state.errorInfo) { if (this.state.errorInfo.componentStack) { output.push(

Component stack

{this.state.errorInfo.componentStack}
); } } return (

Error

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.

To continue you may close the app. Alternatively, if the error persists you may try to restart in safe mode, which will temporarily disable all plugins.

{output}
); } catch (error) { return (
{JSON.stringify(this.state)}
); } } return this.props.children; } }