From 0bf3c910b86f22e986dba47b842d8f2726498b19 Mon Sep 17 00:00:00 2001 From: LudoO Date: Tue, 4 Feb 2025 14:58:01 +0100 Subject: [PATCH 1/9] feat: add systray --- buildAssets/icons/icon16.png | Bin 0 -> 1108 bytes src/main/MainRunner.ts | 30 +++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 buildAssets/icons/icon16.png diff --git a/buildAssets/icons/icon16.png b/buildAssets/icons/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..ae51b5126421e9f0f48814acdd77d0c0e8edb899 GIT binary patch literal 1108 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|T2doC(|mmy zw18|523AHP24;{FAY@>aVqgWc85q16rQz%#Mh&PMCI*J~Oa>OHnkXO*0v4nJa0`PlBg3pY5xV%QuQiw3qZOUY$~jP%-qzHM1_jnoV;SI3R@+x3M(KRB&@Hb09I0xZL1XF8=&Bv zUzDm~re~mMpk&9TprBw=l#*r@P?Wt5Z@Sn2DRmzV368|&p4rRy77T3YHG z80i}s=>k>g7FXt#Bv$C=6)QswftllyTAW;zSx}OhpQivaH!&%{w8U0P31kr*K-^i9 znTD__uNdkrpa=CqGWv#k2KsQbfm&@qqE`MznW;dVLFU^T+JIG}h(YbK(Fa+MHfYh=pKjkZpHxpupVUALAyuD(bk1F^h$jndxOD zPRv-Cq&#Ws){F8Rr6N3B>YJy9NgZ)3&^6Q4*}UIL;7A0A*C)Go?Zxjtw+YN=p6rwM z?2Ki(+M;@!d8b0Y&)Mu+w#(zw_xo$#y~_xH(*ImOZoksDzq|S63(tFhF3ptses1Nn zseYPEy?g`Ds94&oX?Co+{Br3wf$EiCw7s7kQIwTE`QV(aQoB^u1@0at(^CRp89fV=8-j<*jKy``|SJiY5C0^_dRF*mQ|j5tt`|heS5pPiB!w- z^e46R*NC5SaQ(jA==7XDOP;S#7Q5@RuuX2#zC#7ReE0aSd^uN;wRuwcM2$)_!#I2X&elG@kGW%GQBgs{>kyUe zx1Q8Ta=Pz1Sy%M>B#%TwB;%SOK{aFNJFPdaviz5~p74+>(Pf6k#@F2+Jj3SiZ&lsC z?!Dx`-&LPQf4AhH^*-XB8m(2)-g|mCi+bNruRmqm>#AMWiYf@Ivx{2y?mNrXyeDhf zExpeL-)}VAGfxUAEdF-ru%NPdcE{peO$V!01XM7c<{q&X7CyFLWF4ia>!|&hr12=WS|8WL-5Sm;VRzO@2w0%1(j% PpseNT>gTe~DWM4fm!pNO literal 0 HcmV?d00001 diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 2055ef0..1ccc8ee 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow, RenderProcessGoneDetails } from 'electron' +import { app, BrowserWindow, Menu, RenderProcessGoneDetails, Tray } from 'electron' import Constants from './utils/Constants' import IPCs from './IPCs' @@ -49,6 +49,8 @@ export const createMainWindow = async (mainWindow: BrowserWindow): Promise { + mainWindow.show(); + } + }, + { + label: 'Hide App', + click: () => { + mainWindow.hide(); + } + }, + { + label: 'Exit', + click: () => { + app.quit(); + } + } + ]); + tray.setToolTip('Vutron App'); + tray.setContextMenu(contextMenu); +} From fa1d20df26de5431dd5a30e2ba3d167be7994dfe Mon Sep 17 00:00:00 2001 From: LudoO Date: Tue, 4 Feb 2025 15:12:30 +0100 Subject: [PATCH 2/9] feat: double click on icon will open window --- src/main/MainRunner.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 1ccc8ee..98fffc7 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -117,6 +117,9 @@ function createTray(mainWindow) { } } ]); + tray.on('double-click', function (event) { + mainWindow.show(); + }); tray.setToolTip('Vutron App'); tray.setContextMenu(contextMenu); } From 3a7a91e18745d7d2a1861493411b459f2410e5b1 Mon Sep 17 00:00:00 2001 From: LudoO Date: Tue, 4 Feb 2025 16:31:24 +0100 Subject: [PATCH 3/9] feat: add tray window (based on electron-tray-window) --- src/main/MainRunner.ts | 101 +++++++++++++++------------ src/main/tray.ts | 150 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 44 deletions(-) create mode 100644 src/main/tray.ts diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 98fffc7..803b03d 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -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 => { - mainWindow = new BrowserWindow({ +export const createMainWindow = async (): Promise => { + 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 { - 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 { - 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); -} diff --git a/src/main/tray.ts b/src/main/tray.ts new file mode 100644 index 0000000..6b6d3b8 --- /dev/null +++ b/src/main/tray.ts @@ -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 }; +} From 8ac82588c7eaf11e0c9012b4cb7c24d5a12d5f7e Mon Sep 17 00:00:00 2001 From: LudoO Date: Wed, 5 Feb 2025 11:05:33 +0100 Subject: [PATCH 4/9] feat: center tray window --- package-lock.json | 35 ++++++++++++++++---- src/main/MainRunner.ts | 9 +++-- src/main/desktop.ts | 17 ++++++++++ src/main/tray.ts | 65 +++++++++++++------------------------ src/main/utils/Constants.ts | 3 ++ 5 files changed, 78 insertions(+), 51 deletions(-) create mode 100644 src/main/desktop.ts diff --git a/package-lock.json b/package-lock.json index 193961a..e1da818 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2349,6 +2349,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.16.1", @@ -2382,6 +2383,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/types": "7.16.1", @@ -2410,6 +2412,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1" @@ -2427,6 +2430,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "7.16.1", "@typescript-eslint/utils": "7.16.1", @@ -2454,6 +2458,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -2467,6 +2472,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", @@ -2495,6 +2501,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.16.1", @@ -2517,6 +2524,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" @@ -3216,6 +3224,7 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3461,6 +3470,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -4573,6 +4583,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -6118,16 +6129,17 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -6138,6 +6150,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -6220,6 +6233,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6689,6 +6703,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -7332,6 +7347,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -8200,6 +8216,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -8209,6 +8226,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -9122,6 +9140,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10003,6 +10022,7 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10508,6 +10528,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -10536,9 +10557,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "license": "MIT", "engines": { diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 803b03d..ea0f600 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -1,7 +1,8 @@ import { app, BrowserWindow, RenderProcessGoneDetails, BrowserWindowConstructorOptions } from 'electron' import Constants from './utils/Constants' import IPCs from './IPCs' -import { createTray, setWindowAutoHide, showWindow } from './tray.ts' +import { createTray, setWindowAutoHide } from './tray.ts' +import { moveToCurrentDesktop } from './desktop.ts' const options = { tray: true, @@ -45,10 +46,12 @@ export const createMainWindow = async (): Promise => { show: false, frame: false, fullscreenable: false, + hiddenInMissionControl: true, resizable: false, transparent: true, alwaysOnTop: true, webPreferences: { + ...Constants.DEFAULT_WEB_PREFERENCES, backgroundThrottling: false } } @@ -63,7 +66,7 @@ export const createMainWindow = async (): Promise => { }) mainWindow.webContents.on('did-frame-finish-load', (): void => { - if (Constants.IS_DEV_ENV) { + if (Constants.IS_DEV_ENV && Constants.IS_DEVTOOLS) { mainWindow.webContents.openDevTools() } }) @@ -81,6 +84,8 @@ export const createMainWindow = async (): Promise => { mainWindow.show() mainWindow.focus() mainWindow.setAlwaysOnTop(false) + + // moveToCurrentDesktop(mainWindow) }) } diff --git a/src/main/desktop.ts b/src/main/desktop.ts new file mode 100644 index 0000000..f23b00f --- /dev/null +++ b/src/main/desktop.ts @@ -0,0 +1,17 @@ +import { screen } from 'electron' + +// To detect proper desktop/workspace, find the display where the mouse cursor is +export function getDisplayNearestPoint(){ + return screen.getDisplayNearestPoint(screen.getCursorScreenPoint()); +} + +export function moveToCurrentDesktop(mainWindow){ + const currentDisplay = getDisplayNearestPoint(); +// Center window relatively to that display + const centerX = Math.round((currentDisplay.workArea.width - mainWindow.getBounds().width) / 2); + const centerY = Math.round((currentDisplay.workArea.height - mainWindow.getBounds().height) / 2); + mainWindow.setPosition(currentDisplay.workArea.x + centerX, currentDisplay.workArea.y + centerY); +} + + + diff --git a/src/main/tray.ts b/src/main/tray.ts index 6b6d3b8..4209031 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -1,6 +1,6 @@ -import { app, Menu, Tray, BaseWindow, BrowserWindow } from 'electron' +import { app, screen, Menu, Tray, BaseWindow, BrowserWindow } from 'electron' import Constants from './utils/Constants.ts' -const electron = require("electron"); +import { getDisplayNearestPoint } from './desktop.ts' // defaults // const width = 800; @@ -103,48 +103,29 @@ export function alignWindow(window: BaseWindow) { } function calculateWindowPosition() { - const margin = trayOptions.margin; + // To detect proper desktop/workspace, find the display where the mouse cursor is + const currentDisplay = getDisplayNearestPoint(); + console.log("currentDisplay.workArea=", currentDisplay.workArea); + + const margin = { + x: trayOptions.margin.x, // + currentDisplay.workArea.width, + y: trayOptions.margin.y // + currentDisplay.workArea.height + }; const b = trayOptions - const screenBounds = electron.screen.getPrimaryDisplay().size; + const screenBounds = 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 ; + const bottom = trayBounds.y > screenBounds.height / 2 ; + const x = Math.floor(trayBounds.x - b.width/2 - margin.x + trayBounds.width / 2); + const y = bottom ? + Math.floor(trayBounds.y - b.height - margin.y + trayBounds.height / 2) + : + Math.floor(trayBounds.y + margin.y + trayBounds.height / 2) + ; - // 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 }; + // constraint into screen + return { + x: Math.max(0, Math.min(screenBounds.width - b.width, x)), + y: Math.max(0, Math.min(screenBounds.height - b.height, y)) + }; } diff --git a/src/main/utils/Constants.ts b/src/main/utils/Constants.ts index 2a541ad..a97fbc7 100644 --- a/src/main/utils/Constants.ts +++ b/src/main/utils/Constants.ts @@ -12,6 +12,9 @@ export default class Constants { static IS_DEV_ENV = process.env.NODE_ENV === 'development' + // required IS_DEV_ENV + static IS_DEVTOOLS = true + static IS_MAC = process.platform === 'darwin' static DEFAULT_WEB_PREFERENCES = { From bb0812349b6bea8220408cf87b770089ec625458 Mon Sep 17 00:00:00 2001 From: LudoO Date: Sun, 16 Feb 2025 12:47:04 +0100 Subject: [PATCH 5/9] feat: review options tray and trayWindow --- src/main/MainRunner.ts | 16 ++++++++-------- src/main/index.ts | 4 ++-- src/main/tray.ts | 16 +++++++--------- src/main/utils/Constants.ts | 3 ++- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index ea0f600..945ec18 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -1,8 +1,7 @@ import { app, BrowserWindow, RenderProcessGoneDetails, BrowserWindowConstructorOptions } from 'electron' import Constants from './utils/Constants' import IPCs from './IPCs' -import { createTray, setWindowAutoHide } from './tray.ts' -import { moveToCurrentDesktop } from './desktop.ts' +import { createTray, setWindowAutoHide, showWindow } from './tray.ts' const options = { tray: true, @@ -13,8 +12,9 @@ const options = { menu: false, tooltip: 'Vutron App', margin: {x:0, y:0}, - width: Constants.IS_DEV_ENV ? 1500 : 1200, + width: Constants.IS_DEV_ENV ? 800 : 600, height: 650, + showAtStartup: false } } @@ -34,7 +34,7 @@ export const createMainWindow = async (): Promise => { height: options.height, useContentSize: true, webPreferences: Constants.DEFAULT_WEB_PREFERENCES, - frame: !options.trayWindow, + frame: true } if (options.trayWindow){ opt = { @@ -72,20 +72,20 @@ export const createMainWindow = async (): Promise => { }) if (options.tray) { - createTray(mainWindow, options.trayOptions); + createTray(mainWindow, options.trayWindow, options.trayOptions); } if (options.trayWindow) { setWindowAutoHide(mainWindow); - // showWindow(mainWindow) + if (options.trayOptions?.showAtStartup){ + showWindow(mainWindow) + } }else{ mainWindow.once('ready-to-show', (): void => { mainWindow.setAlwaysOnTop(true) mainWindow.show() mainWindow.focus() mainWindow.setAlwaysOnTop(false) - - // moveToCurrentDesktop(mainWindow) }) } diff --git a/src/main/index.ts b/src/main/index.ts index 8dc301c..b3a1666 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -18,12 +18,12 @@ app.on('ready', async () => { } */ - mainWindow = await createMainWindow(mainWindow) + mainWindow = await createMainWindow() }) app.on('activate', async () => { if (!mainWindow) { - mainWindow = await createMainWindow(mainWindow) + mainWindow = await createMainWindow() } }) diff --git a/src/main/tray.ts b/src/main/tray.ts index 4209031..7033a85 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -2,11 +2,6 @@ import { app, screen, Menu, Tray, BaseWindow, BrowserWindow } from 'electron' import Constants from './utils/Constants.ts' import { getDisplayNearestPoint } from './desktop.ts' -// defaults -// const width = 800; -// const height = 500; -// const DEFAULT_MARGIN = {x: 0, y: 0} ; - let tray; let trayOptions; const DEFAULT_OPTIONS = { @@ -17,13 +12,14 @@ const DEFAULT_OPTIONS = { height: 650, } -export function createTray(window: BaseWindow, options) { +export function createTray(window: BaseWindow, trayWindow: boolean, options) { trayOptions = options || DEFAULT_OPTIONS; + trayOptions.trayWindow=trayWindow; tray = new Tray('buildAssets/icons/icon16.png'); - tray.on('double-click', function (event) { - toggleWindow(window) - }); + // tray.on('double-click', function (event) { + // toggleWindow(window) + // }); tray.on('right-click', function (event) { toggleWindow(window) }); @@ -92,6 +88,8 @@ export function showWindow(window: BaseWindow) { } export function alignWindow(window: BaseWindow) { + if (!trayOptions.trayWindow) return; + const position = calculateWindowPosition(); const b = window.getBounds() window.setBounds({ diff --git a/src/main/utils/Constants.ts b/src/main/utils/Constants.ts index a97fbc7..5b19818 100644 --- a/src/main/utils/Constants.ts +++ b/src/main/utils/Constants.ts @@ -12,7 +12,8 @@ export default class Constants { static IS_DEV_ENV = process.env.NODE_ENV === 'development' - // required IS_DEV_ENV + // To show devtools at startup. It requires IS_DEV_ENV=true. + // Note: For debugging purpose, window won't be closed if click elsewhere, if devtools is open. static IS_DEVTOOLS = true static IS_MAC = process.platform === 'darwin' From 7d9036f2f8be93fa95478bdde9b26dc06f5e8728 Mon Sep 17 00:00:00 2001 From: LudoO Date: Sun, 16 Feb 2025 12:49:01 +0100 Subject: [PATCH 6/9] fix: remove console.log for currentDisplay --- src/main/tray.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/tray.ts b/src/main/tray.ts index 7033a85..b035865 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -101,9 +101,9 @@ export function alignWindow(window: BaseWindow) { } function calculateWindowPosition() { - // To detect proper desktop/workspace, find the display where the mouse cursor is - const currentDisplay = getDisplayNearestPoint(); - console.log("currentDisplay.workArea=", currentDisplay.workArea); + // // To detect proper desktop/workspace, find the display where the mouse cursor is + // const currentDisplay = getDisplayNearestPoint(); + // console.log("currentDisplay.workArea=", currentDisplay.workArea); const margin = { x: trayOptions.margin.x, // + currentDisplay.workArea.width, From ecaeb7aa54800767ff1dc1f5e49af5db380e0aec Mon Sep 17 00:00:00 2001 From: LudoO Date: Sun, 16 Feb 2025 12:52:38 +0100 Subject: [PATCH 7/9] feat: no trayWindow by default --- src/main/MainRunner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 945ec18..8477c5b 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -5,7 +5,7 @@ import { createTray, setWindowAutoHide, showWindow } from './tray.ts' const options = { tray: true, - trayWindow: true, + trayWindow: false, // true, to use a tray floating window attached to top try icon width: Constants.IS_DEV_ENV ? 1500 : 1200, height: 650, trayOptions: { From 1fc3ffa6935339b49c9ec8cd4264af6d954ff72b Mon Sep 17 00:00:00 2001 From: LudoO Date: Sun, 23 Feb 2025 15:21:51 +0100 Subject: [PATCH 8/9] feat: review tray options --- src/main/MainRunner.ts | 46 +++++++++++++++-------------- src/main/desktop.ts | 17 ----------- src/main/tray.ts | 58 ++++++++++++++----------------------- src/main/utils/Constants.ts | 20 +++++++++++++ 4 files changed, 67 insertions(+), 74 deletions(-) delete mode 100644 src/main/desktop.ts diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 8477c5b..3667661 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -1,20 +1,15 @@ import { app, BrowserWindow, RenderProcessGoneDetails, BrowserWindowConstructorOptions } from 'electron' -import Constants from './utils/Constants' +import Constants, { TrayOptions } from './utils/Constants' import IPCs from './IPCs' -import { createTray, setWindowAutoHide, showWindow } from './tray.ts' +import { createTray, hideWindow, showWindow } from './tray.ts' const options = { - tray: true, - trayWindow: false, // true, to use a tray floating window attached to top try icon 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 ? 800 : 600, - height: 650, - showAtStartup: false + tray: { + // all optional values from DEFAULT_TRAY_OPTIONS can de defined here + enabled: true, + trayWindow: false // true, to use a tray floating window attached to top try icon } } @@ -36,13 +31,22 @@ export const createMainWindow = async (): Promise => { webPreferences: Constants.DEFAULT_WEB_PREFERENCES, frame: true } - if (options.trayWindow){ + const trayOptions: TrayOptions = (options.tray?.enabled) ? { + ...Constants.DEFAULT_TRAY_OPTIONS, + ...options.tray + }: { + ...Constants.DEFAULT_TRAY_OPTIONS, + enabled: false + } + + // trayWindow requires tray.enabled=true + if (trayOptions.enabled && trayOptions.trayWindow){ opt = { ...opt, - width: options.trayOptions.width , - height: options.trayOptions.height, - maxWidth: options.trayOptions.width, - maxHeight: options.trayOptions.height, + width: options.width , + height: options.height, + maxWidth: options.width, + maxHeight: options.height, show: false, frame: false, fullscreenable: false, @@ -71,13 +75,13 @@ export const createMainWindow = async (): Promise => { } }) - if (options.tray) { - createTray(mainWindow, options.trayWindow, options.trayOptions); + if (trayOptions.enabled) { + createTray(mainWindow, trayOptions); } - if (options.trayWindow) { - setWindowAutoHide(mainWindow); - if (options.trayOptions?.showAtStartup){ + if (trayOptions.enabled && trayOptions.trayWindow) { + hideWindow(mainWindow); + if (trayOptions.showAtStartup){ showWindow(mainWindow) } }else{ diff --git a/src/main/desktop.ts b/src/main/desktop.ts deleted file mode 100644 index f23b00f..0000000 --- a/src/main/desktop.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { screen } from 'electron' - -// To detect proper desktop/workspace, find the display where the mouse cursor is -export function getDisplayNearestPoint(){ - return screen.getDisplayNearestPoint(screen.getCursorScreenPoint()); -} - -export function moveToCurrentDesktop(mainWindow){ - const currentDisplay = getDisplayNearestPoint(); -// Center window relatively to that display - const centerX = Math.round((currentDisplay.workArea.width - mainWindow.getBounds().width) / 2); - const centerY = Math.round((currentDisplay.workArea.height - mainWindow.getBounds().height) / 2); - mainWindow.setPosition(currentDisplay.workArea.x + centerX, currentDisplay.workArea.y + centerY); -} - - - diff --git a/src/main/tray.ts b/src/main/tray.ts index b035865..b483565 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -1,29 +1,23 @@ -import { app, screen, Menu, Tray, BaseWindow, BrowserWindow } from 'electron' +import { app, screen, Menu, Tray, BrowserWindow } from 'electron' import Constants from './utils/Constants.ts' -import { getDisplayNearestPoint } from './desktop.ts' - 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, trayWindow: boolean, options) { - trayOptions = options || DEFAULT_OPTIONS; - trayOptions.trayWindow=trayWindow; +export function createTray(window: BrowserWindow, options) { + trayOptions = options || Constants.DEFAULT_TRAY_OPTIONS; + tray = new Tray('buildAssets/icons/icon16.png'); - // tray.on('double-click', function (event) { - // toggleWindow(window) - // }); + tray.on('double-click', function (event) { + console.log('double-click') + toggleWindow(window) + }); tray.on('right-click', function (event) { + console.log('right-click') toggleWindow(window) }); tray.on('click', function (event) { + console.log('click') toggleWindow(window) }); tray.setToolTip(trayOptions.tooltip); @@ -60,34 +54,33 @@ export function createTray(window: BaseWindow, trayWindow: boolean, options) { return tray } -export function setWindowAutoHide(window: BrowserWindow) { +export function hideWindow(window: BrowserWindow) { + console.log('hide window'); 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) { +export function toggleWindow(window: BrowserWindow) { if (window.isVisible()) { - window.hide(); - // ipcMain.emit("tray-window-hidden", { window: window, tray: tray }); - return; + hideWindow(window); + }else{ + showWindow(window); } - - showWindow(window); - // ipcMain.emit("tray-window-visible", { window: window, tray: tray }); } -export function showWindow(window: BaseWindow) { +export function showWindow(window: BrowserWindow) { + console.log('show window'); window.show() + alignWindow(window) } -export function alignWindow(window: BaseWindow) { +export function alignWindow(window: BrowserWindow) { if (!trayOptions.trayWindow) return; const position = calculateWindowPosition(); @@ -101,15 +94,8 @@ export function alignWindow(window: BaseWindow) { } function calculateWindowPosition() { - // // To detect proper desktop/workspace, find the display where the mouse cursor is - // const currentDisplay = getDisplayNearestPoint(); - // console.log("currentDisplay.workArea=", currentDisplay.workArea); - - const margin = { - x: trayOptions.margin.x, // + currentDisplay.workArea.width, - y: trayOptions.margin.y // + currentDisplay.workArea.height - }; - const b = trayOptions + const margin = trayOptions.margin; + const b = trayOptions; const screenBounds = screen.getPrimaryDisplay().size; const trayBounds = tray.getBounds(); diff --git a/src/main/utils/Constants.ts b/src/main/utils/Constants.ts index 5b19818..43f029f 100644 --- a/src/main/utils/Constants.ts +++ b/src/main/utils/Constants.ts @@ -4,6 +4,15 @@ import { fileURLToPath } from 'url' const __dirname = dirname(fileURLToPath(import.meta.url)) +export interface TrayOptions { + enabled: boolean, + trayWindow: boolean, + menu: boolean, + tooltip: string, + margin: {x: number, y: number}, + showAtStartup: boolean +} + export default class Constants { // Display app name (uppercase first letter) static APP_NAME = name.charAt(0).toUpperCase() + name.slice(1) @@ -25,6 +34,17 @@ export default class Constants { preload: join(__dirname, '../preload/index.js') } + static DEFAULT_TRAY_OPTIONS : TrayOptions = { + enabled: false, + trayWindow: false, + menu: false, + tooltip: 'Vutron App', + margin: {x:0, y:0}, + showAtStartup: false + } + static APP_INDEX_URL_DEV = `${debug.env.VITE_DEV_SERVER_URL}/index.html` static APP_INDEX_URL_PROD = join(__dirname, '../index.html') } + + From 22c3baa4a8074068085fcd309e579004a85e272b Mon Sep 17 00:00:00 2001 From: LudoO Date: Tue, 25 Feb 2025 23:18:17 +0100 Subject: [PATCH 9/9] feat: review tray options --- src/main/MainRunner.ts | 1 + src/main/tray.ts | 40 ++++++++++++++++++---------------------- src/main/utils/Util.ts | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 src/main/utils/Util.ts diff --git a/src/main/MainRunner.ts b/src/main/MainRunner.ts index 3667661..49f1334 100644 --- a/src/main/MainRunner.ts +++ b/src/main/MainRunner.ts @@ -9,6 +9,7 @@ const options = { tray: { // all optional values from DEFAULT_TRAY_OPTIONS can de defined here enabled: true, + menu: false, // true, to use a tray menu ; false to toggle visibility on click on tray icon trayWindow: false // true, to use a tray floating window attached to top try icon } } diff --git a/src/main/tray.ts b/src/main/tray.ts index b483565..f416218 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -1,25 +1,17 @@ import { app, screen, Menu, Tray, BrowserWindow } from 'electron' import Constants from './utils/Constants.ts' -let tray; +import { debounce } from './utils/Util.ts' +let tray let trayOptions; export function createTray(window: BrowserWindow, options) { trayOptions = options || Constants.DEFAULT_TRAY_OPTIONS; + // menu or trayWindow, you need to choose + if (trayOptions.trayWindow){ + trayOptions.menu = false + } tray = new Tray('buildAssets/icons/icon16.png'); - - tray.on('double-click', function (event) { - console.log('double-click') - toggleWindow(window) - }); - tray.on('right-click', function (event) { - console.log('right-click') - toggleWindow(window) - }); - tray.on('click', function (event) { - console.log('click') - toggleWindow(window) - }); tray.setToolTip(trayOptions.tooltip); if (trayOptions.menu) { const contextMenu = Menu.buildFromTemplate([ @@ -32,7 +24,7 @@ export function createTray(window: BrowserWindow, options) { { label: 'Hide App', click: () => { - window.hide() + hideWindow(window) } }, { @@ -45,6 +37,13 @@ export function createTray(window: BrowserWindow, options) { // tray icon only with classic window tray.setContextMenu(contextMenu) } else { + // handle click on tray icon + tray.on('right-click', function (event) { + debounce(() => toggleWindow(window)); + }); + tray.on('click', function (event) { + debounce(() => toggleWindow(window)); + }); // no menu for tray window window.setMenu(null) tray.setContextMenu(null) @@ -55,8 +54,9 @@ export function createTray(window: BrowserWindow, options) { } export function hideWindow(window: BrowserWindow) { - console.log('hide window'); window.hide(); + // if (!trayOptions.trayWindow) return; + // hide window when click elsewhere on screen window.on("blur", () => { // dont close if devtools if (!window.webContents.isDevToolsOpened()) { @@ -74,17 +74,15 @@ export function toggleWindow(window: BrowserWindow) { } export function showWindow(window: BrowserWindow) { - console.log('show window'); window.show() - alignWindow(window) } export function alignWindow(window: BrowserWindow) { if (!trayOptions.trayWindow) return; - const position = calculateWindowPosition(); const b = window.getBounds() + const position = calculateWindowPosition(b); window.setBounds({ width: b.width, height: b.height, @@ -93,10 +91,8 @@ export function alignWindow(window: BrowserWindow) { }); } -function calculateWindowPosition() { +function calculateWindowPosition(b) { const margin = trayOptions.margin; - const b = trayOptions; - const screenBounds = screen.getPrimaryDisplay().size; const trayBounds = tray.getBounds(); const bottom = trayBounds.y > screenBounds.height / 2 ; diff --git a/src/main/utils/Util.ts b/src/main/utils/Util.ts new file mode 100644 index 0000000..3cb030e --- /dev/null +++ b/src/main/utils/Util.ts @@ -0,0 +1,14 @@ + +export function debounce(func, timeout = 200){ + let timer; + return function(...args) { + if (!timer) { + func.apply(this, args); + } + clearTimeout(timer); + timer = setTimeout(() => { + timer = undefined; + }, timeout); + }(); +} +