diff --git a/app/main/src/helpers/analytics.ts b/app/main/src/helpers/analytics.ts index 992fc1ae..e9e3bb9d 100644 --- a/app/main/src/helpers/analytics.ts +++ b/app/main/src/helpers/analytics.ts @@ -3,9 +3,9 @@ import { v4 as uuid } from "uuid"; import store from "../store"; -const userId = store.get("userId") || uuid(); +const userId = store.safeGet("userId") || uuid(); -store.set("userId", userId); +store.safeSet("userId", userId); function activateUser() { const user = ua("UA-172128342-2", userId); diff --git a/app/main/src/main.ts b/app/main/src/main.ts index 30e2ca92..470e9a7c 100644 --- a/app/main/src/main.ts +++ b/app/main/src/main.ts @@ -64,7 +64,7 @@ const getFrameHeight = () => { if (isWindow()) { return 502; } else { - if (store.get("useNativeTitlebar")) { + if (store.safeGet("useNativeTitlebar")) { return 488; } return 502; @@ -91,9 +91,9 @@ function createMainWindow() { resizable: true, maximizable: false, show: false, - frame: store.get("useNativeTitlebar"), + frame: store.safeGet("useNativeTitlebar"), icon: getIcon(), - backgroundColor: store.get("isDarkMode") ? "#141e25" : "#fff", + backgroundColor: store.safeGet("isDarkMode") ? "#141e25" : "#fff", webPreferences: { contextIsolation: true, backgroundThrottling: false, @@ -372,7 +372,7 @@ ipcMain.on(SET_COMPACT_MODE, (e, args) => { }); ipcMain.on(SET_UI_THEME, (e, { isDarkMode }) => { - store.set("isDarkMode", isDarkMode); + store.safeSet("isDarkMode", isDarkMode); }); ipcMain.on(SET_SHOW, () => { @@ -406,8 +406,8 @@ ipcMain.on(SET_CLOSE, (e, { closeToTray }) => { }); ipcMain.on(SET_NATIVE_TITLEBAR, (e, { useNativeTitlebar }) => { - if (store.get("useNativeTitlebar") !== useNativeTitlebar) { - store.set("useNativeTitlebar", useNativeTitlebar); + if (store.safeGet("useNativeTitlebar") !== useNativeTitlebar) { + store.safeSet("useNativeTitlebar", useNativeTitlebar); setTimeout(() => { app.relaunch(); app.exit(); @@ -421,7 +421,7 @@ ipcMain.on(TRAY_ICON_UPDATE, (e, dataUrl) => { }); ipcMain.on(SET_OPEN_AT_LOGIN, (e, { openAtLogin }) => { - store.set("openAtLogin", openAtLogin); + store.safeSet("openAtLogin", openAtLogin); app.setLoginItemSettings({ openAtLogin: openAtLogin, openAsHidden: openAtLogin, diff --git a/app/main/src/store.ts b/app/main/src/store.ts index 365a1a0a..c344349f 100644 --- a/app/main/src/store.ts +++ b/app/main/src/store.ts @@ -1,6 +1,7 @@ -import Store from "electron-store"; +import Store, { Options } from "electron-store"; import { nativeTheme } from "electron"; import { isWindow } from "./helpers"; +import ElectronStore from "electron-store"; type StoreProps = { userId?: string; @@ -10,7 +11,48 @@ type StoreProps = { openAtLogin?: boolean; }; -const store = new Store({ +/** + * Was going to make SafeStore extend Store but it didn't seem to work how it should. (Class constructor ElectronStore cannot be invoked without 'new') + * + * This also ensures that we can force calling the store safely. Though I have switched the names to safeGet and safeSet to make it more clear. + */ +class SafeStore< + T extends Record = Record +> { + private store: ElectronStore; + constructor(props: Options) { + this.store = new Store(props); + } + + /** + * Safely set a value in the store and catch errors + * @param key + * @param value + */ + safeSet(key: Key, value?: T[Key]) { + try { + this.store.set(key, value); + } catch (error) { + console.error("[Store] Safe Set", error); + } + } + + /** + * Safely get a value from the store and catch errors + * @param key + */ + safeGet(key: Key): T[Key] | undefined { + try { + return this.store.get(key); + } catch (error) { + console.error("[Store] Safe Get", error); + } + return undefined; + } +} + +// Wrap the store due to a delete issue +const store = new SafeStore({ defaults: { isDarkMode: nativeTheme.shouldUseDarkColors, useNativeTitlebar: !isWindow(),