TeaSpeak-Client/modules/core/main-window/index.ts
2020-10-01 10:56:22 +02:00

173 lines
5.7 KiB
TypeScript

import {BrowserWindow, app, dialog} from "electron";
import * as path from "path";
export let is_debug: boolean;
export let allow_dev_tools: boolean;
import {Arguments, processArguments} from "../../shared/process-arguments";
import * as updater from "./../app-updater";
import * as loader from "./../ui-loader";
import * as url from "url";
import {loadWindowBounds, startTrackWindowBounds} from "../../shared/window";
import {referenceApp, dereferenceApp} from "../AppInstance";
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
export let mainWindow: BrowserWindow = null;
function spawnMainWindow(rendererEntryPoint: string) {
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
console.log("Allowing untrusted certificate for %o", url);
event.preventDefault();
callback(true);
});
// Create the browser window.
console.log("Spawning main window");
referenceApp(); /* main browser window references the app */
mainWindow = new BrowserWindow({
width: 800,
height: 600,
minHeight: 600,
minWidth: 600,
show: false,
webPreferences: {
webSecurity: false,
nodeIntegrationInWorker: true,
nodeIntegration: true,
preload: path.join(__dirname, "preload.js")
},
icon: path.join(__dirname, "..", "..", "resources", "logo.ico"),
});
mainWindow.webContents.on('devtools-closed', () => {
console.log("Dev tools destroyed!");
});
mainWindow.on('closed', () => {
app.releaseSingleInstanceLock();
require("../url-preview").close();
mainWindow = null;
dereferenceApp();
});
mainWindow.loadURL(url.pathToFileURL(loader.ui.preloading_page(rendererEntryPoint)).toString()).catch(error => {
console.error("Failed to load UI entry point: %o", error);
handleUILoadingError("UI entry point failed to load");
});
mainWindow.once('ready-to-show', () => {
mainWindow.show();
loadWindowBounds('main-window', mainWindow).then(() => {
startTrackWindowBounds('main-window', mainWindow);
mainWindow.focus();
loader.ui.cleanup();
if(allow_dev_tools && !mainWindow.webContents.isDevToolsOpened())
mainWindow.webContents.openDevTools();
});
});
mainWindow.webContents.on('new-window', (event, url_str, frameName, disposition, options, additionalFeatures) => {
if(frameName.startsWith("__modal_external__")) {
return;
}
event.preventDefault();
try {
let url: URL;
try {
url = new URL(url_str);
} catch(error) {
throw "failed to parse URL";
}
{
let protocol = url.protocol.endsWith(":") ? url.protocol.substring(0, url.protocol.length - 1) : url.protocol;
if(protocol !== "https" && protocol !== "http") {
throw "invalid protocol (" + protocol + "). HTTP(S) are only supported!";
}
}
console.log("Got new window " + frameName);
const url_preview = require("./url-preview");
url_preview.open_preview(url_str);
} catch(error) {
console.error("Failed to open preview window for URL %s: %o", url_str, error);
dialog.showErrorBox("Failed to open preview", "Failed to open preview URL: " + url_str + "\nError: " + error);
}
});
mainWindow.webContents.on('crashed', () => {
console.error("UI thread crashed! Closing app!");
if(!processArguments.has_flag(Arguments.DEBUG)) {
mainWindow.close();
}
});
}
function handleUILoadingError(message: string) {
referenceApp();
console.log("Caught loading error: %s", message);
if(mainWindow) {
mainWindow.close();
mainWindow = undefined;
}
dialog.showMessageBox({
type: "error",
buttons: ["exit"],
title: "A critical error happened while loading TeaClient!",
message: (message || "no error").toString()
}).then(dereferenceApp);
loader.ui.cancel();
}
export function execute() {
console.log("Main app executed!");
is_debug = processArguments.has_flag(...Arguments.DEBUG);
allow_dev_tools = processArguments.has_flag(...Arguments.DEV_TOOLS);
if(is_debug) {
console.log("Enabled debug!");
console.log("Arguments: %o", processArguments);
}
console.log("Setting up render backend");
require("../render-backend");
console.log("Spawn loading screen");
loader.ui.execute_loader().then(async (entry_point: string) => {
/* test if the updater may have an update found */
let awaiting_update_set = false;
while(updater.update_question_open) {
if(!awaiting_update_set) {
awaiting_update_set = true;
loader.ui.show_await_update();
console.log("Awaiting update stuff to be finished");
}
await new Promise(resolve => setTimeout(resolve, 100));
}
if(updater.update_restart_pending)
return undefined;
return entry_point;
}).then((entry_point: string) => {
referenceApp(); /* because we've no windows when we close the loader UI */
loader.ui.cleanup(); /* close the window */
if(entry_point) //has not been canceled
spawnMainWindow(entry_point);
else {
handleUILoadingError("Missing UI entry point");
}
dereferenceApp();
}).catch(handleUILoadingError);
}