Merge pull request 'Add context menu' (#16) from add-context-menu into main

Reviewed-on: https://git.internal.vyntehome.com/vynte/vynte-connect/pulls/16
This commit was merged in pull request #16.
This commit is contained in:
2026-06-01 17:56:04 -05:00
+44 -17
View File
@@ -1,4 +1,4 @@
import { app, BrowserWindow, ipcMain, nativeImage, shell, Tray } from 'electron'; import { app, BrowserWindow, ipcMain, Menu, MenuItemConstructorOptions, nativeImage, shell, Tray } from 'electron';
import path from 'node:path'; import path from 'node:path';
import started from 'electron-squirrel-startup'; import started from 'electron-squirrel-startup';
import { APP_NAME, DEFAULT_STATUS, GATEWAY_HOST, MANAGEMENT_URL, POLL_INTERVAL_MS, WINDOW_HEIGHT, WINDOW_WIDTH } from './config'; import { APP_NAME, DEFAULT_STATUS, GATEWAY_HOST, MANAGEMENT_URL, POLL_INTERVAL_MS, WINDOW_HEIGHT, WINDOW_WIDTH } from './config';
@@ -10,10 +10,29 @@ if (started) {
app.quit(); app.quit();
} }
// This method will be called when Electron has finished const singleInstanceLock = app.requestSingleInstanceLock()
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. if (!singleInstanceLock) app.quit();
app.on('ready', createWindow); else {
app.on('second-instance', () => {
if (window) {
if (window.isMinimized()) window.restore();
window.focus();
}
});
app.on('before-quit', disconnect);
}
app.whenReady().then(() => {
createWindow();
createTray();
refreshStatus();
pollTimer = setInterval(refreshStatus, POLL_INTERVAL_MS);
});
app.on('before-quit', () => {
if (pollTimer) clearInterval(pollTimer);
});
// Quit when all windows are closed, except on macOS. There, it's common // Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits // for applications and their menu bar to stay active until the user quits
@@ -65,6 +84,25 @@ function updateTray() {
if (!tray) return; if (!tray) return;
const label = cachedStatus.state === 'connected' ? `${APP_NAME}: Connected` : APP_NAME; const label = cachedStatus.state === 'connected' ? `${APP_NAME}: Connected` : APP_NAME;
tray.setToolTip(label); tray.setToolTip(label);
const template: MenuItemConstructorOptions[] = [];
const connected = cachedStatus.state === "connected";
const busy = ['connecting', 'disconnecting'].includes(cachedStatus.state);
template.push({
label: connected ? 'Disconnect' : 'Connect',
click: connected ? disconnect : connect,
enabled: !busy
});
template.push(
{
label: 'Logout',
click: logout
},
{ role: 'quit' }
);
tray.setContextMenu(Menu.buildFromTemplate(template));
} }
function setStatus(status: Record<string, any>) { function setStatus(status: Record<string, any>) {
@@ -187,21 +225,10 @@ function showWindow() {
function createTray() { function createTray() {
const icon = nativeImage.createFromPath(resourcePath('VynteIcon.png')).resize({ width: 18, height: 18 }); const icon = nativeImage.createFromPath(resourcePath('VynteIcon.png')).resize({ width: 18, height: 18 });
tray = new Tray(icon); tray = new Tray(icon);
tray.setToolTip(APP_NAME); updateTray();
tray.on('click', showWindow); tray.on('click', showWindow);
} }
app.whenReady().then(() => {
createWindow();
createTray();
refreshStatus();
pollTimer = setInterval(refreshStatus, POLL_INTERVAL_MS);
});
app.on('before-quit', () => {
if (pollTimer) clearInterval(pollTimer);
});
ipcMain.handle('status:get', () => withAutoConnect(cachedStatus)); ipcMain.handle('status:get', () => withAutoConnect(cachedStatus));
ipcMain.handle('status:refresh', refreshStatus); ipcMain.handle('status:refresh', refreshStatus);
ipcMain.handle('vpn:connect', connect); ipcMain.handle('vpn:connect', connect);