1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Improve tray initialization and logging (#2048)

- Remove all async click handlers as the typing of the expected method
  is that of `void` so it doesn't know how to handle `Promise<void>`

- Replace the above with promise chains with correctly handle any errors
  by logging them

- Fix the tray menu update logic to actually produce a new menu when the
  reaction is run

- Improve the Clusters submenu generation to involve less work and to
  utilize the built-in checkmark rendering

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-03-30 10:14:19 -04:00 committed by GitHub
parent 503a49261e
commit 0e307e65b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,6 @@
import path from "path"; import path from "path";
import packageInfo from "../../package.json"; import packageInfo from "../../package.json";
import { Menu, NativeImage, Tray } from "electron"; import { Menu, Tray } from "electron";
import { autorun } from "mobx"; import { autorun } from "mobx";
import { showAbout } from "./menu"; import { showAbout } from "./menu";
import { checkForUpdates } from "./app-updater"; import { checkForUpdates } from "./app-updater";
@ -13,6 +13,8 @@ import logger from "./logger";
import { isDevelopment, isWindows } from "../common/vars"; import { isDevelopment, isWindows } from "../common/vars";
import { exitApp } from "./exit-app"; import { exitApp } from "./exit-app";
const TRAY_LOG_PREFIX = "[TRAY]";
// note: instance of Tray should be saved somewhere, otherwise it disappears // note: instance of Tray should be saved somewhere, otherwise it disappears
export let tray: Tray; export let tray: Tray;
@ -25,94 +27,92 @@ export function getTrayIcon(): string {
} }
export function initTray(windowManager: WindowManager) { export function initTray(windowManager: WindowManager) {
const dispose = autorun(() => { const icon = getTrayIcon();
try {
const menu = createTrayMenu(windowManager);
buildTray(getTrayIcon(), menu, windowManager);
} catch (err) {
logger.error(`[TRAY]: building failed: ${err}`);
}
});
return () => {
dispose();
tray?.destroy();
tray = null;
};
}
function buildTray(icon: string | NativeImage, menu: Menu, windowManager: WindowManager) {
if (!tray) {
tray = new Tray(icon); tray = new Tray(icon);
tray.setToolTip(packageInfo.description); tray.setToolTip(packageInfo.description);
tray.setIgnoreDoubleClickEvents(true); tray.setIgnoreDoubleClickEvents(true);
tray.setImage(icon);
tray.setContextMenu(menu);
if (isWindows) { if (isWindows) {
tray.on("click", () => { tray.on("click", () => {
windowManager.ensureMainWindow(); windowManager
.ensureMainWindow()
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to open lens`, { error }));
}); });
} }
}
return tray; const disposers = [
autorun(() => {
try {
const menu = createTrayMenu(windowManager);
tray.setContextMenu(menu);
} catch (error) {
logger.error(`${TRAY_LOG_PREFIX}: building failed`, { error });
}
}),
];
return () => {
disposers.forEach(disposer => disposer());
tray?.destroy();
tray = null;
};
} }
function createTrayMenu(windowManager: WindowManager): Menu { function createTrayMenu(windowManager: WindowManager): Menu {
return Menu.buildFromTemplate([ return Menu.buildFromTemplate([
{ {
label: "Open Lens", label: "Open Lens",
async click() { click() {
await windowManager.ensureMainWindow(); windowManager
.ensureMainWindow()
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to open lens`, { error }));
}, },
}, },
{ {
label: "Preferences", label: "Preferences",
click() { click() {
windowManager.navigate(preferencesURL()); windowManager
.navigate(preferencesURL())
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to nativate to Preferences`, { error }));
}, },
}, },
{ {
label: "Clusters", label: "Clusters",
submenu: workspaceStore.enabledWorkspacesList submenu: workspaceStore.enabledWorkspacesList
.filter(workspace => clusterStore.getByWorkspaceId(workspace.id).length > 0) // hide empty workspaces .map(workspace => [workspace, clusterStore.getByWorkspaceId(workspace.id)] as const)
.map(workspace => { .map(([workspace, clusters]) => ({
const clusters = clusterStore.getByWorkspaceId(workspace.id);
return {
label: workspace.name, label: workspace.name,
toolTip: workspace.description, toolTip: workspace.description,
submenu: clusters.map(cluster => { enabled: clusters.length > 0,
const { id: clusterId, name: label, online, workspace } = cluster; submenu: clusters.map(({ id: clusterId, name: label, online, workspace }) => ({
checked: online,
return { type: "checkbox",
label: `${online ? "✓" : "\x20".repeat(3)/*offset*/}${label}`, label,
toolTip: clusterId, toolTip: clusterId,
async click() { click() {
workspaceStore.setActive(workspace); workspaceStore.setActive(workspace);
windowManager.navigate(clusterViewURL({ params: { clusterId } })); windowManager
.navigate(clusterViewURL({ params: { clusterId } }))
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to nativate to cluster`, { clusterId, error }));
} }
}; }))
}) })),
};
}),
}, },
{ {
label: "Check for updates", label: "Check for updates",
async click() { click() {
await checkForUpdates(); checkForUpdates()
await windowManager.ensureMainWindow(); .then(() => windowManager.ensureMainWindow());
}, },
}, },
{ {
label: "About Lens", label: "About Lens",
async click() { click() {
// note: argument[1] (browserWindow) not available when app is not focused / hidden windowManager.ensureMainWindow()
const browserWindow = await windowManager.ensureMainWindow(); .then(showAbout)
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to show Lens About view`, { error }));
showAbout(browserWindow);
}, },
}, },
{ type: "separator" }, { type: "separator" },