mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add computed tray menu for extensions.
Signed-off-by: Panu Horsmalahti <phorsmalahti@mirantis.com>
This commit is contained in:
parent
9ed64a29df
commit
2846f04e96
@ -4,9 +4,11 @@
|
||||
*/
|
||||
import type { Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type { LensExtension } from "../lens-extension";
|
||||
|
||||
export type ExtensionRegistrator = (extension: LensExtension) => Injectable<any, any, any>[];
|
||||
export type ExtensionRegistrator = (extension: LensExtension) =>
|
||||
Injectable<any, any, any>[] | IComputedValue<Injectable<any, any, any>[]>;
|
||||
|
||||
export const extensionRegistratorInjectionToken = getInjectionToken<ExtensionRegistrator>({
|
||||
id: "extension-registrator-token",
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import type { IReactionDisposer } from "mobx";
|
||||
import { reaction, runInAction } from "mobx";
|
||||
import type { LensExtension } from "../../lens-extension";
|
||||
import { extensionRegistratorInjectionToken } from "../extension-registrator-injection-token";
|
||||
|
||||
@ -21,19 +22,39 @@ const extensionInjectable = getInjectable({
|
||||
|
||||
instantiate: (childDi) => {
|
||||
const extensionRegistrators = childDi.injectMany(extensionRegistratorInjectionToken);
|
||||
const disposers: IReactionDisposer[] = [];
|
||||
|
||||
return {
|
||||
register: () => {
|
||||
const injectables = extensionRegistrators.flatMap((getInjectablesOfExtension) =>
|
||||
getInjectablesOfExtension(instance),
|
||||
);
|
||||
extensionRegistrators.forEach((getInjectablesOfExtension) => {
|
||||
const injectables = getInjectablesOfExtension(instance);
|
||||
|
||||
runInAction(() => {
|
||||
childDi.register(...injectables);
|
||||
disposers.push(
|
||||
// injectables is either an array or a computed array, in which case
|
||||
// we need to update the registered injectables with a reaction every time they change
|
||||
reaction(
|
||||
() => Array.isArray(injectables) ? injectables : injectables.get(),
|
||||
(currentInjectables, previousInjectables) => {
|
||||
// On the second reaction remove the previously registered injectables to avoid duplicate injectables
|
||||
if (previousInjectables) {
|
||||
childDi.deregister(...previousInjectables);
|
||||
}
|
||||
|
||||
childDi.register(...currentInjectables);
|
||||
}, {
|
||||
fireImmediately: true,
|
||||
},
|
||||
));
|
||||
});
|
||||
},
|
||||
|
||||
deregister: () => {
|
||||
disposers.forEach(dispose => {
|
||||
dispose();
|
||||
});
|
||||
|
||||
disposers.length = 0;
|
||||
|
||||
runInAction(() => {
|
||||
parentDi.deregister(extensionInjectable);
|
||||
});
|
||||
@ -50,7 +71,7 @@ const extensionInjectable = getInjectable({
|
||||
},
|
||||
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, instance: LensExtension) => instance,
|
||||
getInstanceKey: (_di, instance: LensExtension) => instance,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
import { LensExtension, lensExtensionDependencies } from "./lens-extension";
|
||||
import type { CatalogEntity } from "../common/catalog";
|
||||
import type { IObservableArray } from "mobx";
|
||||
import type { IComputedValue, IObservableArray } from "mobx";
|
||||
import type { MenuRegistration } from "../features/application-menu/main/menu-registration";
|
||||
import type { TrayMenuRegistration } from "../main/tray/tray-menu-registration";
|
||||
import type { ShellEnvModifier } from "../main/shell-session/shell-env-modifier/shell-env-modifier-registration";
|
||||
@ -13,7 +13,7 @@ import type { LensMainExtensionDependencies } from "./lens-extension-set-depende
|
||||
|
||||
export class LensMainExtension extends LensExtension<LensMainExtensionDependencies> {
|
||||
appMenus: MenuRegistration[] = [];
|
||||
trayMenus: TrayMenuRegistration[] = [];
|
||||
trayMenus: TrayMenuRegistration[] | IComputedValue<TrayMenuRegistration[]> = [];
|
||||
|
||||
/**
|
||||
* implement this to modify the shell environment that Lens terminals are opened with. The ShellEnvModifier type has the signature
|
||||
|
||||
@ -2,13 +2,14 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { IObservableValue } from "mobx";
|
||||
import type { IObservableArray, IObservableValue } from "mobx";
|
||||
import { computed, runInAction, observable } from "mobx";
|
||||
import type { TrayMenuRegistration } from "../../main/tray/tray-menu-registration";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
|
||||
describe("preferences: extension adding tray items", () => {
|
||||
describe("when extension with tray items is enabled", () => {
|
||||
describe("when extension with tray items are statically defined", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let someObservableForVisibility: IObservableValue<boolean>;
|
||||
let someObservableForEnabled: IObservableValue<boolean>;
|
||||
@ -190,4 +191,72 @@ describe("preferences: extension adding tray items", () => {
|
||||
expect(item?.enabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when extension with tray items are dynamically defined", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let menuItems: IObservableArray<TrayMenuRegistration>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
await builder.render();
|
||||
|
||||
builder.preferences.navigate();
|
||||
|
||||
menuItems = observable.array([
|
||||
{
|
||||
id: "some-visible",
|
||||
label: "some-visible",
|
||||
click: () => {},
|
||||
visible: computed(() => true),
|
||||
},
|
||||
]);
|
||||
|
||||
const computedTrayMenu = computed(() => menuItems);
|
||||
|
||||
const testExtension = {
|
||||
id: "some-extension-id",
|
||||
name: "some-extension",
|
||||
|
||||
mainOptions: {
|
||||
trayMenus: computedTrayMenu,
|
||||
},
|
||||
};
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
it("given item exists, it's shown", () => {
|
||||
expect(
|
||||
builder.tray.get(
|
||||
"some-visible-tray-menu-item-for-extension-some-extension",
|
||||
),
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
it("given item is added, it's shown", async () => {
|
||||
menuItems.push({
|
||||
id: "some-added",
|
||||
label: "some-added",
|
||||
click: () => {},
|
||||
visible: computed(() => true),
|
||||
});
|
||||
|
||||
expect(
|
||||
builder.tray.get(
|
||||
"some-added-tray-menu-item-for-extension-some-extension",
|
||||
),
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
it("given item is removed, it's not shown", async () => {
|
||||
menuItems.replace([]);
|
||||
|
||||
expect(
|
||||
builder.tray.get(
|
||||
"some-visible-tray-menu-item-for-extension-some-extension",
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -15,8 +15,8 @@ const startReactiveTrayMenuItemsInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
id: "start-reactive-tray-menu-items",
|
||||
run: async () => {
|
||||
await reactiveTrayMenuItems.start();
|
||||
run: () => {
|
||||
reactiveTrayMenuItems.start();
|
||||
},
|
||||
|
||||
runAfter: di.inject(startTrayInjectable),
|
||||
|
||||
@ -25,9 +25,13 @@ const trayMenuItemRegistratorInjectable = getInjectable({
|
||||
const withErrorLoggingFor = di.inject(withErrorLoggingInjectable);
|
||||
const getRandomId = di.inject(getRandomIdInjectable);
|
||||
|
||||
return mainExtension.trayMenus.flatMap(
|
||||
toItemInjectablesFor(mainExtension, withErrorLoggingFor, getRandomId),
|
||||
);
|
||||
return computed(() => {
|
||||
const trayMenus = Array.isArray(mainExtension.trayMenus) ? mainExtension.trayMenus : mainExtension.trayMenus.get();
|
||||
|
||||
return trayMenus.flatMap(
|
||||
toItemInjectablesFor(mainExtension, withErrorLoggingFor, getRandomId),
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: extensionRegistratorInjectionToken,
|
||||
@ -117,5 +121,3 @@ const toItemInjectablesFor = (extension: LensMainExtension, withErrorLoggingFor:
|
||||
|
||||
return _toItemInjectables(null);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user