/** * setup-dependencies.ts * * Single installer window that ensures LibreOffice and Chrome (Puppeteer) are * available before the user starts creating presentations. Runs checks, then * if either is missing shows one installer that runs LibreOffice then Chrome * in sequence (each with Install / Skip). */ import { BrowserWindow, ipcMain } from "electron"; import * as path from "path"; import { baseDir } from "./constants"; import { isLibreOfficeInstalled } from "./libreoffice-check"; import { isChromeInstalled, type SetupStatus, } from "./puppeteer-check"; export type { SetupStatus }; /** Set by checkDependenciesBeforeWindow; read by setup installer IPC. */ let currentSetupStatus: SetupStatus | null = null; export function getSetupStatus(): SetupStatus | null { return currentSetupStatus; } /** * Checks LibreOffice and Chrome. If both are present, returns immediately. * If either is missing, opens one installer window that runs LibreOffice * then Chrome in sequence. Returns true only when all required dependencies * are installed; false when the installer is closed/skipped before completion. */ export async function checkDependenciesBeforeWindow(): Promise { const [loResult, chromeInstalled] = await Promise.all([ isLibreOfficeInstalled(), isChromeInstalled(), ]); const needsLibreOffice = !loResult.installed; const needsChrome = !chromeInstalled; if (!needsLibreOffice && !needsChrome) { return true; } currentSetupStatus = { needsLibreOffice, needsChrome, }; await showSetupInstallerWindow(); // Re-check after installer closes; setup can only proceed when all // required dependencies are actually installed. const [postLoResult, postChromeInstalled] = await Promise.all([ isLibreOfficeInstalled(), isChromeInstalled(), ]); currentSetupStatus = null; return postLoResult.installed && postChromeInstalled; } /** * Opens the unified setup installer window (LibreOffice then Chrome). * Resolves when the window is closed. */ function showSetupInstallerWindow(): Promise { return new Promise((resolve) => { const win = new BrowserWindow({ width: 520, height: 600, resizable: false, center: true, title: "Presenton – Setup required", icon: path.join( baseDir, "resources/ui/assets/images/presenton_short_filled.png" ), webPreferences: { webSecurity: false, preload: path.join(__dirname, "../preloads/setup-installer.js"), }, }); win.setMenuBarVisibility(false); win.loadFile( path.join(baseDir, "resources/ui/setup-installer/index.html") ); const onDone = () => { if (!win.isDestroyed()) win.close(); }; ipcMain.once("setup:done", onDone); win.on("closed", () => { ipcMain.removeListener("setup:done", onDone); resolve(); }); }); }