124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
/**
|
|
* IPC handlers for the unified setup installer (LibreOffice + Chromium).
|
|
* - setup:get-status — which dependencies are missing
|
|
* - setup:install-chrome — download Chromium (browser-snapshots) with progress
|
|
*/
|
|
|
|
import { ipcMain, WebContents } from "electron";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import os from "os";
|
|
import puppeteer from "puppeteer";
|
|
import {
|
|
Browser,
|
|
detectBrowserPlatform,
|
|
getInstalledBrowsers,
|
|
install,
|
|
resolveBuildId,
|
|
} from "@puppeteer/browsers";
|
|
import { getSetupStatus } from "../utils/setup-dependencies";
|
|
|
|
function getPuppeteerCacheDir(): string {
|
|
const configCache =
|
|
(puppeteer as any).configuration?.cacheDirectory ??
|
|
(puppeteer as any).defaultDownloadPath;
|
|
return configCache ?? path.join(os.homedir(), ".cache", "puppeteer");
|
|
}
|
|
|
|
function sendChromeProgress(
|
|
wc: WebContents,
|
|
phase: "downloading" | "extracting" | "done" | "error",
|
|
percent?: number,
|
|
message?: string
|
|
) {
|
|
if (!wc.isDestroyed()) {
|
|
wc.send("setup:chrome-progress", { phase, percent, message });
|
|
}
|
|
}
|
|
|
|
function sendChromeLog(wc: WebContents, level: string, text: string) {
|
|
if (!wc.isDestroyed()) {
|
|
wc.send("setup:chrome-log", { level, text });
|
|
}
|
|
}
|
|
|
|
export function setupSetupInstallHandlers() {
|
|
ipcMain.handle("setup:get-status", () => {
|
|
return getSetupStatus() ?? { needsLibreOffice: false, needsChrome: false };
|
|
});
|
|
|
|
ipcMain.handle(
|
|
"setup:install-chrome",
|
|
async (event): Promise<{ ok: boolean; error?: string }> => {
|
|
const wc = event.sender;
|
|
|
|
const cacheDir = getPuppeteerCacheDir();
|
|
const platform = detectBrowserPlatform();
|
|
if (!platform) {
|
|
const msg = "Unable to detect platform.";
|
|
sendChromeLog(wc, "error", msg);
|
|
sendChromeProgress(wc, "error", undefined, msg);
|
|
return { ok: false, error: msg };
|
|
}
|
|
|
|
let buildId: string;
|
|
try {
|
|
buildId = await resolveBuildId(
|
|
Browser.CHROMIUM,
|
|
platform,
|
|
"latest" as "latest"
|
|
);
|
|
} catch (err) {
|
|
const msg =
|
|
err instanceof Error
|
|
? err.message
|
|
: "Unable to resolve Chromium revision.";
|
|
sendChromeLog(wc, "error", msg);
|
|
sendChromeProgress(wc, "error", undefined, msg);
|
|
return { ok: false, error: msg };
|
|
}
|
|
|
|
sendChromeLog(wc, "info", `Downloading Chromium r${buildId}…`);
|
|
sendChromeProgress(wc, "downloading", 0, "Connecting…");
|
|
|
|
try {
|
|
await install({
|
|
cacheDir,
|
|
platform,
|
|
browser: Browser.CHROMIUM,
|
|
buildId,
|
|
downloadProgressCallback: (downloadedBytes, totalBytes) => {
|
|
if (totalBytes > 0 && !wc.isDestroyed()) {
|
|
const percent = Math.min(
|
|
99,
|
|
Math.round((downloadedBytes / totalBytes) * 100)
|
|
);
|
|
const mb = (n: number) => (n / 1024 / 1024).toFixed(1);
|
|
sendChromeProgress(
|
|
wc,
|
|
"downloading",
|
|
percent,
|
|
`${mb(downloadedBytes)} / ${mb(totalBytes)} MB`
|
|
);
|
|
}
|
|
},
|
|
});
|
|
} catch (err) {
|
|
const message =
|
|
err instanceof Error ? err.message : "Chromium download failed.";
|
|
sendChromeLog(wc, "error", message);
|
|
sendChromeProgress(wc, "error", undefined, message);
|
|
return { ok: false, error: message };
|
|
}
|
|
|
|
sendChromeProgress(wc, "extracting", 100, "Extracting…");
|
|
const browsers = await getInstalledBrowsers({ cacheDir });
|
|
const chromium = browsers.find((b) => b.browser === Browser.CHROMIUM);
|
|
if (chromium?.executablePath && fs.existsSync(chromium.executablePath)) {
|
|
sendChromeLog(wc, "ok", `Chromium ready at ${chromium.executablePath}`);
|
|
}
|
|
sendChromeProgress(wc, "done", 100);
|
|
return { ok: true };
|
|
}
|
|
);
|
|
}
|