feat: add tray window (based on electron-tray-window)

This commit is contained in:
LudoO committed 2025-02-04 16:31:24 +01:00
1 parent fa1d20df26
commit 3a7a91e187
2 files changed
+207 -44

No files matched your search

+57 -44
View File
@@ -1,6 +1,21 @@
import { app, BrowserWindow, Menu, RenderProcessGoneDetails, Tray } from 'electron'
import { app, BrowserWindow, RenderProcessGoneDetails, BrowserWindowConstructorOptions } from 'electron'
import Constants from './utils/Constants'
import IPCs from './IPCs'
import { createTray, setWindowAutoHide, showWindow } from './tray.ts'
const options = {
tray: true,
trayWindow: true,
width: Constants.IS_DEV_ENV ? 1500 : 1200,
height: 650,
trayOptions: {
menu: false,
tooltip: 'Vutron App',
margin: {x:0, y:0},
width: Constants.IS_DEV_ENV ? 1500 : 1200,
height: 650,
}
}
const exitApp = (mainWindow: BrowserWindow): void => {
if (mainWindow && !mainWindow.isDestroyed()) {
@@ -10,15 +25,35 @@ const exitApp = (mainWindow: BrowserWindow): void => {
app.exit()
}
export const createMainWindow = async (mainWindow: BrowserWindow): Promise<BrowserWindow> => {
mainWindow = new BrowserWindow({
export const createMainWindow = async (): Promise<BrowserWindow> => {
let opt: BrowserWindowConstructorOptions = {
title: Constants.APP_NAME,
show: false,
width: Constants.IS_DEV_ENV ? 1500 : 1200,
height: 650,
width: options.width,
height: options.height,
useContentSize: true,
webPreferences: Constants.DEFAULT_WEB_PREFERENCES
})
webPreferences: Constants.DEFAULT_WEB_PREFERENCES,
frame: !options.trayWindow,
}
if (options.trayWindow){
opt = {
...opt,
width: options.trayOptions.width ,
height: options.trayOptions.height,
maxWidth: options.trayOptions.width,
maxHeight: options.trayOptions.height,
show: false,
frame: false,
fullscreenable: false,
resizable: false,
transparent: true,
alwaysOnTop: true,
webPreferences: {
backgroundThrottling: false
}
}
}
const mainWindow = new BrowserWindow(opt)
mainWindow.setMenu(null)
@@ -33,12 +68,21 @@ export const createMainWindow = async (mainWindow: BrowserWindow): Promise<Brows
}
})
mainWindow.once('ready-to-show', (): void => {
mainWindow.setAlwaysOnTop(true)
mainWindow.show()
mainWindow.focus()
mainWindow.setAlwaysOnTop(false)
})
if (options.tray) {
createTray(mainWindow, options.trayOptions);
}
if (options.trayWindow) {
setWindowAutoHide(mainWindow);
// showWindow(mainWindow)
}else{
mainWindow.once('ready-to-show', (): void => {
mainWindow.setAlwaysOnTop(true)
mainWindow.show()
mainWindow.focus()
mainWindow.setAlwaysOnTop(false)
})
}
// Initialize IPC Communication
IPCs.initialize()
@@ -49,8 +93,6 @@ export const createMainWindow = async (mainWindow: BrowserWindow): Promise<Brows
await mainWindow.loadFile(Constants.APP_INDEX_URL_PROD)
}
createTray(mainWindow);
return mainWindow
}
@@ -94,32 +136,3 @@ export const createErrorWindow = async (
return errorWindow
}
function createTray(mainWindow) {
const tray = new Tray('buildAssets/icons/icon16.png');
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show App',
click: () => {
mainWindow.show();
}
},
{
label: 'Hide App',
click: () => {
mainWindow.hide();
}
},
{
label: 'Exit',
click: () => {
app.quit();
}
}
]);
tray.on('double-click', function (event) {
mainWindow.show();
});
tray.setToolTip('Vutron App');
tray.setContextMenu(contextMenu);
}
+150
View File
@@ -0,0 +1,150 @@
import { app, Menu, Tray, BaseWindow, BrowserWindow } from 'electron'
import Constants from './utils/Constants.ts'
const electron = require("electron");
// defaults
// const width = 800;
// const height = 500;
// const DEFAULT_MARGIN = {x: 0, y: 0} ;
let tray;
let trayOptions;
const DEFAULT_OPTIONS = {
menu: false,
tooltip: 'Vutron App',
margin: {x:0, y:0},
width: Constants.IS_DEV_ENV ? 1500 : 1200,
height: 650,
}
export function createTray(window: BaseWindow, options) {
trayOptions = options || DEFAULT_OPTIONS;
tray = new Tray('buildAssets/icons/icon16.png');
tray.on('double-click', function (event) {
toggleWindow(window)
});
tray.on('right-click', function (event) {
toggleWindow(window)
});
tray.on('click', function (event) {
toggleWindow(window)
});
tray.setToolTip(trayOptions.tooltip);
if (trayOptions.menu) {
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show App',
click: () => {
showWindow(window)
}
},
{
label: 'Hide App',
click: () => {
window.hide()
}
},
{
label: 'Exit',
click: () => {
app.quit()
}
}
])
// tray icon only with classic window
tray.setContextMenu(contextMenu)
} else {
// no menu for tray window
window.setMenu(null)
tray.setContextMenu(null)
}
// align at startup
alignWindow(window)
return tray
}
export function setWindowAutoHide(window: BrowserWindow) {
window.hide();
window.on("blur", () => {
// dont close if devtools
if (!window.webContents.isDevToolsOpened()) {
window.hide();
// ipcMain.emit("tray-window-hidden", { window: window, tray: tray });
}
});
}
export function toggleWindow(window: BaseWindow) {
if (window.isVisible()) {
window.hide();
// ipcMain.emit("tray-window-hidden", { window: window, tray: tray });
return;
}
showWindow(window);
// ipcMain.emit("tray-window-visible", { window: window, tray: tray });
}
export function showWindow(window: BaseWindow) {
window.show()
alignWindow(window)
}
export function alignWindow(window: BaseWindow) {
const position = calculateWindowPosition();
const b = window.getBounds()
window.setBounds({
width: b.width,
height: b.height,
x: position.x,
y: position.y
});
}
function calculateWindowPosition() {
const margin = trayOptions.margin;
const b = trayOptions
const screenBounds = electron.screen.getPrimaryDisplay().size;
const trayBounds = tray.getBounds();
// where is the icon on the screen?
let trayPos = 4; // 1:top-left 2:top-right 3:bottom-left 4.bottom-right
trayPos = trayBounds.y > screenBounds.height / 2 ? trayPos : trayPos / 2;
trayPos = trayBounds.x > screenBounds.width / 2 ? trayPos : trayPos - 1;
let x = 0;
let y = 0 ;
// calculate the new window position
switch (trayPos) {
case 1: // for TOP - LEFT
x = Math.floor(trayBounds.x + margin.x + trayBounds.width / 2);
y = Math.floor(trayBounds.y + margin.y + trayBounds.height / 2);
break;
case 2: // for TOP - RIGHT
x = Math.floor(
trayBounds.x - b.width - margin.x + trayBounds.width / 2
);
y = Math.floor(trayBounds.y + margin.y + trayBounds.height / 2);
break;
case 3: // for BOTTOM - LEFT
x = Math.floor(trayBounds.x + margin.x + trayBounds.width / 2);
y = Math.floor(
trayBounds.y - b.height - margin.y + trayBounds.height / 2
);
break;
case 4: // for BOTTOM - RIGHT
x = Math.floor(
trayBounds.x - b.width - margin.x + trayBounds.width / 2
);
y = Math.floor(
trayBounds.y - b.height - margin.y + trayBounds.height / 2
);
break;
}
return { x, y };
}