diff --git a/package.json b/package.json index 4ec1a1bb..ffcf5c85 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,10 @@ "draft-js-plugins-editor": "^3.0.0", "electron-context-menu": "^0.15.2", "electron-debug": "^3.0.0", + "electron-log": "^4.0.2", "electron-md-to-pdf": "^2.2.0", "electron-settings": "^3.2.0", + "electron-unhandled": "^3.0.1", "electron-updater": "^4.0.14", "electron-util": "^0.13.1", "feather-icons": "^4.25.0", diff --git a/src/main/i18n/i18n.ts b/src/main/i18n/i18n.ts index fcd3a50b..9af776be 100644 --- a/src/main/i18n/i18n.ts +++ b/src/main/i18n/i18n.ts @@ -1,4 +1,5 @@ import { app } from "electron"; +import logger from "electron-log"; import { Translations } from "../../shared/types"; import translationsDe from "./translations/de"; @@ -86,7 +87,7 @@ export function translate( // Log error and return `i18nKey` if translation string is missing both in current and fallback // language if (!translation) { - console.error(`Missing translation of i18nKey "${i18nKey}"`); + logger.error(`Missing translation of i18nKey "${i18nKey}"`); return i18nKey; } diff --git a/src/main/main.ts b/src/main/main.ts index c130a373..91103801 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -3,12 +3,14 @@ import contextMenu from "electron-context-menu"; import electronDebug from "electron-debug"; import path from "path"; +import { initLogger } from "../shared/logger"; import { initI18n } from "./i18n/i18n"; import initIpcListeners from "./ipcMain/listeners"; import { buildMenu } from "./menu/menu"; import updateApp from "./updater"; import { getWindow, setWindow } from "./window"; +initLogger(); electronDebug(); contextMenu(); diff --git a/src/main/updater.ts b/src/main/updater.ts index da6f7fb6..36f8db44 100644 --- a/src/main/updater.ts +++ b/src/main/updater.ts @@ -1,6 +1,9 @@ +import logger from "electron-log"; import { autoUpdater } from "electron-updater"; import { is } from "electron-util"; +autoUpdater.logger = logger; + /** * Check if the app has updates available. If so, download the latest one and notify the user */ @@ -9,10 +12,10 @@ export default async function updateApp(): Promise { if (!is.macAppStore) { try { await autoUpdater.checkForUpdatesAndNotify(); - } catch (e) { + } catch (err) { // Ignore errors thrown because user is not connected to internet - if (e.message !== "net::ERR_INTERNET_DISCONNECTED") { - throw e; + if (err.message !== "net::ERR_INTERNET_DISCONNECTED") { + throw err; } } } diff --git a/src/renderer/components/views/overlays/ImportOverlay/ImportOverlay.tsx b/src/renderer/components/views/overlays/ImportOverlay/ImportOverlay.tsx index e97b2e7d..0fd42f03 100644 --- a/src/renderer/components/views/overlays/ImportOverlay/ImportOverlay.tsx +++ b/src/renderer/components/views/overlays/ImportOverlay/ImportOverlay.tsx @@ -1,4 +1,5 @@ import { remote } from "electron"; +import logger from "electron-log"; import React, { PureComponent, ReactNode } from "react"; import { translate, translations } from "../../../../utils/i18n"; @@ -48,7 +49,9 @@ type Props = StateProps & DispatchProps; export default class ImportOverlay extends PureComponent { static showImportFormatError(): void { - remote.dialog.showErrorBox(translations["import-error-title"], "No import format selected"); + const errMsg = "No import format selected"; + logger.error(`Import error: ${errMsg}`); + remote.dialog.showErrorBox(translations["import-error-title"], errMsg); } constructor(props: Props) { diff --git a/src/renderer/components/views/overlays/PrefOverlay/PrefOverlay.tsx b/src/renderer/components/views/overlays/PrefOverlay/PrefOverlay.tsx index 0591792a..07b61eb5 100644 --- a/src/renderer/components/views/overlays/PrefOverlay/PrefOverlay.tsx +++ b/src/renderer/components/views/overlays/PrefOverlay/PrefOverlay.tsx @@ -1,4 +1,5 @@ import { remote } from "electron"; +import logger from "electron-log"; import { is } from "electron-util"; import React, { ChangeEvent, PureComponent, ReactNode } from "react"; @@ -123,6 +124,7 @@ export default class PrefOverlay extends PureComponent { try { moveFile(fileDir, `${newDir}/${FILE_NAME}`); } catch (err) { + logger.error("Error while moving diary file: ", err); remote.dialog.showErrorBox( translations["move-error-title"], `${translations["move-error-msg"]}: ${err.message}`, diff --git a/src/renderer/renderer.tsx b/src/renderer/renderer.tsx index bb59d442..85b228d3 100755 --- a/src/renderer/renderer.tsx +++ b/src/renderer/renderer.tsx @@ -4,11 +4,13 @@ import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; +import { initLogger } from "../shared/logger"; import AppContainer from "./components/AppContainer"; import initIpcListeners from "./electron/ipcRenderer/listeners"; import store from "./store/store"; import { initI18n } from "./utils/i18n"; +initLogger(); initIpcListeners(); initI18n(); diff --git a/src/renderer/store/file/actionCreators.ts b/src/renderer/store/file/actionCreators.ts index 57637bbe..d3a64d72 100644 --- a/src/renderer/store/file/actionCreators.ts +++ b/src/renderer/store/file/actionCreators.ts @@ -1,3 +1,5 @@ +import logger from "electron-log"; + import { disableMenuItems, enableMenuItems } from "../../electron/ipcRenderer/senders"; import createBackup from "../../files/diary/backupFile"; import { getDiaryFilePath, getMetadata } from "../../files/diary/diaryFile"; @@ -180,7 +182,7 @@ export const createEncryptedFile = (password: string): ThunkActionT => (dispatch createIndex(entries); enableMenuItems(); } catch (err) { - console.error(err); + logger.error(err); dispatch(setEncryptError(err.message)); } }; @@ -201,7 +203,7 @@ const writeEntriesEncrypted = (entries: Entries, hashedPassword: string): ThunkA writeEncryptedFile(filePath, hashedPassword, JSON.stringify(fileContent)); dispatch(setEncryptSuccess(entries)); } catch (err) { - console.error(err); + logger.error(err); dispatch(setEncryptError(err.message)); } }; diff --git a/src/shared/logger.ts b/src/shared/logger.ts new file mode 100644 index 00000000..e2d35f75 --- /dev/null +++ b/src/shared/logger.ts @@ -0,0 +1,13 @@ +import logger from "electron-log"; +import unhandled from "electron-unhandled"; + +export function initLogger(): void { + // Set log level for writing to file + logger.transports.file.level = "info"; + + // Catch unhandled errors and promise rejections, log them instead of crashing + unhandled({ + logger: err => logger.error(err), + showDialog: false, + }); +} diff --git a/yarn.lock b/yarn.lock index 82f3935f..bcea6746 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3005,7 +3005,7 @@ clean-css@4.2.x: dependencies: source-map "~0.6.0" -clean-stack@^2.0.0: +clean-stack@^2.0.0, clean-stack@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== @@ -4066,6 +4066,11 @@ electron-localshortcut@^3.1.0: keyboardevent-from-electron-accelerator "^2.0.0" keyboardevents-areequal "^0.2.1" +electron-log@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-4.0.2.tgz#159431b60688297420ce233895ec7f72d72e84dc" + integrity sha512-pj5iTMvk2Wi0YtXFX1kM4QU9Dxpg9mTZnvIiFInsFBikxMl1HLs2S+ODQ1yIT4+tLLeBocu0BZdyyshm8/2png== + electron-md-to-pdf@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/electron-md-to-pdf/-/electron-md-to-pdf-2.2.0.tgz#8bc4026252f767180858638c6387246f1148f496" @@ -4121,6 +4126,16 @@ electron-to-chromium@^1.3.322: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA== +electron-unhandled@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/electron-unhandled/-/electron-unhandled-3.0.1.tgz#34794326d850ac7bc1a1d2fe90f2b0fcd4d12c9c" + integrity sha512-eIK3LpT/1hrBK4dJjHEQLbTvI8XOflItCOtMzY2RIaRfGAXV0JfJoTe+Y59Q9b/87oXWmSD5p2Dnp2Nzgtlijg== + dependencies: + clean-stack "^2.1.0" + electron-is-dev "^1.0.1" + ensure-error "^2.0.0" + lodash.debounce "^4.0.8" + electron-updater@^4.0.14: version "4.2.0" resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.0.tgz#f9ecfc657f65ead737d42b9efecf628d3756b550" @@ -4222,6 +4237,11 @@ enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" +ensure-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ensure-error/-/ensure-error-2.0.0.tgz#b8359a992601601b3541af9472f6a49d9dca1458" + integrity sha512-1ela4oR5A+TdtFpfiQrZKFUbsOi4JuIYmz2qSGFar6pEdRa54E15mKHVVYrAq1OQhd6b6nVrCaQxQlo6kYwhaw== + entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"