mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Enable installed extensions by default (#1572)
Signed-off-by: Panu Horsmalahti <phorsmalahti@mirantis.com>
This commit is contained in:
parent
f3f9f08c0a
commit
7798dce61d
@ -9,7 +9,7 @@ jest.mock(
|
|||||||
() => ({
|
() => ({
|
||||||
ipcRenderer: {
|
ipcRenderer: {
|
||||||
invoke: jest.fn(async (channel: string) => {
|
invoke: jest.fn(async (channel: string) => {
|
||||||
if (channel === "extensions:loaded") {
|
if (channel === "extensions:main") {
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
manifestPath,
|
manifestPath,
|
||||||
@ -44,7 +44,7 @@ jest.mock(
|
|||||||
}),
|
}),
|
||||||
on: jest.fn(
|
on: jest.fn(
|
||||||
(channel: string, listener: (event: any, ...args: any[]) => void) => {
|
(channel: string, listener: (event: any, ...args: any[]) => void) => {
|
||||||
if (channel === "extensions:loaded") {
|
if (channel === "extensions:main") {
|
||||||
// First initialize with extensions 1 and 2
|
// First initialize with extensions 1 and 2
|
||||||
// and then broadcast event to remove extensioin 2 and add extension number 3
|
// and then broadcast event to remove extensioin 2 and add extension number 3
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { app, ipcRenderer, remote } from "electron";
|
import { app, ipcRenderer, remote } from "electron";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
import { action, computed, observable, reaction, toJS, when } from "mobx";
|
import { action, computed, observable, reaction, toJS, when } from "mobx";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { getHostedCluster } from "../common/cluster-store";
|
import { getHostedCluster } from "../common/cluster-store";
|
||||||
@ -25,7 +26,12 @@ const logModule = "[EXTENSIONS-LOADER]";
|
|||||||
export class ExtensionLoader {
|
export class ExtensionLoader {
|
||||||
protected extensions = observable.map<LensExtensionId, InstalledExtension>();
|
protected extensions = observable.map<LensExtensionId, InstalledExtension>();
|
||||||
protected instances = observable.map<LensExtensionId, LensExtension>();
|
protected instances = observable.map<LensExtensionId, LensExtension>();
|
||||||
protected readonly requestExtensionsChannel = "extensions:loaded";
|
|
||||||
|
// IPC channel to broadcast changes to extensions from main
|
||||||
|
protected static readonly extensionsMainChannel = "extensions:main";
|
||||||
|
|
||||||
|
// IPC channel to broadcast changes to extensions from renderer
|
||||||
|
protected static readonly extensionsRendererChannel = "extensions:renderer";
|
||||||
|
|
||||||
// emits event "remove" of type LensExtension when the extension is removed
|
// emits event "remove" of type LensExtension when the extension is removed
|
||||||
private events = new EventEmitter();
|
private events = new EventEmitter();
|
||||||
@ -95,28 +101,27 @@ export class ExtensionLoader {
|
|||||||
this.loadOnMain();
|
this.loadOnMain();
|
||||||
this.broadcastExtensions();
|
this.broadcastExtensions();
|
||||||
|
|
||||||
reaction(() => this.extensions.toJS(), () => {
|
reaction(() => this.toJSON(), () => {
|
||||||
this.broadcastExtensions();
|
this.broadcastExtensions();
|
||||||
});
|
});
|
||||||
|
|
||||||
handleRequest(this.requestExtensionsChannel, () => {
|
handleRequest(ExtensionLoader.extensionsMainChannel, () => {
|
||||||
return Array.from(this.toJSON());
|
return Array.from(this.toJSON());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
subscribeToBroadcast(ExtensionLoader.extensionsRendererChannel, (_event, extensions: [LensExtensionId, InstalledExtension][]) => {
|
||||||
|
this.syncExtensions(extensions);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initRenderer() {
|
protected async initRenderer() {
|
||||||
const extensionListHandler = (extensions: [LensExtensionId, InstalledExtension][]) => {
|
const extensionListHandler = (extensions: [LensExtensionId, InstalledExtension][]) => {
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
|
this.syncExtensions(extensions);
|
||||||
|
|
||||||
const receivedExtensionIds = extensions.map(([lensExtensionId]) => lensExtensionId);
|
const receivedExtensionIds = extensions.map(([lensExtensionId]) => lensExtensionId);
|
||||||
|
|
||||||
// Add new extensions
|
// Remove deleted extensions in renderer side only
|
||||||
extensions.forEach(([extId, ext]) => {
|
|
||||||
if (!this.extensions.has(extId)) {
|
|
||||||
this.extensions.set(extId, ext);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove deleted extensions
|
|
||||||
this.extensions.forEach((_, lensExtensionId) => {
|
this.extensions.forEach((_, lensExtensionId) => {
|
||||||
if (!receivedExtensionIds.includes(lensExtensionId)) {
|
if (!receivedExtensionIds.includes(lensExtensionId)) {
|
||||||
this.removeExtension(lensExtensionId);
|
this.removeExtension(lensExtensionId);
|
||||||
@ -124,14 +129,26 @@ export class ExtensionLoader {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
requestMain(this.requestExtensionsChannel).then(extensionListHandler);
|
reaction(() => this.toJSON(), () => {
|
||||||
subscribeToBroadcast(this.requestExtensionsChannel, (event, extensions: [LensExtensionId, InstalledExtension][]) => {
|
this.broadcastExtensions(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
requestMain(ExtensionLoader.extensionsMainChannel).then(extensionListHandler);
|
||||||
|
subscribeToBroadcast(ExtensionLoader.extensionsMainChannel, (_event, extensions: [LensExtensionId, InstalledExtension][]) => {
|
||||||
extensionListHandler(extensions);
|
extensionListHandler(extensions);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncExtensions(extensions: [LensExtensionId, InstalledExtension][]) {
|
||||||
|
extensions.forEach(([lensExtensionId, extension]) => {
|
||||||
|
if (!isEqual(this.extensions.get(lensExtensionId), extension)) {
|
||||||
|
this.extensions.set(lensExtensionId, extension);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
loadOnMain() {
|
loadOnMain() {
|
||||||
logger.info(`${logModule}: load on main`);
|
logger.debug(`${logModule}: load on main`);
|
||||||
this.autoInitExtensions(async (extension: LensMainExtension) => {
|
this.autoInitExtensions(async (extension: LensMainExtension) => {
|
||||||
// Each .add returns a function to remove the item
|
// Each .add returns a function to remove the item
|
||||||
const removeItems = [
|
const removeItems = [
|
||||||
@ -151,7 +168,7 @@ export class ExtensionLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadOnClusterManagerRenderer() {
|
loadOnClusterManagerRenderer() {
|
||||||
logger.info(`${logModule}: load on main renderer (cluster manager)`);
|
logger.debug(`${logModule}: load on main renderer (cluster manager)`);
|
||||||
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
||||||
const removeItems = [
|
const removeItems = [
|
||||||
registries.globalPageRegistry.add(extension.globalPages, extension),
|
registries.globalPageRegistry.add(extension.globalPages, extension),
|
||||||
@ -174,7 +191,7 @@ export class ExtensionLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadOnClusterRenderer() {
|
loadOnClusterRenderer() {
|
||||||
logger.info(`${logModule}: load on cluster renderer (dashboard)`);
|
logger.debug(`${logModule}: load on cluster renderer (dashboard)`);
|
||||||
const cluster = getHostedCluster();
|
const cluster = getHostedCluster();
|
||||||
|
|
||||||
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
||||||
@ -204,26 +221,26 @@ export class ExtensionLoader {
|
|||||||
|
|
||||||
protected autoInitExtensions(register: (ext: LensExtension) => Promise<Function[]>) {
|
protected autoInitExtensions(register: (ext: LensExtension) => Promise<Function[]>) {
|
||||||
return reaction(() => this.toJSON(), installedExtensions => {
|
return reaction(() => this.toJSON(), installedExtensions => {
|
||||||
for (const [extId, ext] of installedExtensions) {
|
for (const [extId, extension] of installedExtensions) {
|
||||||
const alreadyInit = this.instances.has(extId);
|
const alreadyInit = this.instances.has(extId);
|
||||||
|
|
||||||
if (ext.isEnabled && !alreadyInit) {
|
if (extension.isEnabled && !alreadyInit) {
|
||||||
try {
|
try {
|
||||||
const LensExtensionClass = this.requireExtension(ext);
|
const LensExtensionClass = this.requireExtension(extension);
|
||||||
|
|
||||||
if (!LensExtensionClass) {
|
if (!LensExtensionClass) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = new LensExtensionClass(ext);
|
const instance = new LensExtensionClass(extension);
|
||||||
|
|
||||||
instance.whenEnabled(() => register(instance));
|
instance.whenEnabled(() => register(instance));
|
||||||
instance.enable();
|
instance.enable();
|
||||||
this.instances.set(extId, instance);
|
this.instances.set(extId, instance);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`${logModule}: activation extension error`, { ext, err });
|
logger.error(`${logModule}: activation extension error`, { ext: extension, err });
|
||||||
}
|
}
|
||||||
} else if (!ext.isEnabled && alreadyInit) {
|
} else if (!extension.isEnabled && alreadyInit) {
|
||||||
this.removeInstance(extId);
|
this.removeInstance(extId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,8 +279,8 @@ export class ExtensionLoader {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcastExtensions() {
|
broadcastExtensions(main = true) {
|
||||||
broadcastMessage(this.requestExtensionsChannel, Array.from(this.toJSON()));
|
broadcastMessage(main ? ExtensionLoader.extensionsMainChannel : ExtensionLoader.extensionsRendererChannel, Array.from(this.toJSON()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,17 +45,6 @@ export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> {
|
|||||||
await extensionLoader.whenLoaded;
|
await extensionLoader.whenLoaded;
|
||||||
await this.whenLoaded;
|
await this.whenLoaded;
|
||||||
|
|
||||||
// apply state on changes from store
|
|
||||||
reaction(() => this.state.toJS(), extensionsState => {
|
|
||||||
extensionsState.forEach((state, extId) => {
|
|
||||||
const ext = extensionLoader.getExtension(extId);
|
|
||||||
|
|
||||||
if (ext && !ext.isBundled) {
|
|
||||||
ext.isEnabled = state.enabled;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// save state on change `extension.isEnabled`
|
// save state on change `extension.isEnabled`
|
||||||
reaction(() => this.getState(extensionLoader), extensionsState => {
|
reaction(() => this.getState(extensionLoader), extensionsState => {
|
||||||
this.state.merge(extensionsState);
|
this.state.merge(extensionsState);
|
||||||
@ -65,7 +54,9 @@ export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> {
|
|||||||
isEnabled(extId: LensExtensionId) {
|
isEnabled(extId: LensExtensionId) {
|
||||||
const state = this.state.get(extId);
|
const state = this.state.get(extId);
|
||||||
|
|
||||||
return state && state.enabled; // by default false
|
// By default false, so that copied extensions are disabled by default.
|
||||||
|
// If user installs the extension from the UI, the Extensions component will specifically enable it.
|
||||||
|
return Boolean(state?.enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@ -91,11 +91,20 @@ export class Extensions extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.addedInstalling.forEach(({ id, displayName }) => {
|
this.addedInstalling.forEach(({ id, displayName }) => {
|
||||||
|
const extension = this.extensions.find(extension => extension.id === id);
|
||||||
|
|
||||||
|
if (!extension) {
|
||||||
|
throw new Error("Extension not found");
|
||||||
|
}
|
||||||
|
|
||||||
Notifications.ok(
|
Notifications.ok(
|
||||||
<p>Extension <b>{displayName}</b> successfully installed!</p>
|
<p>Extension <b>{displayName}</b> successfully installed!</p>
|
||||||
);
|
);
|
||||||
this.extensionState.delete(id);
|
this.extensionState.delete(id);
|
||||||
this.installPath = "";
|
this.installPath = "";
|
||||||
|
|
||||||
|
// Enable installed extensions by default.
|
||||||
|
extension.isEnabled = true;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user