Equicord/src/main/trayMenu.ts
2026-01-30 10:55:20 -05:00

90 lines
2.8 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2026 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { IpcEvents } from "@shared/IpcEvents";
import { BrowserWindow, ipcMain, Menu, MenuItemConstructorOptions, shell } from "electron";
import { SETTINGS_DIR } from "./utils/constants";
let cachedUpdateAvailable = false;
ipcMain.on(IpcEvents.SET_TRAY_UPDATE_STATE, (_, available: boolean) => {
cachedUpdateAvailable = available;
});
function getMainWindow(): BrowserWindow | undefined {
return BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0];
}
function sendToRenderer(event: IpcEvents): void {
getMainWindow()?.webContents.send(event);
}
function findInsertIndex(template: MenuItemConstructorOptions[]): number {
const openIndex = template.findIndex(item => {
const label = item.label?.toLowerCase() ?? "";
return label.includes("open") || label.includes("show");
});
return openIndex !== -1 ? openIndex + 1 : 0;
}
function isTrayMenu(template: MenuItemConstructorOptions[]): boolean {
if (!template.length) return false;
const hasOpenOrShow = template.some(item => {
const label = item.label?.toLowerCase() ?? "";
return label.includes("open") || label.includes("show");
});
const hasQuit = template.some(item =>
item.label?.toLowerCase().includes("quit") || item.role === "quit"
);
const isNotAppMenu = !template.some(item =>
item.label === "&File" || item.label === "File" ||
item.label === "&Edit" || item.label === "Edit"
);
return hasOpenOrShow && hasQuit && isNotAppMenu;
}
function createEquicordMenuItems(): MenuItemConstructorOptions[] {
return [
{
label: "Equicord",
submenu: [
{
label: cachedUpdateAvailable ? "Update Equicord" : "Check for Updates",
click: () => sendToRenderer(IpcEvents.TRAY_CHECK_UPDATES)
},
{
label: "Repair Equicord",
click: () => sendToRenderer(IpcEvents.TRAY_REPAIR)
},
{ type: "separator" },
{
label: "Open Settings Folder",
click: () => shell.openPath(SETTINGS_DIR)
}
]
},
{ type: "separator" }
];
}
export function patchTrayMenu(): void {
const originalBuildFromTemplate = Menu.buildFromTemplate;
Menu.buildFromTemplate = function (template: MenuItemConstructorOptions[]) {
if (isTrayMenu(template)) {
const insertIndex = findInsertIndex(template);
const equicordItems = createEquicordMenuItems();
template.splice(insertIndex, 0, ...equicordItems);
}
return originalBuildFromTemplate.call(this, template);
};
}