import { type JSONSchema } from "json-schema-typed"; import { ipcMain } from "electron"; import Store from "electron-store"; import { destroyDiscordRpc, initDiscordRpc } from "./discordRpc"; import { mainWindow } from "./window"; const schema = { firstLaunch: { type: "boolean", } as JSONSchema.Boolean, customFrame: { type: "boolean", } as JSONSchema.Boolean, customFrameNativeMenu: { type: "boolean", } as JSONSchema.Boolean, minimiseToTray: { type: "boolean", } as JSONSchema.Boolean, disableTrayClick: { type: "boolean", } as JSONSchema.Boolean, startMinimisedToTray: { type: "boolean", } as JSONSchema.Boolean, spellchecker: { type: "boolean", } as JSONSchema.Boolean, hardwareAcceleration: { type: "boolean", } as JSONSchema.Boolean, discordRpc: { type: "boolean", } as JSONSchema.Boolean, gamePresenceEnabled: { type: "boolean", } as JSONSchema.Boolean, gamePresenceRestrictToAllowList: { type: "boolean", } as JSONSchema.Boolean, gamePresenceAllowList: { type: "string", } as JSONSchema.String, windowState: { type: "object", properties: { x: { type: "number", } as JSONSchema.Number, y: { type: "number", } as JSONSchema.Number, width: { type: "number", } as JSONSchema.Number, height: { type: "number", } as JSONSchema.Number, isMaximised: { type: "boolean", } as JSONSchema.Boolean, }, } as JSONSchema.Object, }; const store = new Store({ schema, defaults: { firstLaunch: true, customFrame: true, customFrameNativeMenu: false, minimiseToTray: true, disableTrayClick: false, startMinimisedToTray: false, spellchecker: true, hardwareAcceleration: true, discordRpc: true, gamePresenceEnabled: true, gamePresenceRestrictToAllowList: true, gamePresenceAllowList: "", windowState: { x: 0, y: 0, width: 0, height: 0, isMaximised: false, }, } as DesktopConfig, }); /** * Shim for `electron-store` because typings are broken */ class Config { sync() { mainWindow.webContents.send("config", { firstLaunch: this.firstLaunch, customFrame: this.customFrame, customFrameNativeMenu: this.customFrameNativeMenu, minimiseToTray: this.minimiseToTray, disableTrayClick: this.disableTrayClick, startMinimisedToTray: this.startMinimisedToTray, spellchecker: this.spellchecker, hardwareAcceleration: this.hardwareAcceleration, discordRpc: this.discordRpc, gamePresenceEnabled: this.gamePresenceEnabled, gamePresenceRestrictToAllowList: this.gamePresenceRestrictToAllowList, gamePresenceAllowList: this.gamePresenceAllowList, windowState: this.windowState, }); } get firstLaunch() { return (store as never as { get(k: string): boolean }).get("firstLaunch"); } set firstLaunch(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "firstLaunch", value, ); this.sync(); } get customFrame() { return (store as never as { get(k: string): boolean }).get("customFrame"); } set customFrame(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "customFrame", value, ); this.sync(); } get customFrameNativeMenu() { return (store as never as { get(k: string): boolean }).get("customFrameNativeMenu"); } set customFrameNativeMenu(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "customFrameNativeMenu", value, ); this.sync(); } get disableTrayClick() { return (store as never as { get(k: string): boolean }).get( "disableTrayClick", ); } set disableTrayClick(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "disableTrayClick", value, ); this.sync(); } get minimiseToTray() { return (store as never as { get(k: string): boolean }).get( "minimiseToTray", ); } set minimiseToTray(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "minimiseToTray", value, ); this.sync(); } get startMinimisedToTray() { return (store as never as { get(k: string): boolean }).get( "startMinimisedToTray", ); } set startMinimisedToTray(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "startMinimisedToTray", value, ); this.sync(); } get spellchecker() { return (store as never as { get(k: string): boolean }).get("spellchecker"); } set spellchecker(value: boolean) { mainWindow.webContents.session.setSpellCheckerEnabled(value); (store as never as { set(k: string, value: boolean): void }).set( "spellchecker", value, ); this.sync(); } get hardwareAcceleration() { return (store as never as { get(k: string): boolean }).get( "hardwareAcceleration", ); } set hardwareAcceleration(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "hardwareAcceleration", value, ); this.sync(); } get discordRpc() { return (store as never as { get(k: string): boolean }).get("discordRpc"); } set discordRpc(value: boolean) { if (value) { initDiscordRpc(); } else { destroyDiscordRpc(); } (store as never as { set(k: string, value: boolean): void }).set( "discordRpc", value, ); this.sync(); } get gamePresenceEnabled() { return (store as never as { get(k: string): boolean }).get("gamePresenceEnabled"); } set gamePresenceEnabled(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "gamePresenceEnabled", value, ); this.sync(); } get gamePresenceRestrictToAllowList() { return (store as never as { get(k: string): boolean }).get( "gamePresenceRestrictToAllowList", ); } set gamePresenceRestrictToAllowList(value: boolean) { (store as never as { set(k: string, value: boolean): void }).set( "gamePresenceRestrictToAllowList", value, ); this.sync(); } get gamePresenceAllowList() { return (store as never as { get(k: string): string }).get("gamePresenceAllowList"); } set gamePresenceAllowList(value: string) { (store as never as { set(k: string, value: string): void }).set( "gamePresenceAllowList", value, ); this.sync(); } get windowState() { return ( store as never as { get(k: string): DesktopConfig["windowState"] } ).get("windowState"); } set windowState(value: DesktopConfig["windowState"]) { ( store as never as { set(k: string, value: DesktopConfig["windowState"]): void; } ).set("windowState", value); this.sync(); } } export const config = new Config(); ipcMain.on("config", (_, newConfig: Partial) => { console.info("Received new configuration", newConfig); Object.entries(newConfig).forEach( ([key, value]) => (config[key as keyof DesktopConfig] = value as never), ); });