diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 8ee085f8..68514bc0 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -9,7 +9,6 @@ import { type BrowserWindow } from "electron"; import type AutoLaunch from "auto-launch"; import { type AppLocalization } from "../language-helper.js"; -import { type Store } from "../store.js"; // global type extensions need to use var for whatever reason /* eslint-disable no-var */ @@ -24,6 +23,5 @@ declare global { icon_path: string; brand: string; }; - var store: Store; } /* eslint-enable no-var */ diff --git a/src/electron-main.ts b/src/electron-main.ts index 262e19c2..70f8acf2 100644 --- a/src/electron-main.ts +++ b/src/electron-main.ts @@ -24,7 +24,7 @@ import "./ipc.js"; import "./seshat.js"; import "./settings.js"; import * as tray from "./tray.js"; -import { Store } from "./store.js"; +import store from "./store.js"; import { buildMenuTemplate } from "./vectormenu.js"; import webContentsHandler from "./webcontents-handler.js"; import * as updater from "./updater.js"; @@ -262,8 +262,6 @@ async function moveAutoLauncher(): Promise { } } -global.store = new Store(); - global.appQuitting = false; const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [ @@ -274,7 +272,7 @@ const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [ ]; const warnBeforeExit = (event: Event, input: Input): void => { - const shouldWarnBeforeExit = global.store.get("warnBeforeExit", true); + const shouldWarnBeforeExit = store.get("warnBeforeExit", true); const exitShortcutPressed = input.type === "keyDown" && exitShortcuts.some((shortcutFn) => shortcutFn(input, process.platform)); @@ -356,7 +354,7 @@ app.enableSandbox(); app.commandLine.appendSwitch("disable-features", "HardwareMediaKeyHandling,MediaSessionService"); // Disable hardware acceleration if the setting has been set. -if (global.store.get("disableHardwareAcceleration") === true) { +if (store.get("disableHardwareAcceleration") === true) { console.log("Disabling hardware acceleration."); app.disableHardwareAcceleration(); } @@ -467,7 +465,7 @@ app.on("ready", async () => { icon: global.trayConfig.icon_path, show: false, - autoHideMenuBar: global.store.get("autoHideMenuBar"), + autoHideMenuBar: store.get("autoHideMenuBar"), x: mainWindowState.x, y: mainWindowState.y, @@ -489,10 +487,10 @@ app.on("ready", async () => { // Handle spellchecker // For some reason spellCheckerEnabled isn't persisted, so we have to use the store here - global.mainWindow.webContents.session.setSpellCheckerEnabled(global.store.get("spellCheckerEnabled", true)); + global.mainWindow.webContents.session.setSpellCheckerEnabled(store.get("spellCheckerEnabled", true)); // Create trayIcon icon - if (global.store.get("minimizeToTray")) tray.create(global.trayConfig); + if (store.get("minimizeToTray")) tray.create(global.trayConfig); global.mainWindow.once("ready-to-show", () => { if (!global.mainWindow) return; @@ -545,7 +543,6 @@ app.on("ready", async () => { webContentsHandler(global.mainWindow.webContents); global.appLocalization = new AppLocalization({ - store: global.store, components: [(): void => tray.initApplicationMenu(), (): void => Menu.setApplicationMenu(buildMenuTemplate())], }); diff --git a/src/ipc.ts b/src/ipc.ts index ee24f040..289971e8 100644 --- a/src/ipc.ts +++ b/src/ipc.ts @@ -112,11 +112,11 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) { if (typeof args[0] !== "boolean") return; global.mainWindow.webContents.session.setSpellCheckerEnabled(args[0]); - global.store.set("spellCheckerEnabled", args[0]); + store.set("spellCheckerEnabled", args[0]); break; case "getSpellCheckEnabled": - ret = global.store.get("spellCheckerEnabled"); + ret = store.get("spellCheckerEnabled"); break; case "setSpellCheckLanguages": @@ -140,7 +140,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) { case "getPickleKey": try { - ret = await global.store.getSecret(`${args[0]}|${args[1]}`); + ret = await store.getSecret(`${args[0]}|${args[1]}`); } catch { // if an error is thrown (e.g. keytar can't connect to the keychain), // then return null, which means the default pickle key will be used @@ -151,7 +151,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) { case "createPickleKey": try { const pickleKey = await randomArray(32); - await global.store.setSecret(`${args[0]}|${args[1]}`, pickleKey); + await store.setSecret(`${args[0]}|${args[1]}`, pickleKey); ret = pickleKey; } catch (e) { console.error("Failed to create pickle key", e); @@ -161,7 +161,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) { case "destroyPickleKey": try { - await global.store.deleteSecret(`${args[0]}|${args[1]}`); + await store.deleteSecret(`${args[0]}|${args[1]}`); } catch (e) { console.error("Failed to destroy pickle key", e); } @@ -180,7 +180,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) { break; case "clearStorage": - global.store.clear(); + store.clear(); global.mainWindow.webContents.session.flushStorageData(); await global.mainWindow.webContents.session.clearStorageData(); relaunchApp(); diff --git a/src/language-helper.ts b/src/language-helper.ts index daf6e5d6..1849022c 100644 --- a/src/language-helper.ts +++ b/src/language-helper.ts @@ -12,7 +12,7 @@ import { fileURLToPath } from "node:url"; import type EN from "./i18n/strings/en_EN.json"; import { loadJsonFile } from "./utils.js"; -import { type Store } from "./store.js"; +import store from "./store.js"; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -62,10 +62,9 @@ type Component = () => void; export class AppLocalization { private static readonly STORE_KEY = "locale"; - private readonly store: Store; private readonly localizedComponents?: Set; - public constructor({ store, components = [] }: { store: Store; components: Component[] }) { + public constructor({ components = [] }: { components: Component[] }) { counterpart.registerTranslations(FALLBACK_LOCALE, this.fetchTranslationJson("en_EN")); counterpart.setFallbackLocale(FALLBACK_LOCALE); counterpart.setSeparator("|"); @@ -74,9 +73,8 @@ export class AppLocalization { this.localizedComponents = new Set(components); } - this.store = store; - if (this.store.has(AppLocalization.STORE_KEY)) { - const locales = this.store.get(AppLocalization.STORE_KEY); + if (store.has(AppLocalization.STORE_KEY)) { + const locales = store.get(AppLocalization.STORE_KEY); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.setAppLocale(locales!); } @@ -122,7 +120,7 @@ export class AppLocalization { }); counterpart.setLocale(loadedLocales[0]); - this.store.set(AppLocalization.STORE_KEY, locales); + store.set(AppLocalization.STORE_KEY, locales); this.resetLocalizedUI(); } diff --git a/src/seshat.ts b/src/seshat.ts index 9b022551..d5860832 100644 --- a/src/seshat.ts +++ b/src/seshat.ts @@ -41,12 +41,12 @@ let eventIndex: SeshatType | null = null; const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE"; async function getOrCreatePassphrase(key: string): Promise { try { - const storedPassphrase = await global.store.getSecret(key); + const storedPassphrase = await store.getSecret(key); if (storedPassphrase !== null) { return storedPassphrase; } else { const newPassphrase = await randomArray(32); - await global.store.setSecret(key, newPassphrase); + await store.setSecret(key, newPassphrase); return newPassphrase; } } catch (e) { diff --git a/src/settings.ts b/src/settings.ts index 950f84bb..a9599886 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -27,10 +27,10 @@ export const Settings: Record = { }, "Electron.warnBeforeExit": { async read(): Promise { - return global.store.get("warnBeforeExit"); + return store.get("warnBeforeExit"); }, async write(value: any): Promise { - global.store.set("warnBeforeExit", value); + store.set("warnBeforeExit", value); }, }, "Electron.alwaysShowMenuBar": { @@ -39,7 +39,7 @@ export const Settings: Record = { return !global.mainWindow!.autoHideMenuBar; }, async write(value: any): Promise { - global.store.set("autoHideMenuBar", !value); + store.set("autoHideMenuBar", !value); global.mainWindow!.autoHideMenuBar = !value; global.mainWindow!.setMenuBarVisibility(value); }, @@ -56,15 +56,15 @@ export const Settings: Record = { } else { tray.destroy(); } - global.store.set("minimizeToTray", value); + store.set("minimizeToTray", value); }, }, "Electron.enableHardwareAcceleration": { async read(): Promise { - return !global.store.get("disableHardwareAcceleration"); + return !store.get("disableHardwareAcceleration"); }, async write(value: any): Promise { - global.store.set("disableHardwareAcceleration", !value); + store.set("disableHardwareAcceleration", !value); }, }, }; diff --git a/src/store.ts b/src/store.ts index 1f4dcc93..5bc70301 100644 --- a/src/store.ts +++ b/src/store.ts @@ -29,7 +29,7 @@ const LEGACY_KEYTAR_SERVICE = "riot.im"; * Secrets are stored within the `safeStorage` object, encrypted with safeStorage. * Any secrets operations are blocked on Electron app ready emit, and keytar migration if still needed. */ -export class Store extends ElectronStore<{ +class Store extends ElectronStore<{ warnBeforeExit: boolean; minimizeToTray: boolean; spellCheckerEnabled: boolean; @@ -174,3 +174,14 @@ export class Store extends ElectronStore<{ await keytar.deletePassword(namespace, key); } } + +declare global { + // eslint-disable-next-line no-var + var store: Store; +} + +if (!global.store) { + global.store = new Store(); +} + +export default global.store;