mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Respond to PR comments
- Revert changes to structure of electronTrayInjectable - Add some behavioural tests for the tray icon Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
9f3140db77
commit
b7a2bb5385
@ -44,7 +44,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_13"
|
||||
data-testid="close-notification-for-notification_16"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -95,7 +95,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_96"
|
||||
data-testid="close-notification-for-notification_115"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -135,7 +135,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_99"
|
||||
data-testid="close-notification-for-notification_118"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -186,7 +186,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_149"
|
||||
data-testid="close-notification-for-notification_183"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -226,7 +226,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_152"
|
||||
data-testid="close-notification-for-notification_186"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -266,7 +266,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_157"
|
||||
data-testid="close-notification-for-notification_191"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -317,7 +317,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_215"
|
||||
data-testid="close-notification-for-notification_266"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -357,7 +357,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_218"
|
||||
data-testid="close-notification-for-notification_269"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -478,7 +478,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_48"
|
||||
data-testid="close-notification-for-notification_59"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
@ -518,7 +518,7 @@ exports[`installing update using tray when started when user checks for updates
|
||||
>
|
||||
<i
|
||||
class="Icon close material interactive focusable"
|
||||
data-testid="close-notification-for-notification_51"
|
||||
data-testid="close-notification-for-notification_62"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
|
||||
@ -15,12 +15,15 @@ import type { DownloadPlatformUpdate } from "../../main/application-update/downl
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import showApplicationWindowInjectable from "../../main/start-main-application/lens-window/show-application-window.injectable";
|
||||
import progressOfUpdateDownloadInjectable from "../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
||||
import type { TrayIconPaths } from "../../main/tray/tray-icon-path.injectable";
|
||||
import trayIconPathsInjectable from "../../main/tray/tray-icon-path.injectable";
|
||||
|
||||
describe("installing update using tray", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let showApplicationWindowMock: jest.Mock;
|
||||
let trayIconPaths: TrayIconPaths;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
@ -44,6 +47,7 @@ describe("installing update using tray", () => {
|
||||
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
trayIconPaths = mainDi.inject(trayIconPathsInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -58,6 +62,10 @@ describe("installing update using tray", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should use the normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(trayIconPaths.normal);
|
||||
});
|
||||
|
||||
it("user cannot install update yet", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
@ -73,15 +81,19 @@ describe("installing update using tray", () => {
|
||||
expect(showApplicationWindowMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should still use the normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(trayIconPaths.normal);
|
||||
});
|
||||
|
||||
it("user cannot check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates indicates that checking is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
|
||||
).toBe("Checking for updates...");
|
||||
});
|
||||
|
||||
@ -106,19 +118,23 @@ describe("installing update using tray", () => {
|
||||
expect(showApplicationWindowMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should still use the normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(trayIconPaths.normal);
|
||||
});
|
||||
|
||||
it("user cannot install update", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that checking is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
@ -141,15 +157,19 @@ describe("installing update using tray", () => {
|
||||
expect(showApplicationWindowMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should use the update available icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(trayIconPaths.updateAvailable);
|
||||
});
|
||||
|
||||
it("user cannot check for updates again yet", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
|
||||
).toBe("Downloading update some-version (0%)...");
|
||||
});
|
||||
|
||||
@ -161,7 +181,7 @@ describe("installing update using tray", () => {
|
||||
progressOfUpdateDownload.set({ percentage: 42.424242 });
|
||||
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
|
||||
).toBe("Downloading update some-version (42%)...");
|
||||
});
|
||||
|
||||
@ -184,15 +204,19 @@ describe("installing update using tray", () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("should revert to use the normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(trayIconPaths.normal);
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
@ -208,19 +232,23 @@ describe("installing update using tray", () => {
|
||||
|
||||
it("user can install update", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("install-update")?.label,
|
||||
applicationBuilder.tray.get("install-update")?.label?.get(),
|
||||
).toBe("Install update some-version");
|
||||
});
|
||||
|
||||
it("should use the update available icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(trayIconPaths.updateAvailable);
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
|
||||
export type UpdateChannelId = "alpha" | "beta" | "latest";
|
||||
|
||||
const latestChannel: UpdateChannel = {
|
||||
|
||||
@ -4,12 +4,21 @@
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type { JsonValue } from "type-fest";
|
||||
|
||||
export interface SyncBox<TValue extends JsonValue> {
|
||||
type AsJson<T> = T extends string | number | boolean | null
|
||||
? T
|
||||
: T extends Function
|
||||
? never
|
||||
: T extends Array<infer V>
|
||||
? AsJson<V>[]
|
||||
: T extends object
|
||||
? { [K in keyof T]: AsJson<T[K]> }
|
||||
: never;
|
||||
|
||||
export interface SyncBox<TValue> {
|
||||
id: string;
|
||||
value: IComputedValue<TValue>;
|
||||
set: (value: TValue) => void;
|
||||
value: IComputedValue<AsJson<TValue>>;
|
||||
set: (value: AsJson<TValue>) => void;
|
||||
}
|
||||
|
||||
export const syncBoxInjectionToken = getInjectionToken<SyncBox<any>>({
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { MenuItemConstructorOptions } from "electron";
|
||||
import { Menu } from "electron";
|
||||
|
||||
export type BuildMenuFromTemplate = (template: MenuItemConstructorOptions[]) => Menu;
|
||||
|
||||
const buildMenuFromTemplateInjectable = getInjectable({
|
||||
id: "build-menu-from-template",
|
||||
instantiate: (): BuildMenuFromTemplate => (template) => Menu.buildFromTemplate(template),
|
||||
causesSideEffects: true, // Not really but isn't defined
|
||||
});
|
||||
|
||||
export default buildMenuFromTemplateInjectable;
|
||||
@ -3,20 +3,28 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { Menu } from "electron";
|
||||
import { Tray } from "electron";
|
||||
import { Menu, Tray } from "electron";
|
||||
import packageJsonInjectable from "../../../common/vars/package-json.injectable";
|
||||
import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable";
|
||||
import isWindowsInjectable from "../../../common/vars/is-windows.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import trayIconPathsInjectable from "../tray-icon-path.injectable";
|
||||
import type { TrayMenuItem } from "../tray-menu-item/tray-menu-item-injection-token";
|
||||
import { convertToElectronMenuTemplate } from "../reactive-tray-menu-items/converters";
|
||||
|
||||
const TRAY_LOG_PREFIX = "[TRAY]";
|
||||
|
||||
export interface ElectronTray {
|
||||
start(): void;
|
||||
stop(): void;
|
||||
setMenuItems(menuItems: TrayMenuItem[]): void;
|
||||
setIconPath(iconPath: string): void;
|
||||
}
|
||||
|
||||
const electronTrayInjectable = getInjectable({
|
||||
id: "electron-tray",
|
||||
|
||||
instantiate: (di) => {
|
||||
instantiate: (di): ElectronTray => {
|
||||
const packageJson = di.inject(packageJsonInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const isWindows = di.inject(isWindowsInjectable);
|
||||
@ -42,10 +50,13 @@ const electronTrayInjectable = getInjectable({
|
||||
stop: () => {
|
||||
tray.destroy();
|
||||
},
|
||||
setMenu: (menu: Menu) => {
|
||||
setMenuItems: (menuItems) => {
|
||||
const template = convertToElectronMenuTemplate(menuItems);
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
|
||||
tray.setContextMenu(menu);
|
||||
},
|
||||
setIconPath: (iconPath: string) => {
|
||||
setIconPath: (iconPath) => {
|
||||
tray.setImage(iconPath);
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { TrayMenuItem } from "../tray-menu-item/tray-menu-item-injection-token";
|
||||
|
||||
const convertToElectronMenuTemplateInjectable = getInjectable({
|
||||
id: "convert-to-electron-menu-template",
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return (trayMenuItems: TrayMenuItem[]) => {
|
||||
const toTrayMenuOptions = (parentId: string | null) => (
|
||||
trayMenuItems
|
||||
.filter((item) => item.parentId === parentId)
|
||||
.map((trayMenuItem: TrayMenuItem): Electron.MenuItemConstructorOptions => {
|
||||
if (trayMenuItem.separator) {
|
||||
return { id: trayMenuItem.id, type: "separator" };
|
||||
}
|
||||
|
||||
const childItems = toTrayMenuOptions(trayMenuItem.id);
|
||||
|
||||
return {
|
||||
id: trayMenuItem.id,
|
||||
label: trayMenuItem.label?.get(),
|
||||
enabled: trayMenuItem.enabled.get(),
|
||||
toolTip: trayMenuItem.tooltip,
|
||||
|
||||
...(childItems.length === 0
|
||||
? {
|
||||
type: "normal",
|
||||
submenu: toTrayMenuOptions(trayMenuItem.id),
|
||||
|
||||
click: () => {
|
||||
(async () => {
|
||||
try {
|
||||
await trayMenuItem.click?.();
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`[TRAY]: clicking item "${trayMenuItem.id} failed."`,
|
||||
{ error },
|
||||
);
|
||||
}
|
||||
})();
|
||||
},
|
||||
}
|
||||
: {
|
||||
type: "submenu",
|
||||
submenu: toTrayMenuOptions(trayMenuItem.id),
|
||||
}),
|
||||
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return toTrayMenuOptions(null);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default convertToElectronMenuTemplateInjectable;
|
||||
40
src/main/tray/reactive-tray-menu-items/converters.ts
Normal file
40
src/main/tray/reactive-tray-menu-items/converters.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { TrayMenuItem } from "../tray-menu-item/tray-menu-item-injection-token";
|
||||
|
||||
export function convertToElectronMenuTemplate(trayMenuItems: TrayMenuItem[]): Electron.MenuItemConstructorOptions[] {
|
||||
const toTrayMenuOptions = (parentId: string | null) => (
|
||||
trayMenuItems
|
||||
.filter((item) => item.parentId === parentId)
|
||||
.map((trayMenuItem: TrayMenuItem): Electron.MenuItemConstructorOptions => {
|
||||
if (trayMenuItem.separator) {
|
||||
return { id: trayMenuItem.id, type: "separator" };
|
||||
}
|
||||
|
||||
const childItems = toTrayMenuOptions(trayMenuItem.id);
|
||||
|
||||
return {
|
||||
id: trayMenuItem.id,
|
||||
label: trayMenuItem.label?.get(),
|
||||
enabled: trayMenuItem.enabled.get(),
|
||||
toolTip: trayMenuItem.tooltip,
|
||||
|
||||
...(childItems.length === 0
|
||||
? {
|
||||
type: "normal",
|
||||
submenu: toTrayMenuOptions(trayMenuItem.id),
|
||||
click: trayMenuItem.click,
|
||||
}
|
||||
: {
|
||||
type: "submenu",
|
||||
submenu: toTrayMenuOptions(trayMenuItem.id),
|
||||
}),
|
||||
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return toTrayMenuOptions(null);
|
||||
}
|
||||
@ -6,19 +6,19 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
|
||||
import { reaction } from "mobx";
|
||||
import electronTrayInjectable from "../electron-tray/electron-tray.injectable";
|
||||
import trayMenuInjectable from "./tray-menu.injectable";
|
||||
import trayMenuItemsInjectable from "../tray-menu-item/tray-menu-items.injectable";
|
||||
|
||||
const reactiveTrayMenuItemsInjectable = getInjectable({
|
||||
id: "reactive-tray-menu-items",
|
||||
|
||||
instantiate: (di) => {
|
||||
const electronTray = di.inject(electronTrayInjectable);
|
||||
const trayMenu = di.inject(trayMenuInjectable);
|
||||
const trayMenuItems = di.inject(trayMenuItemsInjectable);
|
||||
|
||||
return getStartableStoppable("reactive-tray-menu-items", () => (
|
||||
reaction(
|
||||
() => trayMenu.get(),
|
||||
electronTray.setMenu,
|
||||
() => trayMenuItems.get(),
|
||||
electronTray.setMenuItems,
|
||||
{
|
||||
fireImmediately: true,
|
||||
},
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import trayMenuItemsInjectable from "../tray-menu-item/tray-menu-items.injectable";
|
||||
import buildMenuFromTemplateInjectable from "../../electron/build-from-template.injectable";
|
||||
import convertToElectronMenuTemplateInjectable from "./convert-to-electron-menu-template.injectable";
|
||||
|
||||
const trayMenuInjectable = getInjectable({
|
||||
id: "tray-menu",
|
||||
instantiate: (di) => {
|
||||
const trayMenuItems = di.inject(trayMenuItemsInjectable);
|
||||
const convertToElectronMenuTemplate = di.inject(convertToElectronMenuTemplateInjectable);
|
||||
const buildMenuFromTemplate = di.inject(buildMenuFromTemplateInjectable);
|
||||
|
||||
return computed(() => (
|
||||
buildMenuFromTemplate(
|
||||
convertToElectronMenuTemplate(
|
||||
trayMenuItems.get(),
|
||||
),
|
||||
)
|
||||
));
|
||||
},
|
||||
});
|
||||
|
||||
export default trayMenuInjectable;
|
||||
@ -8,10 +8,15 @@ import staticFilesDirectoryInjectable from "../../common/vars/static-files-direc
|
||||
import isDevelopmentInjectable from "../../common/vars/is-development.injectable";
|
||||
import isMacInjectable from "../../common/vars/is-mac.injectable";
|
||||
|
||||
export interface TrayIconPaths {
|
||||
normal: string;
|
||||
updateAvailable: string;
|
||||
}
|
||||
|
||||
const trayIconPathsInjectable = getInjectable({
|
||||
id: "tray-icon-paths",
|
||||
|
||||
instantiate: (di) => {
|
||||
instantiate: (di): TrayIconPaths => {
|
||||
const getAbsolutePath = di.inject(getAbsolutePathInjectable);
|
||||
const staticFilesDirectory = di.inject(staticFilesDirectoryInjectable);
|
||||
const isDevelopment = di.inject(isDevelopmentInjectable);
|
||||
|
||||
@ -24,12 +24,12 @@ import type { ClusterStore } from "../../../common/cluster-store/cluster-store";
|
||||
import mainExtensionsInjectable from "../../../extensions/main-extensions.injectable";
|
||||
import currentRouteComponentInjectable from "../../routes/current-route-component.injectable";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { flatMap, compact, join, get, filter, map } from "lodash/fp";
|
||||
import { flatMap, compact, join, get, filter, map, matches, find } from "lodash/fp";
|
||||
import preferenceNavigationItemsInjectable from "../+preferences/preferences-navigation/preference-navigation-items.injectable";
|
||||
import navigateToPreferencesInjectable from "../../../common/front-end-routing/routes/preferences/navigate-to-preferences.injectable";
|
||||
import type { MenuItemOpts } from "../../../main/menu/application-menu-items.injectable";
|
||||
import applicationMenuItemsInjectable from "../../../main/menu/application-menu-items.injectable";
|
||||
import type { MenuItemConstructorOptions, MenuItem, Menu } from "electron";
|
||||
import type { MenuItemConstructorOptions, MenuItem } from "electron";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import navigateToHelmChartsInjectable from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable";
|
||||
import hostedClusterInjectable from "../../../common/cluster-store/hosted-cluster.injectable";
|
||||
@ -50,7 +50,8 @@ import broadcastThatRootFrameIsRenderedInjectable from "../../frames/root-frame/
|
||||
import { getDiForUnitTesting as getRendererDi } from "../../getDiForUnitTesting";
|
||||
import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTesting";
|
||||
import { overrideChannels } from "../../../test-utils/channel-fakes/override-channels";
|
||||
import buildMenuFromTemplateInjectable from "../../../main/electron/build-from-template.injectable";
|
||||
import type { TrayMenuItem } from "../../../main/tray/tray-menu-item/tray-menu-item-injection-token";
|
||||
import trayIconPathsInjectable from "../../../main/tray/tray-icon-path.injectable";
|
||||
|
||||
type Callback = (dis: DiContainers) => void | Promise<void>;
|
||||
|
||||
@ -65,7 +66,8 @@ export interface ApplicationBuilder {
|
||||
|
||||
tray: {
|
||||
click: (id: string) => Promise<void>;
|
||||
get: (id: string) => Electron.MenuItem | null;
|
||||
get: (id: string) => TrayMenuItem | null;
|
||||
getIconPath: () => string;
|
||||
};
|
||||
|
||||
applicationMenu: {
|
||||
@ -96,10 +98,6 @@ interface Environment {
|
||||
onAllowKubeResource: () => void;
|
||||
}
|
||||
|
||||
const getAllSubMenuItems = (item: MenuItem): MenuItem[] => {
|
||||
return [item, ...(item.submenu?.items ?? []).flatMap(getAllSubMenuItems)];
|
||||
};
|
||||
|
||||
export const getApplicationBuilder = () => {
|
||||
const mainDi = getMainDi({
|
||||
doGeneralOverrides: true,
|
||||
@ -170,84 +168,22 @@ export const getApplicationBuilder = () => {
|
||||
computed(() => []),
|
||||
);
|
||||
|
||||
let commandId = 0;
|
||||
const makeFakeMenuItem = (opts: MenuItemConstructorOptions, menu: Menu): MenuItem => {
|
||||
const menuItemFake: MenuItem = {
|
||||
accelerator: opts.accelerator,
|
||||
checked: opts.checked ?? false,
|
||||
click: () => opts.click?.(menuItemFake, undefined, new KeyboardEvent("fake")),
|
||||
commandId: commandId += 1,
|
||||
enabled: opts.enabled ?? false,
|
||||
icon: opts.icon,
|
||||
id: opts.id ?? "",
|
||||
label: opts.label ?? "",
|
||||
menu,
|
||||
registerAccelerator: opts.registerAccelerator ?? true,
|
||||
sharingItem: opts.sharingItem ?? {},
|
||||
sublabel: opts.sublabel ?? "",
|
||||
toolTip: opts.toolTip ?? "",
|
||||
type: opts.type ?? "normal",
|
||||
visible: opts.visible ?? true,
|
||||
role: opts.role,
|
||||
submenu: opts.submenu === undefined
|
||||
? undefined
|
||||
: Array.isArray(opts.submenu)
|
||||
? makeFakeMenu(opts.submenu)
|
||||
: opts.submenu,
|
||||
};
|
||||
const iconPaths = mainDi.inject(trayIconPathsInjectable);
|
||||
|
||||
return menuItemFake;
|
||||
};
|
||||
const makeFakeMenu = (templates: MenuItemConstructorOptions[]): Menu => {
|
||||
const menuFake: Electron.Menu = {
|
||||
addListener: () => {
|
||||
throw new Error("Adding listeners is not supported currently");
|
||||
},
|
||||
on: () => {
|
||||
throw new Error("Adding listeners is not supported currently");
|
||||
},
|
||||
once: () => {
|
||||
throw new Error("Adding listeners is not supported currently");
|
||||
},
|
||||
removeListener: () => {
|
||||
throw new Error("Removing listeners is not supported currently");
|
||||
},
|
||||
append: () => {
|
||||
throw new Error("Adding new menu items is not supported currently");
|
||||
},
|
||||
insert: () => {
|
||||
throw new Error("Adding new menu items is not supported currently");
|
||||
},
|
||||
popup: () => {
|
||||
throw new Error("Popping up menu is not supported currently");
|
||||
},
|
||||
closePopup: () => {
|
||||
throw new Error("Popping up menu is not supported currently");
|
||||
},
|
||||
get items() {
|
||||
return [...menuItems];
|
||||
},
|
||||
getMenuItemById: (id) => menuItems
|
||||
.flatMap(getAllSubMenuItems)
|
||||
.find(menuItem => menuItem.id === id)
|
||||
?? null,
|
||||
};
|
||||
const menuItems = templates.map(template => makeFakeMenuItem(template, menuFake));
|
||||
|
||||
return menuFake;
|
||||
};
|
||||
|
||||
mainDi.override(buildMenuFromTemplateInjectable, () => makeFakeMenu);
|
||||
|
||||
let trayMenuStateFake: Electron.Menu | undefined;
|
||||
let trayMenuItemsStateFake: TrayMenuItem[];
|
||||
let trayMenuIconPath: string;
|
||||
|
||||
mainDi.override(electronTrayInjectable, () => ({
|
||||
start: () => {},
|
||||
stop: () => {},
|
||||
setMenu: (menu) => {
|
||||
trayMenuStateFake = menu;
|
||||
start: () => {
|
||||
trayMenuIconPath = iconPaths.normal;
|
||||
},
|
||||
stop: () => {},
|
||||
setMenuItems: (items) => {
|
||||
trayMenuItemsStateFake = items;
|
||||
},
|
||||
setIconPath: (path) => {
|
||||
trayMenuIconPath = path;
|
||||
},
|
||||
setIconPath: () => {},
|
||||
}));
|
||||
|
||||
let allowedResourcesState: IObservableArray<KubeResource>;
|
||||
@ -294,20 +230,18 @@ export const getApplicationBuilder = () => {
|
||||
|
||||
tray: {
|
||||
get: (id: string) => {
|
||||
return trayMenuStateFake?.getMenuItemById(id) ?? null;
|
||||
return trayMenuItemsStateFake.find(matches({ id })) ?? null;
|
||||
},
|
||||
|
||||
getIconPath: () => trayMenuIconPath,
|
||||
click: async (id: string) => {
|
||||
if (!trayMenuStateFake) {
|
||||
throw new Error(`Tried to click tray menu with ID ${id}, but tray menu has not been set yet`);
|
||||
}
|
||||
|
||||
const menuItem = trayMenuStateFake.getMenuItemById(id);
|
||||
const menuItem = pipeline(
|
||||
trayMenuItemsStateFake,
|
||||
find((menuItem) => menuItem.id === id),
|
||||
);
|
||||
|
||||
if (!menuItem) {
|
||||
const availableIds = pipeline(
|
||||
trayMenuStateFake.items,
|
||||
flatMap(getAllSubMenuItems),
|
||||
trayMenuItemsStateFake,
|
||||
filter(item => !!item.click),
|
||||
map(item => item.id),
|
||||
join(", "),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user