TeaSpeak-Client/modules/core/main_window.ts
2019-07-24 20:27:10 +02:00

275 lines
8.8 KiB
TypeScript

import {BrowserWindow, Menu, MenuItem, MessageBoxOptions, app, dialog} from "electron";
import * as electron from "electron";
import * as winmgr from "./window";
export let prevent_instant_close: boolean = true;
export function set_prevent_instant_close(flag: boolean) {
prevent_instant_close = flag;
}
export let is_debug: boolean;
export let allow_dev_tools: boolean;
import {Arguments, parse_arguments, process_args} from "../shared/process-arguments";
import * as updater from "./app-updater";
import * as loader from "./ui-loader";
import {open as open_changelog} from "./app-updater/changelog";
import * as crash_handler from "../crash_handler";
// 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 main_window: BrowserWindow = null;
function create_menu() : Menu {
const menu = new Menu();
if(allow_dev_tools) {
menu.append(new MenuItem({
id: "developer-tools",
enabled: true,
label: "Developer",
submenu: [
{
id: "tool-dev-tools",
label: "Open developer tools",
enabled: true,
click: event => {
main_window.webContents.openDevTools();
}
},
{
id: "tool-page-reload",
label: "Reload current page",
enabled: true,
click: event => {
main_window.reload();
}
}
]
}));
menu.items[0].visible = false;
}
menu.append(new MenuItem({
id: "help",
enabled: true,
label: "Help",
submenu: [
{
id: "update-check",
label: "Check for updates",
click: () => updater.selected_channel().then(channel => updater.execute_graphical(channel, true))
},
{
id: "changelog",
label: "View ChangeLog file",
click: open_changelog
},
{
id: "hr-01",
type: "separator"
},
{
id: "visit-home",
label: "Visit TeaSpeak.de",
click: () => electron.shell.openExternal("https://teaspeak.de")
},
{
id: "visit-support",
label: "Get support",
click: () => electron.shell.openExternal("https://forum.teaspeak.de")
},
{
id: "about-teaclient",
label: "About TeaClient",
click: () => {
updater.current_version().then(version => {
dialog.showMessageBox({
title: "TeaClient info",
message: "TeaClient by TeaSpeak (WolverinDEV)\nVersion: " + version.toString(true),
buttons: ["close"]
} as MessageBoxOptions, result => {});
});
}
},
]
}));
return menu;
}
function spawn_main_window(entry_point: string) {
// Create the browser window.
console.log("Spawning main window");
main_window = new BrowserWindow({
width: 800,
height: 600,
show: false,
webPreferences: {
webSecurity: false,
nodeIntegrationInWorker: true,
nodeIntegration: true
},
});
const menu = create_menu();
if(menu.items.length > 0)
main_window.setMenu(menu);
main_window.webContents.on('devtools-closed', event => {
console.log("Dev tools destroyed!");
});
main_window.on('closed', () => {
main_window = null;
prevent_instant_close = false;
});
main_window.loadFile(loader.ui.preloading_page(entry_point));
main_window.once('ready-to-show', () => {
main_window.show();
winmgr.apply_bounds('main-window', main_window).then(() => {
winmgr.track_bounds('main-window', main_window);
main_window.focus();
loader.ui.cleanup();
if(allow_dev_tools && !main_window.webContents.isDevToolsOpened())
main_window.webContents.openDevTools();
prevent_instant_close = false; /* just to ensure that the client could be unloaded */
});
});
main_window.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
console.log("Got new window " + frameName);
if (frameName === 'teaforo-login') {
// open window as modal
Object.assign(options, {
modal: true,
parent: main_window,
width: 100,
height: 100
});
let a = new BrowserWindow(options);
a.show();
} else {
const url_preview = require("./url-preview");
url_preview.open_preview(url);
}
event.preventDefault();
});
main_window.webContents.on('crashed', event => {
console.error("UI thread crashed! Closing app!");
if(!process_args.has_flag(Arguments.DEBUG)) {
main_window.close();
prevent_instant_close = false;
}
});
}
function handle_error(message: string) {
console.log("Caught loading error: %s", message);
//"A critical error happened while loading TeaClient!", "A critical error happened while loading TeaClient!<br>" + message
dialog.showMessageBox({
type: "error",
buttons: ["exit"],
title: "A critical error happened while loading TeaClient!",
message: message
});
loader.ui.cancel();
}
function init_listener() {
app.on('quit', () => {
console.debug("Finalizing crash handler");
crash_handler.finalize_handler();
console.log("RUNNING quit!");
loader.cleanup();
console.log("RUNNING quit 2!");
loader.ui.cleanup();
console.log("RUNNING quit done!");
});
app.on('window-all-closed', () => {
console.log("RUNNING all win closed!");
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
if(!prevent_instant_close) {
console.log("All windows have been closed, closing app.");
app.quit();
} else {
console.log("All windows have been closed, but we dont want to quit instantly. Waiting 10 seconds if something happens");
setTimeout(() => {
if(BrowserWindow.getAllWindows().length == 0) {
console.log("All windows have been closed for over an minute. Exiting app!");
app.quit();
}
}, 10 * 1000);
}
}
});
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (main_window === null) {
//spawn_loading_screen();
//createWindow()
}
});
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
console.log("Allowing untrusted certificate for %o", url);
event.preventDefault();
callback(true);
});
}
export function execute() {
console.log("Main app executed!");
parse_arguments();
is_debug = process_args.has_flag(...Arguments.DEBUG);
allow_dev_tools = process_args.has_flag(...Arguments.DEV_TOOLS);
if(is_debug) {
console.log("Enabled debug!");
console.log("Arguments: %o", process_args);
}
Menu.setApplicationMenu(null);
init_listener();
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) => {
loader.ui.cleanup(); /* close the window */
if(entry_point) //has not been canceled
spawn_main_window(entry_point);
else {
console.warn("Missing entry point!");
}
}).catch(handle_error);
}