2024-05-14 23:51:25 +03:00
|
|
|
import {
|
|
|
|
BrowserWindow,
|
|
|
|
Menu,
|
|
|
|
MenuItem,
|
|
|
|
MenuItemConstructorOptions,
|
|
|
|
Tray,
|
|
|
|
app,
|
2024-06-01 05:14:14 +03:00
|
|
|
nativeImage,
|
2024-05-14 23:51:25 +03:00
|
|
|
shell,
|
|
|
|
} from "electron";
|
2024-04-25 07:52:19 +03:00
|
|
|
import { is } from "@electron-toolkit/utils";
|
2024-04-21 08:26:29 +03:00
|
|
|
import { t } from "i18next";
|
|
|
|
import path from "node:path";
|
2024-04-29 13:01:34 +03:00
|
|
|
import icon from "@resources/icon.png?asset";
|
|
|
|
import trayIcon from "@resources/tray-icon.png?asset";
|
2024-05-14 23:51:25 +03:00
|
|
|
import { gameRepository, userPreferencesRepository } from "@main/repository";
|
|
|
|
import { IsNull, Not } from "typeorm";
|
2024-06-20 15:22:12 +03:00
|
|
|
import { HydraApi } from "./hydra-api";
|
2024-04-21 08:26:29 +03:00
|
|
|
|
|
|
|
export class WindowManager {
|
|
|
|
public static mainWindow: Electron.BrowserWindow | null = null;
|
2024-05-24 21:02:45 +03:00
|
|
|
|
2024-04-25 07:52:19 +03:00
|
|
|
private static loadURL(hash = "") {
|
|
|
|
// HMR for renderer base on electron-vite cli.
|
|
|
|
// Load the remote URL for development or the local html file for production.
|
|
|
|
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
|
2024-04-25 22:54:38 +03:00
|
|
|
this.mainWindow?.loadURL(
|
2024-04-25 07:52:19 +03:00
|
|
|
`${process.env["ELECTRON_RENDERER_URL"]}#/${hash}`
|
|
|
|
);
|
|
|
|
} else {
|
2024-04-25 22:54:38 +03:00
|
|
|
this.mainWindow?.loadFile(
|
|
|
|
path.join(__dirname, "../renderer/index.html"),
|
|
|
|
{
|
|
|
|
hash,
|
|
|
|
}
|
|
|
|
);
|
2024-04-25 07:52:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-04 21:07:19 +03:00
|
|
|
public static createMainWindow() {
|
2024-05-27 03:49:32 +03:00
|
|
|
if (this.mainWindow) return;
|
2024-05-19 20:56:06 +03:00
|
|
|
|
2024-04-21 08:26:29 +03:00
|
|
|
this.mainWindow = new BrowserWindow({
|
|
|
|
width: 1200,
|
|
|
|
height: 720,
|
|
|
|
minWidth: 1024,
|
|
|
|
minHeight: 540,
|
2024-05-20 23:41:57 +03:00
|
|
|
backgroundColor: "#1c1c1c",
|
2024-04-21 08:26:29 +03:00
|
|
|
titleBarStyle: "hidden",
|
2024-05-03 19:17:53 +03:00
|
|
|
...(process.platform === "linux" ? { icon } : {}),
|
|
|
|
trafficLightPosition: { x: 16, y: 16 },
|
2024-04-21 08:26:29 +03:00
|
|
|
titleBarOverlay: {
|
|
|
|
symbolColor: "#DADBE1",
|
|
|
|
color: "#151515",
|
|
|
|
height: 34,
|
|
|
|
},
|
|
|
|
webPreferences: {
|
|
|
|
preload: path.join(__dirname, "../preload/index.mjs"),
|
|
|
|
sandbox: false,
|
|
|
|
},
|
2024-05-26 01:18:08 +03:00
|
|
|
show: false,
|
2024-04-21 08:26:29 +03:00
|
|
|
});
|
|
|
|
|
2024-04-25 07:52:19 +03:00
|
|
|
this.loadURL();
|
2024-04-21 08:26:29 +03:00
|
|
|
this.mainWindow.removeMenu();
|
|
|
|
|
2024-05-04 17:09:43 +03:00
|
|
|
this.mainWindow.on("ready-to-show", () => {
|
|
|
|
if (!app.isPackaged) WindowManager.mainWindow?.webContents.openDevTools();
|
2024-05-26 01:18:08 +03:00
|
|
|
WindowManager.mainWindow?.show();
|
2024-05-04 17:09:43 +03:00
|
|
|
});
|
|
|
|
|
2024-05-04 21:07:19 +03:00
|
|
|
this.mainWindow.on("close", async () => {
|
|
|
|
const userPreferences = await userPreferencesRepository.findOne({
|
|
|
|
where: { id: 1 },
|
|
|
|
});
|
|
|
|
|
2024-05-03 20:58:45 +03:00
|
|
|
if (userPreferences?.preferQuitInsteadOfHiding) {
|
|
|
|
app.quit();
|
|
|
|
}
|
|
|
|
WindowManager.mainWindow?.setProgressBar(-1);
|
2024-04-21 08:26:29 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-06-20 15:22:12 +03:00
|
|
|
public static openAuthWindow() {
|
|
|
|
if (this.mainWindow) {
|
|
|
|
const authWindow = new BrowserWindow({
|
|
|
|
width: 600,
|
|
|
|
height: 640,
|
|
|
|
backgroundColor: "#1c1c1c",
|
|
|
|
parent: this.mainWindow,
|
|
|
|
modal: true,
|
|
|
|
show: false,
|
|
|
|
maximizable: false,
|
|
|
|
resizable: false,
|
|
|
|
minimizable: false,
|
|
|
|
webPreferences: {
|
|
|
|
sandbox: false,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
authWindow.removeMenu();
|
|
|
|
|
|
|
|
authWindow.loadURL("http://localhost:3000");
|
|
|
|
|
|
|
|
authWindow.once("ready-to-show", () => {
|
|
|
|
authWindow.show();
|
|
|
|
});
|
|
|
|
|
|
|
|
authWindow.webContents.on("will-navigate", (_event, url) => {
|
|
|
|
if (url.startsWith("hydralauncher://auth")) {
|
|
|
|
authWindow.close();
|
|
|
|
|
|
|
|
HydraApi.handleExternalAuth(url);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-25 07:52:19 +03:00
|
|
|
public static redirect(hash: string) {
|
2024-04-21 08:26:29 +03:00
|
|
|
if (!this.mainWindow) this.createMainWindow();
|
2024-04-25 07:52:19 +03:00
|
|
|
this.loadURL(hash);
|
2024-04-21 08:26:29 +03:00
|
|
|
|
2024-04-25 22:54:38 +03:00
|
|
|
if (this.mainWindow?.isMinimized()) this.mainWindow.restore();
|
|
|
|
this.mainWindow?.focus();
|
2024-04-21 08:26:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public static createSystemTray(language: string) {
|
2024-06-01 05:14:14 +03:00
|
|
|
let tray;
|
|
|
|
|
|
|
|
if (process.platform === "darwin") {
|
|
|
|
const macIcon = nativeImage
|
|
|
|
.createFromPath(trayIcon)
|
|
|
|
.resize({ width: 24, height: 24 });
|
|
|
|
tray = new Tray(macIcon);
|
|
|
|
} else {
|
|
|
|
tray = new Tray(trayIcon);
|
|
|
|
}
|
2024-04-21 08:26:29 +03:00
|
|
|
|
2024-05-14 23:51:25 +03:00
|
|
|
const updateSystemTray = async () => {
|
|
|
|
const games = await gameRepository.find({
|
|
|
|
where: {
|
|
|
|
isDeleted: false,
|
|
|
|
executablePath: Not(IsNull()),
|
2024-05-16 17:26:45 +03:00
|
|
|
lastTimePlayed: Not(IsNull()),
|
2024-04-21 08:26:29 +03:00
|
|
|
},
|
2024-05-14 23:51:25 +03:00
|
|
|
take: 5,
|
|
|
|
order: {
|
2024-05-28 06:00:39 +03:00
|
|
|
lastTimePlayed: "DESC",
|
2024-05-14 23:51:25 +03:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const recentlyPlayedGames: Array<MenuItemConstructorOptions | MenuItem> =
|
2024-05-16 17:26:45 +03:00
|
|
|
games.map(({ title, executablePath }) => ({
|
2024-05-14 23:51:25 +03:00
|
|
|
label: title,
|
|
|
|
type: "normal",
|
|
|
|
click: async () => {
|
|
|
|
if (!executablePath) return;
|
|
|
|
|
|
|
|
shell.openPath(executablePath);
|
|
|
|
},
|
|
|
|
}));
|
|
|
|
|
|
|
|
const contextMenu = Menu.buildFromTemplate([
|
|
|
|
{
|
|
|
|
label: t("open", {
|
|
|
|
ns: "system_tray",
|
|
|
|
lng: language,
|
|
|
|
}),
|
|
|
|
type: "normal",
|
|
|
|
click: () => {
|
|
|
|
if (this.mainWindow) {
|
|
|
|
this.mainWindow.show();
|
|
|
|
} else {
|
|
|
|
this.createMainWindow();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "separator",
|
|
|
|
},
|
|
|
|
...recentlyPlayedGames,
|
|
|
|
{
|
|
|
|
type: "separator",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: t("quit", {
|
|
|
|
ns: "system_tray",
|
|
|
|
lng: language,
|
|
|
|
}),
|
|
|
|
type: "normal",
|
|
|
|
click: () => app.quit(),
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
return contextMenu;
|
|
|
|
};
|
2024-04-21 08:26:29 +03:00
|
|
|
|
2024-06-01 05:14:14 +03:00
|
|
|
const showContextMenu = async () => {
|
|
|
|
const contextMenu = await updateSystemTray();
|
|
|
|
tray.popUpContextMenu(contextMenu);
|
|
|
|
};
|
|
|
|
|
2024-04-21 08:26:29 +03:00
|
|
|
tray.setToolTip("Hydra");
|
|
|
|
|
2024-06-01 05:14:14 +03:00
|
|
|
if (process.platform !== "darwin") {
|
2024-04-21 08:26:29 +03:00
|
|
|
tray.addListener("click", () => {
|
|
|
|
if (this.mainWindow) {
|
2024-04-25 22:54:38 +03:00
|
|
|
if (WindowManager.mainWindow?.isMinimized())
|
2024-04-21 08:26:29 +03:00
|
|
|
WindowManager.mainWindow.restore();
|
|
|
|
|
2024-04-25 22:54:38 +03:00
|
|
|
WindowManager.mainWindow?.focus();
|
2024-04-21 08:26:29 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.createMainWindow();
|
|
|
|
});
|
2024-05-14 23:51:25 +03:00
|
|
|
|
2024-06-01 05:14:14 +03:00
|
|
|
tray.addListener("right-click", showContextMenu);
|
|
|
|
} else {
|
|
|
|
tray.addListener("click", showContextMenu);
|
|
|
|
tray.addListener("right-click", showContextMenu);
|
2024-04-21 08:26:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|