diff --git a/src/main/app-updater.ts b/src/main/app-updater.ts index 852bc3161f..66eb09e7d4 100644 --- a/src/main/app-updater.ts +++ b/src/main/app-updater.ts @@ -1,7 +1,7 @@ import { autoUpdater } from "electron-updater" import logger from "./logger" -export default class AppUpdater { +export class AppUpdater { static defaultUpdateIntervalMs = 1000 * 60 * 60 * 24 // once a day static checkForUpdates() { diff --git a/src/main/index.ts b/src/main/index.ts index 5ed8eb24d6..bdcd5c1f44 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -2,13 +2,13 @@ import "../common/system-ca" import "../common/prometheus-providers" -import { app, dialog, Tray } from "electron" +import { app, dialog } from "electron" import { appName } from "../common/vars"; import path from "path" import { LensProxy } from "./lens-proxy" import { WindowManager } from "./window-manager"; import { ClusterManager } from "./cluster-manager"; -import AppUpdater from "./app-updater" +import { AppUpdater } from "./app-updater" import { shellSync } from "./shell-sync" import { getFreePort } from "./port" import { mangleProxyEnv } from "./proxy-env" @@ -28,7 +28,6 @@ if (!process.env.CICD) { let windowManager: WindowManager; let clusterManager: ClusterManager; let proxyServer: LensProxy; -let trayIcon: Tray; mangleProxyEnv() if (app.commandLine.getSwitchValue("proxy-server") !== "") { diff --git a/src/main/tray.ts b/src/main/tray.ts index 11bee0016a..a042e28eaf 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -3,29 +3,30 @@ import sharp from "sharp"; import packageInfo from "../../package.json" import { app, dialog, Menu, nativeImage, Tray } from "electron" import { isDevelopment, isMac } from "../common/vars"; -import { WindowManager } from "./window-manager"; +import { autorun } from "mobx"; import { showAbout } from "./menu"; -import AppUpdater from "./app-updater"; +import { AppUpdater } from "./app-updater"; +import { WindowManager } from "./window-manager"; +import { clusterStore } from "../common/cluster-store"; +import { workspaceStore } from "../common/workspace-store"; import { preferencesURL } from "../renderer/components/+preferences/preferences.route"; +import { clusterViewURL } from "../renderer/components/cluster-manager/cluster-view.route"; +import logger from "./logger"; + +// note: instance of Tray should be saved somewhere, otherwise it disappears +export let tray: Tray; export const trayIcon = isDevelopment ? path.resolve(__static, "../src/renderer/components/icon/logo-lens.svg") : path.resolve(__static, "logo.svg") // electron-builder's extraResources -export async function setupTrayIcon(windowManager: WindowManager) { - await app.whenReady(); - - const iconSize = isMac ? 16 : 32; // todo: verify on windows/linux - const pngIcon = await sharp(trayIcon).png().toBuffer(); - const icon = nativeImage.createFromBuffer(pngIcon).resize({ - width: iconSize, - height: iconSize - }); - - const appTray = new Tray(icon) - appTray.setToolTip(packageInfo.description) - appTray.setIgnoreDoubleClickEvents(true); +export function initTray(windowManager: WindowManager) { + return autorun(() => buildTrayMenu(windowManager), { + delay: 100 + }) +} +export async function buildTrayMenu(windowManager: WindowManager) { // note: browserWindow not available within menuItem.click() as argument[1] when app is not focused / hidden const trayMenu = Menu.buildFromTemplate([ { @@ -42,6 +43,25 @@ export async function setupTrayIcon(windowManager: WindowManager) { windowManager.navigate(preferencesURL()); }, }, + { + label: "Clusters", + submenu: workspaceStore.workspacesList.map(workspace => { + const clusters = clusterStore.getByWorkspaceId(workspace.id); + return { + label: workspace.name, + toolTip: workspace.description, + submenu: clusters.map(({ id: clusterId, contextName: label }) => { + return { + label, + click() { + windowManager.bringToTop(); + windowManager.navigate(clusterViewURL({ params: { clusterId } })); + } + } + }) + } + }), + }, { label: "Check for updates", async click() { @@ -57,6 +77,25 @@ export async function setupTrayIcon(windowManager: WindowManager) { }, ]); - appTray.setContextMenu(trayMenu); - return appTray; + // note: all "await"-s must be defined *AFTER* getting observables for proper mobx reactions + await app.whenReady(); + logger.info('[TRAY]: building tray icon and menu'); + + const iconSize = isMac ? 16 : 32; // todo: verify on windows/linux + const pngIcon = await sharp(trayIcon).png().toBuffer(); + const icon = nativeImage.createFromBuffer(pngIcon).resize({ + width: iconSize, + height: iconSize + }); + + if (tray) { + tray.destroy(); // remove old tray on update + } + + tray = new Tray(icon) + tray.setToolTip(packageInfo.description) + tray.setIgnoreDoubleClickEvents(true); + tray.setContextMenu(trayMenu); + + return tray; } diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index b42c074641..01a4b1d898 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -1,16 +1,15 @@ import type { ClusterId } from "../common/cluster-store"; import { clusterStore } from "../common/cluster-store"; -import { BrowserWindow, dialog, ipcMain, shell, Tray, webContents } from "electron" +import { BrowserWindow, dialog, ipcMain, shell, webContents } from "electron" import windowStateKeeper from "electron-window-state" import { observable } from "mobx"; import { initMenu } from "./menu"; -import { setupTrayIcon } from "./tray"; +import { initTray } from "./tray"; export class WindowManager { public mainView: BrowserWindow; protected splashWindow: BrowserWindow; protected windowState: windowStateKeeper.State; - protected trayIcon: Tray; @observable activeClusterId: ClusterId; @@ -55,7 +54,7 @@ export class WindowManager { async initMenus() { initMenu(this); - this.trayIcon = await setupTrayIcon(this); + initTray(this); } bringToTop() {