From e6f07cb112b7b42935cd4dba947c86485ee501d3 Mon Sep 17 00:00:00 2001 From: Juho Heikka Date: Wed, 29 Dec 2021 12:56:04 +0200 Subject: [PATCH] Add extension ability to add tray menu items. Signed-off-by: Juho Heikka --- src/extensions/lens-main-extension.ts | 2 ++ src/main/index.ts | 6 ++-- .../menu/electron-menu-items.injectable.ts | 2 +- src/main/tray/tray-items.injectable.ts | 36 +++++++++++++++++++ src/main/{ => tray}/tray.ts | 35 +++++++++++------- 5 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 src/main/tray/tray-items.injectable.ts rename src/main/{ => tray}/tray.ts (78%) diff --git a/src/extensions/lens-main-extension.ts b/src/extensions/lens-main-extension.ts index c0c0a5674a..7c6e393e3b 100644 --- a/src/extensions/lens-main-extension.ts +++ b/src/extensions/lens-main-extension.ts @@ -25,9 +25,11 @@ import { catalogEntityRegistry } from "../main/catalog"; import type { CatalogEntity } from "../common/catalog"; import type { IObservableArray } from "mobx"; import type { MenuRegistration } from "../main/menu/menu-registration"; +import type { MenuItemConstructorOptions } from "electron"; export class LensMainExtension extends LensExtension { appMenus: MenuRegistration[] = []; + trayMenus: MenuItemConstructorOptions[] = []; async navigate(pageId?: string, params?: Record, frameId?: number) { return WindowManager.getInstance().navigateExtension(this.id, pageId, params, frameId); diff --git a/src/main/index.ts b/src/main/index.ts index 1f7b26e773..26e65a8614 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -60,7 +60,7 @@ import { SentryInit } from "../common/sentry"; import { ensureDir } from "fs-extra"; import { Router } from "./router"; import { initMenu } from "./menu/menu"; -import { initTray } from "./tray"; +import { initTray } from "./tray/tray"; import { kubeApiRequest, shellApiRequest, ShellRequestAuthenticator } from "./proxy-functions"; import { AppPaths } from "../common/app-paths"; import { ShellSession } from "./shell-session/shell-session"; @@ -68,6 +68,7 @@ import { getDi } from "./getDi"; import electronMenuItemsInjectable from "./menu/electron-menu-items.injectable"; import extensionLoaderInjectable from "../extensions/extension-loader/extension-loader.injectable"; import lensProtocolRouterMainInjectable from "./protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable"; +import trayItemsInjectable from "./tray/tray-items.injectable"; const di = getDi(); @@ -104,6 +105,7 @@ mangleProxyEnv(); logger.debug("[APP-MAIN] initializing ipc main handlers"); const menuItems = di.inject(electronMenuItemsInjectable); +const trayItems = di.inject(trayItemsInjectable); initializers.initIpcMainHandlers(menuItems); @@ -244,7 +246,7 @@ app.on("ready", async () => { onQuitCleanup.push( initMenu(windowManager, menuItems), - initTray(windowManager), + initTray(windowManager, trayItems), () => ShellSession.cleanup(), ); diff --git a/src/main/menu/electron-menu-items.injectable.ts b/src/main/menu/electron-menu-items.injectable.ts index dd70812d89..df7c88fe39 100644 --- a/src/main/menu/electron-menu-items.injectable.ts +++ b/src/main/menu/electron-menu-items.injectable.ts @@ -29,7 +29,7 @@ const electronMenuItemsInjectable = getInjectable({ const extensions = di.inject(mainExtensionsInjectable); return computed(() => - extensions.get().flatMap((extension) => extension.appMenus), + extensions.get().flatMap((extension) => extension.appMenus.slice()), ); }, }); diff --git a/src/main/tray/tray-items.injectable.ts b/src/main/tray/tray-items.injectable.ts new file mode 100644 index 0000000000..147d610e58 --- /dev/null +++ b/src/main/tray/tray-items.injectable.ts @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { computed } from "mobx"; +import mainExtensionsInjectable from "../../extensions/main-extensions.injectable"; + +const trayItemsInjectable = getInjectable({ + lifecycle: lifecycleEnum.singleton, + + instantiate: (di) => { + const extensions = di.inject(mainExtensionsInjectable); + + return computed(() => + extensions.get().flatMap(extension => extension.trayMenus.slice())); + }, +}); + +export default trayItemsInjectable; diff --git a/src/main/tray.ts b/src/main/tray/tray.ts similarity index 78% rename from src/main/tray.ts rename to src/main/tray/tray.ts index 850d19fe21..50de3a9997 100644 --- a/src/main/tray.ts +++ b/src/main/tray/tray.ts @@ -20,16 +20,17 @@ */ import path from "path"; -import packageInfo from "../../package.json"; +import packageInfo from "../../../package.json"; import { Menu, Tray } from "electron"; -import { autorun } from "mobx"; -import { showAbout } from "./menu/menu"; -import { checkForUpdates, isAutoUpdateEnabled } from "./app-updater"; -import type { WindowManager } from "./window-manager"; -import logger from "./logger"; -import { isDevelopment, isWindows, productName } from "../common/vars"; -import { exitApp } from "./exit-app"; -import { preferencesURL } from "../common/routes"; +import { autorun, IComputedValue } from "mobx"; +import { showAbout } from "../menu/menu"; +import { checkForUpdates, isAutoUpdateEnabled } from "../app-updater"; +import type { WindowManager } from "../window-manager"; +import logger from "../logger"; +import { isDevelopment, isWindows, productName } from "../../common/vars"; +import { exitApp } from "../exit-app"; +import { preferencesURL } from "../../common/routes"; +import type { MenuItemConstructorOptions } from "electron/main"; const TRAY_LOG_PREFIX = "[TRAY]"; @@ -44,7 +45,10 @@ export function getTrayIcon(): string { ); } -export function initTray(windowManager: WindowManager) { +export function initTray( + windowManager: WindowManager, + trayItems: IComputedValue, +) { const icon = getTrayIcon(); tray = new Tray(icon); @@ -62,7 +66,7 @@ export function initTray(windowManager: WindowManager) { const disposers = [ autorun(() => { try { - const menu = createTrayMenu(windowManager); + const menu = createTrayMenu(windowManager, trayItems.get()); tray.setContextMenu(menu); } catch (error) { @@ -78,7 +82,10 @@ export function initTray(windowManager: WindowManager) { }; } -function createTrayMenu(windowManager: WindowManager): Menu { +function createTrayMenu( + windowManager: WindowManager, + extensionTrayItems: MenuItemConstructorOptions[], +): Menu { const template: Electron.MenuItemConstructorOptions[] = [ { label: `Open ${productName}`, @@ -108,6 +115,10 @@ function createTrayMenu(windowManager: WindowManager): Menu { }); } + for (const item of extensionTrayItems) { + template.push(item); + } + return Menu.buildFromTemplate(template.concat([ { label: `About ${productName}`,