feat: add tray window (based on electron-tray-window)
This commit is contained in:
1 parent
fa1d20df26
commit
3a7a91e187
2 files changed
+207
-44
No files matched your search
+57
-44
@@ -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);
|
||||
}
|
||||
@@ -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 };
|
||||
}
|
||||
Reference in new issue
Block a user