tray.ts
1 import { app, screen, session, Menu, Tray, BrowserWindow } from 'electron' 2 import Constants from './utils/Constants.ts' 3 import { debounce } from './utils/Util.ts' 4 let tray 5 let trayOptions 6 7 export function createTray(window: BrowserWindow, options) { 8 trayOptions = options || Constants.DEFAULT_TRAY_OPTIONS 9 // menu or trayWindow, you need to choose 10 if (trayOptions.trayWindow) { 11 trayOptions.menu = false 12 } 13 14 tray = new Tray(Constants.ASSETS_PATH.icon) 15 tray.setToolTip(trayOptions.tooltip) 16 if (trayOptions.menu) { 17 tray.on('click', function (_event) { 18 debounce(() => toggleWindow(window), 100) 19 }) 20 const contextMenu = Menu.buildFromTemplate([ 21 { 22 label: 'Open Dev Tools', 23 click: () => { 24 window.webContents.openDevTools() 25 } 26 }, 27 { 28 label: 'Force Reload', 29 click: () => { 30 window.webContents.reloadIgnoringCache() 31 } 32 }, 33 { 34 label: 'Clear Storage', 35 click: () => { 36 const sess = session.fromPartition(Constants.PARTITION_NAME) 37 sess.clearStorageData({ 38 storages: ['cookies', 'cachestorage', 'localstorage', 'indexdb', 'serviceworkers'] 39 }) 40 window.webContents.reloadIgnoringCache() 41 } 42 }, 43 { 44 label: 'Exit', 45 click: () => { 46 app.quit() 47 } 48 } 49 ]) 50 // tray icon only with classic window 51 tray.setContextMenu(contextMenu) 52 } else { 53 // handle click on tray icon 54 tray.on('right-click', function (_event) { 55 debounce(() => toggleWindow(window)) 56 }) 57 tray.on('click', function (_event) { 58 debounce(() => toggleWindow(window)) 59 }) 60 // no menu for tray window 61 // window.setMenu(null) 62 // tray.setContextMenu(null) 63 } 64 // align at startup 65 alignWindow(window) 66 return tray 67 } 68 69 export function hideWindow(window: BrowserWindow) { 70 window.hide() 71 // if (!trayOptions.trayWindow) return; 72 // hide window when click elsewhere on screen 73 // window.on('blur', () => { 74 // // dont close if devtools 75 // if (!window.webContents.isDevToolsOpened()) { 76 // window.hide() 77 // } 78 // }) 79 } 80 81 export function toggleWindow(window: BrowserWindow) { 82 if (window.isVisible()) { 83 hideWindow(window) 84 } else { 85 showWindow(window) 86 } 87 } 88 89 export function showWindow(window: BrowserWindow) { 90 window.show() 91 alignWindow(window) 92 } 93 94 export function alignWindow(window: BrowserWindow) { 95 if (!trayOptions.trayWindow) return 96 97 const b = window.getBounds() 98 const position = calculateWindowPosition(b) 99 window.setBounds({ 100 width: b.width, 101 height: b.height, 102 x: position.x, 103 y: position.y 104 }) 105 } 106 107 function calculateWindowPosition(b) { 108 const margin = trayOptions.margin 109 const screenBounds = screen.getPrimaryDisplay().size 110 const trayBounds = tray.getBounds() 111 const bottom = trayBounds.y > screenBounds.height / 2 112 const x = Math.floor(trayBounds.x - b.width / 2 - margin.x + trayBounds.width / 2) 113 const y = bottom 114 ? Math.floor(trayBounds.y - b.height - margin.y + trayBounds.height / 2) 115 : Math.floor(trayBounds.y + margin.y + trayBounds.height / 2) 116 // constraint into screen 117 return { 118 x: Math.max(0, Math.min(screenBounds.width - b.width, x)), 119 y: Math.max(0, Math.min(screenBounds.height - b.height, y)) 120 } 121 }