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

auto enable/disable extensions -- part 2

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-11-03 08:39:50 +02:00
parent addc55e577
commit 7de278f8b5
3 changed files with 42 additions and 32 deletions

View File

@ -3,7 +3,7 @@ import type { LensMainExtension } from "./lens-main-extension"
import type { LensRendererExtension } from "./lens-renderer-extension" import type { LensRendererExtension } from "./lens-renderer-extension"
import path from "path" import path from "path"
import { broadcastIpc } from "../common/ipc" import { broadcastIpc } from "../common/ipc"
import { action, computed, observable, reaction, toJS } from "mobx" import { action, autorun, computed, observable, reaction, toJS } from "mobx"
import logger from "../main/logger" import logger from "../main/logger"
import { app, ipcRenderer, remote } from "electron" import { app, ipcRenderer, remote } from "electron"
import { BaseStore } from "../common/base-store"; import { BaseStore } from "../common/base-store";
@ -25,6 +25,8 @@ export function extensionPackagesRoot() {
} }
export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> { export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
protected disposers = new Map<LensExtensionId, Function[]>();
@observable extensions = observable.map<LensExtensionId, InstalledExtension>([], { deep: false }); @observable extensions = observable.map<LensExtensionId, InstalledExtension>([], { deep: false });
@observable instances = observable.map<LensExtensionId, LensExtension>([], { deep: false }) @observable instances = observable.map<LensExtensionId, LensExtension>([], { deep: false })
@observable state = observable.map<LensExtensionId, LensExtensionStoreModel>(); @observable state = observable.map<LensExtensionId, LensExtensionStoreModel>();
@ -48,11 +50,22 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
return [...this.instances.values()].filter(ext => !ext.isBundled) return [...this.instances.values()].filter(ext => !ext.isBundled)
} }
protected handleActivation(ext: LensExtension, addToRegistry: () => Function[]) {
if (ext.isEnabled) {
this.disposers.set(ext.id, addToRegistry())
} else {
this.disposers.get(ext.id)?.forEach(dispose => dispose())
this.disposers.delete(ext.id)
}
}
loadOnMain() { loadOnMain() {
logger.info('[EXTENSIONS-LOADER]: load on main') logger.info('[EXTENSIONS-LOADER]: load on main')
this.autoInitExtensions(); this.autoInitExtensions();
this.autoEnableExtensions((extension: LensMainExtension) => { this.autoEnableExtensions((extension: LensMainExtension) => {
extension.registerTo(registries.menuRegistry, extension.appMenus) this.handleActivation(extension, () => [
registries.menuRegistry.add(...extension.appMenus)
])
}) })
} }
@ -60,10 +73,12 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)') logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)')
this.autoInitExtensions(); this.autoInitExtensions();
this.autoEnableExtensions((extension: LensRendererExtension) => { this.autoEnableExtensions((extension: LensRendererExtension) => {
extension.registerTo(registries.globalPageRegistry, extension.globalPages) this.handleActivation(extension, () => [
extension.registerTo(registries.appPreferenceRegistry, extension.appPreferences) registries.globalPageRegistry.add(...extension.globalPages),
extension.registerTo(registries.clusterFeatureRegistry, extension.clusterFeatures) registries.appPreferenceRegistry.add(...extension.appPreferences),
extension.registerTo(registries.statusBarRegistry, extension.statusBarItems) registries.clusterFeatureRegistry.add(...extension.clusterFeatures),
registries.statusBarRegistry.add(...extension.statusBarItems),
])
}) })
} }
@ -71,15 +86,17 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)') logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)')
this.autoInitExtensions(); this.autoInitExtensions();
this.autoEnableExtensions((extension: LensRendererExtension) => { this.autoEnableExtensions((extension: LensRendererExtension) => {
extension.registerTo(registries.clusterPageRegistry, extension.clusterPages) this.handleActivation(extension, () => [
extension.registerTo(registries.kubeObjectMenuRegistry, extension.kubeObjectMenuItems) registries.clusterPageRegistry.add(...extension.clusterPages),
extension.registerTo(registries.kubeObjectDetailRegistry, extension.kubeObjectDetailItems) registries.kubeObjectMenuRegistry.add(...extension.kubeObjectMenuItems),
registries.kubeObjectDetailRegistry.add(...extension.kubeObjectDetailItems),
])
}) })
} }
protected autoEnableExtensions(callback: (ext: LensExtension) => void) { protected autoEnableExtensions(callback: (ext: LensExtension) => void) {
return reaction(() => this.instances.toJS(), instances => { return autorun(() => {
instances.forEach(ext => { this.instances.forEach(ext => {
const extensionState = this.state.get(ext.id); const extensionState = this.state.get(ext.id);
const enabledInStore = !extensionState /*enabled by default*/ || extensionState.isEnabled; const enabledInStore = !extensionState /*enabled by default*/ || extensionState.isEnabled;
if (!ext.isEnabled && enabledInStore) { if (!ext.isEnabled && enabledInStore) {
@ -87,10 +104,9 @@ export class ExtensionLoader extends BaseStore<ExtensionLoaderStoreModel> {
callback(ext); callback(ext);
} else if (ext.isEnabled && !enabledInStore) { } else if (ext.isEnabled && !enabledInStore) {
ext.disable(); ext.disable();
callback(ext);
} }
}) })
}, {
fireImmediately: true,
}) })
} }

View File

@ -1,6 +1,5 @@
import { action, observable, toJS } from "mobx"; import { action, observable, toJS } from "mobx";
import logger from "../main/logger"; import logger from "../main/logger";
import { BaseRegistry } from "./registries/base-registry";
import type { InstalledExtension } from "./extension-loader"; import type { InstalledExtension } from "./extension-loader";
export type LensExtensionId = string; // path to manifest (package.json) export type LensExtensionId = string; // path to manifest (package.json)
@ -24,7 +23,6 @@ export class LensExtension {
public manifest: LensExtensionManifest; public manifest: LensExtensionManifest;
public manifestPath: string; public manifestPath: string;
public isBundled: boolean; public isBundled: boolean;
protected disposers: (() => void)[] = [];
@observable isEnabled = false; @observable isEnabled = false;
@ -54,17 +52,15 @@ export class LensExtension {
async enable() { async enable() {
if (this.isEnabled) return; if (this.isEnabled) return;
this.isEnabled = true; this.isEnabled = true;
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
this.onActivate(); this.onActivate();
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
} }
@action @action
async disable() { async disable() {
if (!this.isEnabled) return; if (!this.isEnabled) return;
this.onDeactivate();
this.isEnabled = false; this.isEnabled = false;
this.disposers.forEach(cleanUp => cleanUp()); this.onDeactivate();
this.disposers.length = 0;
logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`);
} }
@ -84,14 +80,6 @@ export class LensExtension {
// mock // mock
} }
registerTo<T = any>(registry: BaseRegistry<T>, items: T[] = []) {
const disposers = items.map(item => registry.add(item));
this.disposers.push(...disposers);
return () => {
this.disposers = this.disposers.filter(disposer => !disposers.includes(disposer))
};
}
toJSON(): LensExtensionStoreModel { toJSON(): LensExtensionStoreModel {
return toJS({ return toJS({
id: this.id, id: this.id,

View File

@ -1,5 +1,5 @@
// Base class for extensions-api registries // Base class for extensions-api registries
import { observable } from "mobx"; import { action, observable } from "mobx";
export class BaseRegistry<T = any> { export class BaseRegistry<T = any> {
protected items = observable<T>([], { deep: false }); protected items = observable<T>([], { deep: false });
@ -8,10 +8,16 @@ export class BaseRegistry<T = any> {
return this.items.toJS(); return this.items.toJS();
} }
add(item: T) { @action
this.items.push(item); add(...items: T[]) {
return () => { this.items.push(...items);
return () => this.remove(...items);
}
@action
remove(...items: T[]) {
items.forEach(item => {
this.items.remove(item); // works because of {deep: false}; this.items.remove(item); // works because of {deep: false};
} })
} }
} }