import path from "path"; import { BrowserWindow, app, screen, ipcMain } from "electron"; import log from "electron-log"; import settings from "../settings"; import { getHostname } from "../utils/os"; import openDevToolsWindow from "../utils/openDevToolsWindow"; import setWindowBouns from "../utils/setWindowBounds"; const isDev = process.env.NODE_ENV === "development"; const baseUrl = new URL(process.env.DATA_ACQUISITION_URL); let url = `${baseUrl.href}sebn-speedometer-next/dashboard/${getHostname()}/`; if (isDev) url = `http://127.0.0.1:3000/speedometer/dashboard/${getHostname()}/`; const kSpeedometerBoundsSettings = "speedometerBoundsSettings"; const kSpeedometerEnableSetting = "speedometerEnable"; let speedometerWindow; let speedometerDevToolsWindow; export default async function initSpeedometerChannel(mainWindow) { const defaultWidth = 240; const enableSetting = settings.get(kSpeedometerEnableSetting, false); const getSpeedometerBoundsSettings = () => { const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().size; const defaultX = screenWidth - defaultWidth; const defaultY = screenHeight / 2 - defaultWidth / 2; const speedometerSettings = settings.get(kSpeedometerBoundsSettings); if (speedometerSettings) { let { x: sX, y: sY, w: sW, h: sH } = speedometerSettings; sX = parseInt(sX, 10); sY = parseInt(sY, 10); sW = parseInt(sW, 10); sH = parseInt(sH, 10); const isBoundsValid = sX && sY && sW && sH; if (isBoundsValid) { sX = sX > defaultX || sX < 0 ? Math.floor(defaultX - 1) : sX; sY = sY > screenHeight - defaultWidth || sY < 0 ? Math.floor(defaultY - 1) : sY; sW = defaultWidth; sH = defaultWidth; return { x: sX, y: sY, width: sW, height: sH }; } } return { x: defaultX, y: defaultY, width: defaultWidth, height: defaultWidth, }; }; const createSpeedometerWindow = async () => { const { x, y, width, height } = getSpeedometerBoundsSettings(); const win = new BrowserWindow({ x, y, width, height, minWidth: width, maxWidth: width, minHeight: height, type: "toolbar", skipTaskbar: true, hasShadow: false, fullscreenable: false, maximizable: false, minimizable: false, resizable: true, movable: true, thickFrame: false, titleBarStyle: "hidden", transparent: true, alwaysOnTop: true, frame: false, show: false, webPreferences: { preload: path.join(app.getAppPath(), "./dist/preload.js"), nodeIntegration: true, contextIsolation: false, backgroundThrottling: false, enablePreferredSizeMode: true, devTools: isDev, additionalArguments: ["speedometer"], }, }); win.once("ready-to-show", () => { win.showInactive(); win.setAlwaysOnTop(true, "status"); }); win.on("moved", () => { const { x: newX, y: newY, width: newW, height: newH, } = setWindowBouns(win); settings.set(kSpeedometerBoundsSettings, { x: newX, y: newY, w: newW, h: newH, }); }); win.webContents.on( "preferred-size-changed", (event, { width: w, height: h }) => { const { height: screenHeight } = screen.getPrimaryDisplay().size; win.setSize( w >= defaultWidth ? defaultWidth : w, h >= screenHeight ? screenHeight - 100 : h ); } ); win.on("closed", () => { speedometerWindow = null; mainWindow.webContents.send("speedometer", { event: "closed" }); if (!speedometerDevToolsWindow?.isDestroyed()) speedometerDevToolsWindow?.close(); }); win.webContents.once( "did-fail-load", (_event, errorCode, errorDescription, validatedURL) => { win.close(); log.error( `Speedometer failed to load ${validatedURL}. ${errorCode}: ${errorDescription}` ); } ); if (isDev) { win.webContents.once("did-finish-load", () => { speedometerDevToolsWindow = openDevToolsWindow({ window: win, title: "Speedometer", }); }); } await win.loadURL(url); return win; }; ipcMain.handle("speedometer", async (_e, { event }) => { switch (event) { case "open": if (!speedometerWindow) { speedometerWindow = await createSpeedometerWindow(); settings.set(kSpeedometerEnableSetting, true); } return true; case "close": speedometerWindow?.destroy(); return false; case "toggle": if (speedometerWindow) { speedometerWindow?.destroy(); settings.set(kSpeedometerEnableSetting, false); return false; } speedometerWindow = await createSpeedometerWindow(); settings.set(kSpeedometerEnableSetting, true); return true; case "is-open": return !!speedometerWindow; default: return false; } }); if (enableSetting) { speedometerWindow = await createSpeedometerWindow(); } }