import * as electron from "electron"; import * as path from "path"; import {screen} from "electron"; import {Arguments, processArguments} from "../../shared/process-arguments"; import * as loader from "./loader"; import * as updater from "../app-updater"; import * as url from "url"; import {loadWindowBounds, startTrackWindowBounds} from "../../shared/window"; export namespace ui { let gui: electron.BrowserWindow; let promise: Promise; let resolve: any; let reject: any; export function running() : boolean { return promise !== undefined; } export function cancel() : boolean { if(resolve) resolve(); cleanup(); return true; } export function cleanup() { if(gui) { promise = undefined; resolve = undefined; gui.destroy(); gui = undefined; reject = error => { if(error) console.error("Received error from loader after it had been closed... Error: %o", error); }; } } async function load_files() { const channel = await updater.selected_channel(); try { const entry_point = await loader.load_files(channel, (status, index) => { if(gui) { gui.webContents.send('progress-update', status, index); } }); const resolved = () => { resolve(entry_point); promise = undefined; resolve = undefined; reject = error => { if(error) console.error("Received error from loader after it had been closed... Error: %o", error); }; }; if(!processArguments.has_flag(...Arguments.DISABLE_ANIMATION)) setTimeout(resolved, 250); else setImmediate(resolved); } catch (error) { throw error; } } export function show_await_update() { if(gui) gui.webContents.send('await-update'); } function spawn_gui() { if(gui) { gui.focus(); return; } console.log("Open UI loader window."); let dev_tools = false; const WINDOW_WIDTH = 340 + (dev_tools ? 1000 : 0); const WINDOW_HEIGHT = 400 + (process.platform == "win32" ? 40 : 0); gui = new electron.BrowserWindow({ width: WINDOW_WIDTH, height: WINDOW_HEIGHT, frame: dev_tools, resizable: dev_tools, show: false, autoHideMenuBar: true, webPreferences: { webSecurity: false, nodeIntegrationInWorker: false, nodeIntegration: true } }); gui.setMenu(null); gui.loadURL(url.pathToFileURL(path.join(path.dirname(module.filename), "ui", "loading_screen.html")).toString()) gui.on('closed', () => { if(resolve) { resolve(); } gui = undefined; cleanup(); }); gui.on('ready-to-show', () => { gui.show(); try { let bounds = screen.getPrimaryDisplay()?.bounds; let x, y; if(bounds) { x = (bounds.x | 0) + ((bounds.width | 0) - WINDOW_WIDTH) / 2; y = (bounds.y | 0) + ((bounds.height | 0) - WINDOW_HEIGHT) / 2; } else { x = 0; y = 0; } console.log("Setting UI position to %ox%o", x, y); if(typeof x === "number" && typeof y === "number") gui.setPosition(x, y); } catch (error) { console.warn("Failed to apply UI position: %o", error); } loadWindowBounds('ui-load-window', gui, undefined, { applySize: false }).then(() => { startTrackWindowBounds('ui-load-window', gui); const call_loader = () => load_files().catch(reject); if(!processArguments.has_flag(...Arguments.DISABLE_ANIMATION)) setTimeout(call_loader, 1000); else setImmediate(call_loader); if(dev_tools) gui.webContents.openDevTools(); }); }); } export async function execute_loader() : Promise { return promise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject || (error => { console.error("Failed to load UI files! Error: %o", error) }); spawn_gui(); }); } export function preloading_page(entry_point: string) : string { global["browser-root"] = entry_point; /* setup entry point */ return path.join(path.dirname(module.filename), "ui", "preload_page.html"); } }