diff --git a/.gitignore b/.gitignore index 1e85a97..913ec66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,22 @@ node_modules/ out/ build/**/*.js -Terabit*/ \ No newline at end of file +Terabit*/ + +dist/ +node_modules/ +coverage/ +npm-debug.log +yarn-error.log +app/node_modules/ +.DS_Store +.awcache +.idea/ +.vs/ +.vscode/*.log +.eslintcache +*.iml +.envrc +junit*.xml +*.swp +tslint-rules/ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..24e85a0 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +build/ +content/ +node_modules/ +src/res/ +*.json +**/*.md \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ad4b7b6..8788251 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "electron-installer-dmg": "^4.0.0", "electron-installer-windows": "^3.0.0", "electron-packager": "^17.1.2", + "prettier": "^3.2.5", "typescript": "^5.4.2" } }, @@ -2276,6 +2277,21 @@ "node": ">=10.4.0" } }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/progress": { "version": "2.0.3", "dev": true, diff --git a/package.json b/package.json index 05eacea..f7fd7ba 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "test": "tsc -p ./src/tsconfig.json && electron .", "build-win": "electron-packager . --platform=win32 --asar --icon=content/resources/icon --path=out/ --overwrite", "build-linux": "electron-packager . --platform=linux --asar --icon=content/resources/icon --path=out/ --overwrite", - "ibuild-win": "npm run build-win && electron-installer-windows --src Terabit Desktop-win32-x64/ --icon content/logo.ico --dest out/releases/" + "ibuild-win": "npm run build-win && electron-installer-windows --src Terabit Desktop-win32-x64/ --icon content/logo.ico --dest out/releases/", + "prettier": "prettier --check \"./**/*.{ts,tsx,js}\"", + "prettier-fix": "prettier . --write" }, "repository": { "type": "git", @@ -30,6 +32,7 @@ "electron-installer-dmg": "^4.0.0", "electron-installer-windows": "^3.0.0", "electron-packager": "^17.1.2", + "prettier": "^3.2.5", "typescript": "^5.4.2" } } diff --git a/src/main.ts b/src/main.ts index 9d17843..ce12ff6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,48 +1,53 @@ -import { app } from 'electron' -import { AssignProtocolHandler } from './tbd/ProtocolHandler'; -import { Window } from './tbd/ui/Window'; -import { AppInfo, Version } from './tbd/Version'; -import {OperatingSystem} from "./tbd/OperatingSystem"; -import {Logging} from "./tbd/Logging"; +import { app } from "electron"; +import { AssignProtocolHandler } from "./tbd/ProtocolHandler"; +import { Window } from "./tbd/ui/Window"; +import { AppInfo, Version } from "./tbd/Version"; +import { OperatingSystem } from "./tbd/OperatingSystem"; +import { Logging } from "./tbd/Logging"; let SplashWindow: Window; let ParentWindow: Window; - app.whenReady().then(() => { - Logging.Info(`Loading: ${AppInfo.APP_NAME} | v${Version.VERSION_MAJOR}.${Version.VERSION_MINOR}.${Version.VERSION_BUILD} - '${Version.VERSION_CODENAME}'...`); - Logging.Info(`Running on '${OperatingSystem.GetHumanFriendlyOS()}' (${OperatingSystem.CurrentArch}).`); - // --------------------------------- Splash Screen --------------------------------- - SplashWindow = new Window(undefined, 620, 300, true); - SplashWindow.Get()?.loadFile(`${__dirname}/splash.html`).catch((result) => { - Logging.Error(`There was an error getting 'splash.html'. ${result}`); + Logging.Info( + `Loading: ${AppInfo.APP_NAME} | v${Version.VERSION_MAJOR}.${Version.VERSION_MINOR}.${Version.VERSION_BUILD} - '${Version.VERSION_CODENAME}'...`, + ); + Logging.Info( + `Running on '${OperatingSystem.GetHumanFriendlyOS()}' (${OperatingSystem.CurrentArch}).`, + ); + // --------------------------------- Splash Screen --------------------------------- + SplashWindow = new Window(undefined, 620, 300, true); + SplashWindow.Get() + ?.loadFile(`${__dirname}/splash.html`) + .catch((result) => { + Logging.Error(`There was an error getting 'splash.html'. ${result}`); }); - // --------------------------------------------------------------------------------- - SplashWindow.Show(); - AssignProtocolHandler(); - - // StartWindow(); - ParentWindow = new Window(undefined, 1366, 720); - ParentWindow.Load(); - ParentWindow.Show(); - SplashWindow.Close(); + // --------------------------------------------------------------------------------- + SplashWindow.Show(); + AssignProtocolHandler(); + + // StartWindow(); + ParentWindow = new Window(undefined, 1366, 720); + ParentWindow.Load(); + ParentWindow.Show(); + SplashWindow.Close(); }); -app.on('web-contents-created', (event, contents) => { - contents.on('will-navigate', (event, navigationUrl) => { - const parsedUrl = new URL(navigationUrl) - const allowedOrigins = ['terabit.io', 'discord.com', 'terabit.io:8080']; // Allow Discord for the Discord invite, Allow Terabit.io for the main site and the admin panel. - allowedOrigins.forEach(element => { - if (!parsedUrl.origin.endsWith(element)) { - Logging.Warn(`${element} lead to a URL outside of the allowed origin.`); - event.preventDefault(); // Stops any urls with origins outside terabit.io or discord.com from loading. - } - }); +app.on("web-contents-created", (event, contents) => { + contents.on("will-navigate", (event, navigationUrl) => { + const parsedUrl = new URL(navigationUrl); + const allowedOrigins = ["terabit.io", "discord.com", "terabit.io:8080"]; // Allow Discord for the Discord invite, Allow Terabit.io for the main site and the admin panel. + allowedOrigins.forEach((element) => { + if (!parsedUrl.origin.endsWith(element)) { + Logging.Warn(`${element} lead to a URL outside of the allowed origin.`); + event.preventDefault(); // Stops any urls with origins outside terabit.io or discord.com from loading. + } }); + }); }); -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); \ No newline at end of file +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); + } +}); diff --git a/src/res/ui/main.html b/src/res/ui/main.html new file mode 100644 index 0000000..8ef3894 --- /dev/null +++ b/src/res/ui/main.html @@ -0,0 +1,10 @@ + + + + + Terabit Desktop + + + + + \ No newline at end of file diff --git a/src/tbd/FactorySettings.ts b/src/tbd/FactorySettings.ts index e0909bb..81f918a 100644 --- a/src/tbd/FactorySettings.ts +++ b/src/tbd/FactorySettings.ts @@ -1,36 +1,39 @@ import { BrowserWindow, app } from "electron"; -const { dialog } = require('electron'); -import * as fs from 'fs'; -import * as path from 'path'; -import {Logging} from "./Logging"; +const { dialog } = require("electron"); +import * as fs from "fs"; +import * as path from "path"; +import { Logging } from "./Logging"; export class FactorySettings { + static ResetApplication(): void { + dialog + .showMessageBox(BrowserWindow.getAllWindows()[0], { + type: "warning", + buttons: ["Reset Terabit Desktop", "Cancel"], + defaultId: 0, + title: "Reset Terabit Desktop", + message: "Are you sure you wish to reset Terabit Desktop?", + detail: + "Are you sure you wish to reset Terabit Desktop? You'll need to login again after the reset.", + }) + .then((result) => { + if (result.response === 0) { + const getAppPath = path.join(app.getPath("appData"), app.getName()); - static ResetApplication(): void { - dialog.showMessageBox(BrowserWindow.getAllWindows()[0], { - type: 'warning', - buttons: ['Reset Terabit Desktop', 'Cancel'], - defaultId: 0, - title: 'Reset Terabit Desktop', - message: 'Are you sure you wish to reset Terabit Desktop?', - detail: "Are you sure you wish to reset Terabit Desktop? You'll need to login again after the reset.", - }).then((result) => { - if (result.response === 0) { - const getAppPath = path.join(app.getPath('appData'), app.getName()); + fs.unlink(getAppPath, () => { + Logging.Info( + "The cache has been cleared successfully. We just need to relaunch to apply any needed changes.", + ); + app.relaunch(); + }); + } + }); + } - fs.unlink(getAppPath, () => { - Logging.Info("The cache has been cleared successfully. We just need to relaunch to apply any needed changes."); - app.relaunch(); - }); - } - }); - } - - public static ResetCache() - { - BrowserWindow.getAllWindows().forEach(element => { - element.webContents.session.clearCache(); - element.webContents.reloadIgnoringCache(); - }); - } -} \ No newline at end of file + public static ResetCache() { + BrowserWindow.getAllWindows().forEach((element) => { + element.webContents.session.clearCache(); + element.webContents.reloadIgnoringCache(); + }); + } +} diff --git a/src/tbd/Logging.ts b/src/tbd/Logging.ts index af0bdeb..5fa17e9 100644 --- a/src/tbd/Logging.ts +++ b/src/tbd/Logging.ts @@ -1,8 +1,18 @@ -import { } from 'electron'; +import {} from "electron"; export class Logging { - public static Debug(Message: string) { if (process.argv.includes("--verbose")) { console.log(`[DEBUG]: ${Message}`); } } - public static Info(Message: string) { console.log(`[INFO]: ${Message}`); } - public static Warn(Message: string) { console.log(`[WARN]: ${Message}`); } - public static Error(Message: string) { console.log(`[ERROR]: ${Message}`); } -} \ No newline at end of file + public static Debug(Message: string) { + if (process.argv.includes("--verbose")) { + console.log(`[DEBUG]: ${Message}`); + } + } + public static Info(Message: string) { + console.log(`[INFO]: ${Message}`); + } + public static Warn(Message: string) { + console.log(`[WARN]: ${Message}`); + } + public static Error(Message: string) { + console.log(`[ERROR]: ${Message}`); + } +} diff --git a/src/tbd/OperatingSystem.ts b/src/tbd/OperatingSystem.ts index 8df4414..083aa1b 100644 --- a/src/tbd/OperatingSystem.ts +++ b/src/tbd/OperatingSystem.ts @@ -1,20 +1,19 @@ -import process from 'process'; +import process from "process"; -export class OperatingSystem -{ - public static readonly CurrentOS: string = process.platform; - public static readonly CurrentArch: string = process.arch; +export class OperatingSystem { + public static readonly CurrentOS: string = process.platform; + public static readonly CurrentArch: string = process.arch; - public static GetHumanFriendlyOS() { - switch (process.platform) { - case 'win32': - return "Windows"; - case 'linux': - return "Linux"; - case 'darwin': - return "MacOS"; - default: - return "Unknown"; - } + public static GetHumanFriendlyOS() { + switch (process.platform) { + case "win32": + return "Windows"; + case "linux": + return "Linux"; + case "darwin": + return "MacOS"; + default: + return "Unknown"; } -} \ No newline at end of file + } +} diff --git a/src/tbd/ProtocolHandler.ts b/src/tbd/ProtocolHandler.ts index 393a05f..aaebe6c 100644 --- a/src/tbd/ProtocolHandler.ts +++ b/src/tbd/ProtocolHandler.ts @@ -1,11 +1,11 @@ -import { app } from 'electron'; -import path from 'path' +import { app } from "electron"; +import path from "path"; -export function AssignProtocolHandler() -{ - if (process.defaultApp) - if (process.argv.length >= 2) - app.setAsDefaultProtocolClient('terabit', process.execPath, [path.resolve(process.argv[1])]) - else - app.setAsDefaultProtocolClient('terabit') -} \ No newline at end of file +export function AssignProtocolHandler() { + if (process.defaultApp) + if (process.argv.length >= 2) + app.setAsDefaultProtocolClient("terabit", process.execPath, [ + path.resolve(process.argv[1]), + ]); + else app.setAsDefaultProtocolClient("terabit"); +} diff --git a/src/tbd/Version.ts b/src/tbd/Version.ts index 11c76c0..66ac3d7 100644 --- a/src/tbd/Version.ts +++ b/src/tbd/Version.ts @@ -1,10 +1,10 @@ export class Version { - static VERSION_MAJOR = 1; - static VERSION_MINOR = 0; - static VERSION_BUILD = 1; - static VERSION_CODENAME = "Creek"; + static VERSION_MAJOR = 1; + static VERSION_MINOR = 0; + static VERSION_BUILD = 1; + static VERSION_CODENAME = "Creek"; } export class AppInfo { - static APP_NAME: string = "Terabit Desktop"; -} \ No newline at end of file + static APP_NAME: string = "Terabit Desktop"; +} diff --git a/src/tbd/ui/AppUrlManager.ts b/src/tbd/ui/AppUrlManager.ts index 0b1fe79..e840bfc 100644 --- a/src/tbd/ui/AppUrlManager.ts +++ b/src/tbd/ui/AppUrlManager.ts @@ -10,39 +10,39 @@ // https://gaming.terabit.io/admin/servers/view/605/details - specific sub-section of server specific admin stuff // https://gaming.terabit.io/admin/nodes - admin panel list of server nodes -export class AppUrlManager{ +export class AppUrlManager { + private static domains = ["terabit://"]; - private static domains = [ - 'terabit://' - ]; + public static GetUrl(): string { + const _args = process.argv; // Get the arguments passed to the process + const _url = + _args.find((arg) => + AppUrlManager.domains.some((domain) => arg.startsWith(domain)), + ) || "https://gaming.terabit.io/"; + const prefix = this.GetPrefix(_url); - public static GetUrl(): string { - const _args = process.argv; // Get the arguments passed to the process - const _url = _args.find(arg => AppUrlManager.domains.some(domain => arg.startsWith(domain))) || 'https://gaming.terabit.io/'; - const prefix = this.GetPrefix(_url); - - switch (prefix) { - case 'my': - return 'https://my.terabit.io/'; - case 'dcs': - const dcsPath = _url.replace("terabit://dcs", ''); - return `https://dcs.terabit.io/${dcsPath}`; - case 'vps': - const vpsPath = _url.replace('terabit://vps', ''); - return `https://vps.terabit.io/${vpsPath}`; - case 'default': - const defaultPath = _url.replace('terabit://', ''); - return `https://gaming.terabit.io/${defaultPath}`; - default: - return 'https://gaming.terabit.io/'; // owo - } + switch (prefix) { + case "my": + return "https://my.terabit.io/"; + case "dcs": + const dcsPath = _url.replace("terabit://dcs", ""); + return `https://dcs.terabit.io/${dcsPath}`; + case "vps": + const vpsPath = _url.replace("terabit://vps", ""); + return `https://vps.terabit.io/${vpsPath}`; + case "default": + const defaultPath = _url.replace("terabit://", ""); + return `https://gaming.terabit.io/${defaultPath}`; + default: + return "https://gaming.terabit.io/"; // owo } + } - private static GetPrefix(_url: string): string { - if (_url.startsWith('terabit://my')) return 'my'; - if (_url.startsWith('terabit://dcs')) return 'dcs'; - if (_url.startsWith('terabit://vps')) return 'vps'; - if (_url.startsWith('terabit://')) return 'default'; - return ''; - } -} \ No newline at end of file + private static GetPrefix(_url: string): string { + if (_url.startsWith("terabit://my")) return "my"; + if (_url.startsWith("terabit://dcs")) return "dcs"; + if (_url.startsWith("terabit://vps")) return "vps"; + if (_url.startsWith("terabit://")) return "default"; + return ""; + } +} diff --git a/src/tbd/ui/Window.ts b/src/tbd/ui/Window.ts index 91ccfdf..c2bd97c 100644 --- a/src/tbd/ui/Window.ts +++ b/src/tbd/ui/Window.ts @@ -1,108 +1,221 @@ -import { BrowserWindow, Menu, app } from 'electron'; -import { AppUrlManager } from './AppUrlManager'; -import { FactorySettings } from '../FactorySettings'; -import {Logging} from "../Logging"; +import { BrowserWindow, Menu, app } from "electron"; +import { AppUrlManager } from "./AppUrlManager"; +import { FactorySettings } from "../FactorySettings"; +import { Logging } from "../Logging"; export class Window { - private Target: BrowserWindow; - constructor(Parent: BrowserWindow | undefined, Width: number, Height: number, IsSplash: boolean = false) { - this.Target = new BrowserWindow({ width: Width, height: Height, title: "Terabit Desktop", transparent: IsSplash, frame: !IsSplash, alwaysOnTop: IsSplash, resizable: !IsSplash ,parent: Parent, webPreferences: { nodeIntegration: true, webgl: process.argv.includes("--disable-webgl"), devTools: true /* process.argv.includes("--dev-tools") */, scrollBounce: !IsSplash }}); - this.Target.setBackgroundColor("#0b0d2a"); - this.Target.maximize(); - this.ConfigureEvents(); - this.ConfigureMenu(); + private Target: BrowserWindow; + constructor( + Parent: BrowserWindow | undefined, + Width: number, + Height: number, + IsSplash: boolean = false, + ) { + this.Target = new BrowserWindow({ + width: Width, + height: Height, + title: "Terabit Desktop", + transparent: IsSplash, + frame: !IsSplash, + alwaysOnTop: IsSplash, + resizable: !IsSplash, + parent: Parent, + webPreferences: { + nodeIntegration: true, + webgl: process.argv.includes("--disable-webgl"), + devTools: true /* process.argv.includes("--dev-tools") */, + scrollBounce: !IsSplash, + }, + }); + this.Target.setBackgroundColor("#0b0d2a"); + this.Target.maximize(); + this.ConfigureEvents(); + this.ConfigureMenu(); - Logging.Debug(`A new window was created. Title: ${this.Target.title}`); - } + Logging.Debug(`A new window was created. Title: ${this.Target.title}`); + } - public Show(): void { - this.Target?.show(); - } + public Show(): void { + this.Target?.show(); + } - public Get(): BrowserWindow | null { - return this.Target; - } + public Get(): BrowserWindow | null { + return this.Target; + } - public Close(): void { - this.Target?.close(); - } + public Close(): void { + this.Target?.close(); + } - public Load(): void; - public Load(url?: string): void; - public Load(url?: string): void { - if (url) - this.Target.loadURL(url).catch((result) => { - this.Target.loadFile(`file://${__dirname}/error.html`); - }); - else - this.Target.loadURL(AppUrlManager.GetUrl()).catch((result) => { - this.Target.loadFile(`file://${__dirname}/error.html`); - }); - } - - // Configure Events + public Load(): void; + public Load(url?: string): void; + public Load(url?: string): void { + if (url) + this.Target.loadURL(url).catch((result) => { + this.Target.loadFile(`file://${__dirname}/error.html`); + }); + else + this.Target.loadURL(AppUrlManager.GetUrl()).catch((result) => { + this.Target.loadFile(`file://${__dirname}/error.html`); + }); + } - private ConfigureEvents(): void { - this.Target.webContents.session.on("will-download", (event, item, webContents) => { - item.on("updated", (event, state) => { - if (state === "interrupted") { - console.log(`[INFO]: Download was interrupted: ${item.getFilename()}`); - } else if (state === "progressing") { - if (item.isPaused()) { - console.log(`[INFO]: Download was paused: ${item.getFilename()}`); - } - } - }); + // Configure Events - item.once("done", (event, state) => { - if (state === "completed") { - console.log(`[INFO]: Download completed: ${item.getFilename()}`); - } else { - console.log(`[INFO]: Download failed: ${item.getFilename()}`); - } - }); + private ConfigureEvents(): void { + this.Target.webContents.session.on( + "will-download", + (event, item, webContents) => { + item.on("updated", (event, state) => { + if (state === "interrupted") { + console.log( + `[INFO]: Download was interrupted: ${item.getFilename()}`, + ); + } else if (state === "progressing") { + if (item.isPaused()) { + console.log(`[INFO]: Download was paused: ${item.getFilename()}`); + } + } + }); + + item.once("done", (event, state) => { + if (state === "completed") { + console.log(`[INFO]: Download completed: ${item.getFilename()}`); + } else { + console.log(`[INFO]: Download failed: ${item.getFilename()}`); + } }); - } + }, + ); + } - private ConfigureMenu(): void { - const template: (Electron.MenuItemConstructorOptions | Electron.MenuItem)[] = [ - { - label: 'Terabit Desktop', - submenu: [ - { label: 'Options', submenu: [ - { label: 'Clear Cache', click: () => { FactorySettings.ResetCache(); }}, - { label: 'Reset Application', click: () => { FactorySettings.ResetApplication(); }}, - ]}, - { type: 'separator' }, - { label: 'Quit', click: () => { app.exit() }, accelerator: 'CmdOrCtrl+Q'} - ] + private ConfigureMenu(): void { + const template: ( + | Electron.MenuItemConstructorOptions + | Electron.MenuItem + )[] = [ + { + label: "Terabit Desktop", + submenu: [ + { + label: "Options", + submenu: [ + { + label: "Clear Cache", + click: () => { + FactorySettings.ResetCache(); + }, + }, + { + label: "Reset Application", + click: () => { + FactorySettings.ResetApplication(); + }, + }, + ], + }, + { type: "separator" }, + { + label: "Quit", + click: () => { + app.exit(); }, - { - label: 'Navigation', - submenu: [ - { label: 'Dashboard', click: () => { this.Load("https://gaming.terabit.io/"); }, accelerator: 'CmdOrCtrl+1'}, - { label: 'Client Area', click: () => { this.Load("https://my.terabit.io/"); }, accelerator: 'CmdOrCtrl+2'}, - { label: 'Admin Area', click: () => { this.Load("https://gaming.terabit.io/admin"); }, accelerator: 'CmdOrCtrl+3'}, - { type: 'separator', visible: true }, - { label: 'Tenantos', click: () => { this.Load("https://dcs.terabit.io/")}, accelerator: 'CmdOrCtrl+4'}, - { label: 'VirtFusion', click: () => { this.Load("https://vps.terabit.io/")}, accelerator: 'CmdOrCtrl+5'}, - ] + accelerator: "CmdOrCtrl+Q", + }, + ], + }, + { + label: "Navigation", + submenu: [ + { + label: "Dashboard", + click: () => { + this.Load("https://gaming.terabit.io/"); }, - { - label: 'Window', - submenu: [ - { label: 'Reload', click: () => { this.Target.reload(); }, accelerator: 'CmdOrCtrl+R'}, - { label: 'Full Reload', click: () => { this.Target.webContents.reloadIgnoringCache(); }, accelerator: 'CmdOrCtrl+Alt+R'}, - { type: 'separator', visible: true }, - { label: 'Back', click: () => { this.Target.webContents.goBack(); }, accelerator: 'CmdOrCtrl+Left'}, - { label: 'Forward', click: () => { this.Target.webContents.goForward(); }, accelerator: 'CmdOrCtrl+Right'}, - { type: 'separator', visible: true }, - { label: 'Minimize', click: () => { this.Target.minimize(); }, accelerator: 'CmdOrCtrl+M'}, - { label: 'Maximize', click: () => { this.Target.maximize(); }, accelerator: 'CmdOrCtrl+Shift+M'} - ] - } - ]; - const menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); - } -} \ No newline at end of file + accelerator: "CmdOrCtrl+1", + }, + { + label: "Client Area", + click: () => { + this.Load("https://my.terabit.io/"); + }, + accelerator: "CmdOrCtrl+2", + }, + { + label: "Admin Area", + click: () => { + this.Load("https://gaming.terabit.io/admin"); + }, + accelerator: "CmdOrCtrl+3", + }, + { type: "separator", visible: true }, + { + label: "Tenantos", + click: () => { + this.Load("https://dcs.terabit.io/"); + }, + accelerator: "CmdOrCtrl+4", + }, + { + label: "VirtFusion", + click: () => { + this.Load("https://vps.terabit.io/"); + }, + accelerator: "CmdOrCtrl+5", + }, + ], + }, + { + label: "Window", + submenu: [ + { + label: "Reload", + click: () => { + this.Target.reload(); + }, + accelerator: "CmdOrCtrl+R", + }, + { + label: "Full Reload", + click: () => { + this.Target.webContents.reloadIgnoringCache(); + }, + accelerator: "CmdOrCtrl+Alt+R", + }, + { type: "separator", visible: true }, + { + label: "Back", + click: () => { + this.Target.webContents.goBack(); + }, + accelerator: "CmdOrCtrl+Left", + }, + { + label: "Forward", + click: () => { + this.Target.webContents.goForward(); + }, + accelerator: "CmdOrCtrl+Right", + }, + { type: "separator", visible: true }, + { + label: "Minimize", + click: () => { + this.Target.minimize(); + }, + accelerator: "CmdOrCtrl+M", + }, + { + label: "Maximize", + click: () => { + this.Target.maximize(); + }, + accelerator: "CmdOrCtrl+Shift+M", + }, + ], + }, + ]; + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); + } +}