import * as React from 'react'; import versionInfo, { PackageInfo } from '@joplin/lib/versionInfo'; import PluginService, { Plugins } from '@joplin/lib/services/plugins/PluginService'; import Setting from '@joplin/lib/models/Setting'; import restart from '../services/restart'; const packageInfo: 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[]; plugins: Plugins; } interface Props { message?: string; children: any; } export default class ErrorBoundary extends React.Component { public state: State = { error: null, errorInfo: null, pluginInfos: [], plugins: {} }; public componentDidCatch(error: any, errorInfo: ErrorInfo) { if (typeof error === 'string') error = { message: error }; const pluginInfos: PluginInfo[] = []; let plugins: Plugins = {}; try { const service = PluginService.instance(); plugins = service.plugins; 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, plugins }); } public componentDidMount() { const onAppClose = () => { ipcRenderer.send('asynchronous-message', 'appCloseReply', { canClose: true, }); }; ipcRenderer.on('appClose', onAppClose); } public renderMessage() { const message = this.props.message || 'Joplin encountered a fatal error and could not continue.'; return

{message}

; } public render() { if (this.state.error) { const safeMode_click = async () => { Setting.setValue('isSafeMode', true); await Setting.saveAll(); await restart(); }; try { const output = []; output.push(

Message

{this.state.error.message}

, ); output.push(

Version info

{versionInfo(packageInfo, this.state.plugins).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

{this.renderMessage()}

To report the error, please copy the *entire content* of this page and post it on Joplin forum or GitHub.

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; } }