// Copyright 2018-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { app, dialog, clipboard } from 'electron'; import * as Errors from '../ts/types/errors'; import { redactAll } from '../ts/util/privacy'; import type { LocaleMessagesType } from '../ts/types/I18N'; import { reallyJsonStringify } from '../ts/util/reallyJsonStringify'; // We use hard-coded strings until we're able to update these strings from the locale. let quitText = 'Quit'; let copyErrorAndQuitText = 'Copy error and quit'; function handleError(prefix: string, error: Error): void { if (console._error) { console._error(`${prefix}:`, Errors.toLogFormat(error)); } console.error(`${prefix}:`, Errors.toLogFormat(error)); if (app.isReady()) { // title field is not shown on macOS, so we don't use it const buttonIndex = dialog.showMessageBoxSync({ buttons: [quitText, copyErrorAndQuitText], defaultId: 0, detail: redactAll(error.stack || ''), message: prefix, noLink: true, type: 'error', }); if (buttonIndex === 1) { clipboard.writeText(`${prefix}\n\n${redactAll(error.stack || '')}`); } } else { dialog.showErrorBox(prefix, error.stack || ''); } app.exit(1); } export const updateLocale = (messages: LocaleMessagesType): void => { quitText = messages.quit.message; copyErrorAndQuitText = messages.copyErrorAndQuit.message; }; function _getError(reason: unknown): Error { if (reason instanceof Error) { return reason; } const errorString = reallyJsonStringify(reason); return new Error(`Promise rejected with a non-error: ${errorString}`); } export const addHandler = (): void => { process.on('uncaughtException', (reason: unknown) => { handleError('Unhandled Error', _getError(reason)); }); process.on('unhandledRejection', (reason: unknown) => { handleError('Unhandled Promise Rejection', _getError(reason)); }); };