production-taskbar-client / src / main / ipc / informingChannel.js
informingChannel.js
Raw
import path from "path";
import { BrowserWindow, app, ipcMain, screen, Menu } from "electron";
import { createBarcodeHandler, parseUserId } from "../utils/barcodeHandler";
import createBrowserWindowTemplate from "../utils/createBrowserWindowTemplate";
import openDevToolsWindow from "../utils/openDevToolsWindow";

const isDev = process.env.NODE_ENV === "development";
const kInformingChannel = "informing";
const kInputEventChannel = "input-event";
let connectionStatus = false;

export default async function initInformingChannel(mainWindow) {
  const route = "informing";
  let url = `file:///${app
    .getAppPath()
    .replace(/\\/g, "/")}/dist/renderer/index.html#/${route}`;

  if (isDev) {
    url = `http://localhost:4000/#/${route}`;
  }

  const win = new BrowserWindow({
    show: false,
    alwaysOnTop: true,
    movable: true,
    resizable: true,
    minimizable: false,
    backgroundColor: "lightblue",
    hasShadow: false,
    webPreferences: {
      preload: path.join(app.getAppPath(), "./dist/preload.js"),
      nodeIntegration: true,
      contextIsolation: false,
      backgroundThrottling: true,
      devTools: isDev,
      additionalArguments: [route],
    },
  });
  win.setMenu(null);
  win.setAlwaysOnTop(true, "pop-up-menu");
  win.setFocusable(false);
  win.loadURL(url);

  const barcodeProcessor = (barcode) => {
    const userId = parseUserId(barcode);
    if (userId) win.webContents.send(kInputEventChannel, userId);
  };

  const barcodeHandler = createBarcodeHandler(barcodeProcessor, 200, 4);

  const inputEventCallback = (message) => {
    if (message.event === "key-down") {
      const { char } = message.data;
      barcodeHandler(char);
    }
  };

  win.on("show", () => {
    setTimeout(() => win.focus(), 200);
    ipcMain.on(kInputEventChannel, inputEventCallback);
  });

  win.on("close", (e) => {
    e.preventDefault();
    win.hide();
    ipcMain.removeListener(kInputEventChannel, inputEventCallback);
    win.webContents.send(kInformingChannel, { event: "hidden" });
  });

  win.webContents.on("will-navigate", (e, navUrl) => {
    // preventDefault and url check exists because "will-navigate" emits with undefined url after rxdb indexedDB.deleteDatabase recreated
    // navUrl compared with url to prevent open while dev hot reload
    if (navUrl && navUrl !== url) {
      e.preventDefault();
      let externalWin = new BrowserWindow({
        alwaysOnTop: true,
        center: true,
      });
      externalWin.setMenu(
        Menu.buildFromTemplate(
          createBrowserWindowTemplate(externalWin, "informing external url")
        )
      );

      externalWin.on("closed", () => {
        externalWin = null;
      });

      externalWin.loadURL(url);
    }
  });

  ipcMain.handle(kInformingChannel, async (_e, { event, data }) => {
    switch (event) {
      case "show": {
        const { isOverlay } = data;
        const { width: screenWidth, height: screenHeight } =
          screen.getPrimaryDisplay().size;
        if (isOverlay) {
          const { height: winh } = win.getBounds();
          const { height: winContentH } = win.getContentBounds();
          const titleH = Math.floor(winh - winContentH) - 8;
          win.unmaximize(); // setBounds doesnt work on maximized win
          win.setOpacity(0.8);
          win.setBounds({
            x: 0,
            y: 0 - titleH, // y with offset to hide title
            width: Math.floor(screenWidth),
            height: Math.floor(screenHeight / 5),
          });
          win.setIgnoreMouseEvents(true);
          win.show();
        } else {
          win.setOpacity(1);
          win.setIgnoreMouseEvents(false);
          // reset size
          win.setSize(
            Math.floor(screenWidth / 1.5),
            Math.floor(screenHeight / 1.5)
          );
          win.center();
          win.maximize();
        }
        return true;
      }
      case "hide":
        win.hide();
        return true;
      case "set-closable":
        win.setClosable(data);
        return true;
      case "open-devtools":
        openDevToolsWindow({ window: win, title: "Informing window" });
        return true;
      case "connection-status":
        return connectionStatus;
      case "connection-changed":
        connectionStatus = data;
        mainWindow.webContents.send(kInformingChannel, {
          event: "connection-changed",
          data,
        });
        return true;
      default:
        break;
    }
    return false;
  });
}