Files
bodyshop-desktop/src/main/index.ts
2025-03-21 08:33:41 -07:00

271 lines
7.7 KiB
TypeScript

import { electronApp, is, optimizer } from "@electron-toolkit/utils";
import { app, BrowserWindow, Menu, shell } from "electron";
import log from "electron-log/main";
import path, { join } from "path";
import icon from "../../resources/icon.png?asset";
import ErrorTypeCheck from "../util/errorTypeCheck";
import client from "./graphql/graphql-client";
import store from "./store/store";
log.initialize();
const isMac = process.platform === "darwin";
function createWindow(): void {
// Create the browser window.
const { width, height, x, y } = store.get("app.windowBounds") as {
width: number;
height: number;
x: number | undefined;
y: number | undefined;
};
const mainWindow = new BrowserWindow({
width,
height,
x,
y,
show: false,
//autoHideMenuBar: true,
...(process.platform === "linux" ? { icon } : {}),
webPreferences: {
preload: join(__dirname, "../preload/index.js"),
sandbox: false,
devTools: true,
},
});
const template: Electron.MenuItemConstructorOptions[] = [
// { role: 'appMenu' }
...(isMac
? [
{
label: app.name,
submenu: [
{ role: "about" },
{ type: "separator" },
{ role: "services" },
{ type: "separator" },
{ role: "hide" },
{ role: "hideOthers" },
{ role: "unhide" },
{ type: "separator" },
{ role: "quit" },
],
},
]
: []),
// { role: 'fileMenu' }
{
label: "File",
submenu: [isMac ? { role: "close" } : { role: "quit" }],
},
// { role: 'editMenu' }
{
label: "Edit",
submenu: [
{ role: "undo" },
{ role: "redo" },
{ type: "separator" },
{ role: "cut" },
{ role: "copy" },
{ role: "paste" },
...(isMac
? [
{ role: "pasteAndMatchStyle" },
{ role: "delete" },
{ role: "selectAll" },
{ type: "separator" },
{
label: "Speech",
submenu: [{ role: "startSpeaking" }, { role: "stopSpeaking" }],
},
]
: [{ role: "delete" }, { type: "separator" }, { role: "selectAll" }]),
],
},
// { role: 'viewMenu' }
{
label: "View",
submenu: [
{ role: "reload" },
{ role: "forceReload" },
{ role: "toggleDevTools" },
{ type: "separator" },
{ role: "resetZoom" },
{ role: "zoomIn" },
{ role: "zoomOut" },
{ type: "separator" },
{ role: "togglefullscreen" },
],
},
// { role: 'windowMenu' }
{
label: "Window",
submenu: [
{ role: "minimize" },
{ role: "zoom" },
...(isMac
? [
{ type: "separator" },
{ role: "front" },
{ type: "separator" },
{ role: "window" },
]
: [{ role: "close" }]),
],
},
{
role: "help",
submenu: [
{
label: "Learn More",
click: async (): Promise<void> => {
const { shell } = require("electron");
await shell.openExternal("https://electronjs.org");
},
},
],
},
...(import.meta.env.DEV
? [
{
label: "Development",
submenu: [
{
label: "Open Log Folder",
click: (): void => {
/* action for item 1 */
shell.openPath(log.transports.file.getFile().path);
},
},
{
label: "Clear Log",
click: (): void => {
log.transports.file.getFile().clear();
},
},
{
label: "Open Config",
click: (): void => {
shell.openPath(path.dirname(store.path));
},
},
{
label: "Log the Store",
click: (): void => {
log.debug(
"Store Contents" + JSON.stringify(store.store, null, 4)
);
},
},
{
type: "separator",
},
{
label: "Temp Test Action - Get Token from Renderer",
click: (): void => {
client
.request(
`
query jobs{
jobs
{
id}}
`
)
.then((data) => {
log.info("Data from graffle", data);
});
},
},
],
},
]
: []),
];
const menu: Electron.Menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
// Store window properties for later
const storeWindowState = (): void => {
const [width, height] = mainWindow.getSize();
const [x, y] = mainWindow.getPosition();
store.set("app.windowBounds", { width, height, x, y });
};
mainWindow.on("resized", storeWindowState);
mainWindow.on("maximize", storeWindowState);
mainWindow.on("unmaximize", storeWindowState);
mainWindow.on("moved", storeWindowState);
mainWindow.on("ready-to-show", () => {
mainWindow.show();
});
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url);
return { action: "deny" };
});
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
mainWindow.loadURL(process.env["ELECTRON_RENDERER_URL"]);
} else {
mainWindow.loadFile(join(__dirname, "../renderer/index.html"));
}
if (import.meta.env.DEV) {
mainWindow.webContents.openDevTools();
}
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(async () => {
// Set app user model id for windows
electronApp.setAppUserModelId("com.electron");
// Default open or close DevTools by F12 in development
// and ignore CommandOrControl + R in production.
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
app.on("browser-window-created", (_, window) => {
optimizer.watchWindowShortcuts(window);
});
//Dynamically load ipcMain handlers once ready.
try {
// Replace 'path/to/your/file' with the actual path to your file
const module = await import("./ipc/ipcMainConfig");
// You can now use anything exported from the module
// For example:
// module.someFunction()
log.debug("Successfully loaded ipcMainConfig", module);
} catch (error) {
log.error("Failed to load ipcMainconfig", {
...ErrorTypeCheck(error),
});
}
createWindow();
app.on("activate", function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.