mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Send LensMainExtension.nagivate calls to renderer before navigating (#3082)
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
dc2d7a08d3
commit
c3c944cd30
@ -21,9 +21,9 @@
|
||||
|
||||
import { observable } from "mobx";
|
||||
|
||||
export type ClusterFrameInfo = {
|
||||
export interface ClusterFrameInfo {
|
||||
frameId: number;
|
||||
processId: number
|
||||
};
|
||||
}
|
||||
|
||||
export const clusterFrameMap = observable.map<string, ClusterFrameInfo>();
|
||||
|
||||
@ -140,3 +140,19 @@ export function* filterMapStrict<T, U>(src: Iterable<T>, fn: (from: T) => U | nu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through `src` until `match` returns a truthy value
|
||||
* @param src A type that can be iterated over
|
||||
* @param match A function that should return a truthy value for the item that you want to find
|
||||
* @returns The first entry that `match` returns a truthy value for, or `undefined`
|
||||
*/
|
||||
export function find<T>(src: Iterable<T>, match: (i: T) => any): T | undefined {
|
||||
for (const from of src) {
|
||||
if (match(from)) {
|
||||
return from;
|
||||
}
|
||||
}
|
||||
|
||||
return void 0;
|
||||
}
|
||||
|
||||
@ -24,6 +24,6 @@ export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from ".
|
||||
export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../registries/kube-object-menu-registry";
|
||||
export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry";
|
||||
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry";
|
||||
export type { PageMenuRegistration, ClusterPageMenuRegistration, PageMenuComponents } from "../registries/page-menu-registry";
|
||||
export type { ClusterPageMenuRegistration, ClusterPageMenuComponents } from "../registries/page-menu-registry";
|
||||
export type { StatusBarRegistration } from "../registries/status-bar-registry";
|
||||
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler";
|
||||
|
||||
@ -355,6 +355,10 @@ export class ExtensionLoader extends Singleton {
|
||||
return this.extensions.get(extId);
|
||||
}
|
||||
|
||||
getInstanceById<E extends LensExtension>(extId: LensExtensionId): E {
|
||||
return this.instances.get(extId) as E;
|
||||
}
|
||||
|
||||
toJSON(): Map<LensExtensionId, InstalledExtension> {
|
||||
return toJS(this.extensions);
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
|
||||
import { LensExtension } from "./lens-extension";
|
||||
import { WindowManager } from "../main/window-manager";
|
||||
import { getExtensionPageUrl } from "./registries/page-registry";
|
||||
import { catalogEntityRegistry } from "../main/catalog";
|
||||
import type { CatalogEntity } from "../common/catalog";
|
||||
import type { IObservableArray } from "mobx";
|
||||
@ -30,15 +29,8 @@ import type { MenuRegistration } from "./registries";
|
||||
export class LensMainExtension extends LensExtension {
|
||||
appMenus: MenuRegistration[] = [];
|
||||
|
||||
async navigate<P extends object>(pageId?: string, params?: P, frameId?: number) {
|
||||
const windowManager = WindowManager.getInstance();
|
||||
const pageUrl = getExtensionPageUrl({
|
||||
extensionId: this.name,
|
||||
pageId,
|
||||
params: params ?? {}, // compile to url with params
|
||||
});
|
||||
|
||||
await windowManager.navigate(pageUrl, frameId);
|
||||
async navigate(pageId?: string, params?: Record<string, any>, frameId?: number) {
|
||||
return WindowManager.getInstance().navigateExtension(this.id, pageId, params, frameId);
|
||||
}
|
||||
|
||||
addCatalogSource(id: string, source: IObservableArray<CatalogEntity>) {
|
||||
|
||||
@ -19,33 +19,26 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import type {
|
||||
AppPreferenceRegistration, CatalogEntityDetailRegistration, ClusterPageMenuRegistration, KubeObjectDetailRegistration, KubeObjectMenuRegistration,
|
||||
KubeObjectStatusRegistration, PageMenuRegistration, PageRegistration, StatusBarRegistration, WelcomeMenuRegistration, WorkloadsOverviewDetailRegistration,
|
||||
} from "./registries";
|
||||
import type * as registries from "./registries";
|
||||
import type { Cluster } from "../main/cluster";
|
||||
import { LensExtension } from "./lens-extension";
|
||||
import { getExtensionPageUrl } from "./registries/page-registry";
|
||||
import type { CommandRegistration } from "./registries/command-registry";
|
||||
import type { EntitySettingRegistration } from "./registries/entity-setting-registry";
|
||||
import type { TopBarRegistration } from "./registries/topbar-registry";
|
||||
|
||||
export class LensRendererExtension extends LensExtension {
|
||||
globalPages: PageRegistration[] = [];
|
||||
clusterPages: PageRegistration[] = [];
|
||||
globalPageMenus: PageMenuRegistration[] = [];
|
||||
clusterPageMenus: ClusterPageMenuRegistration[] = [];
|
||||
kubeObjectStatusTexts: KubeObjectStatusRegistration[] = [];
|
||||
appPreferences: AppPreferenceRegistration[] = [];
|
||||
entitySettings: EntitySettingRegistration[] = [];
|
||||
statusBarItems: StatusBarRegistration[] = [];
|
||||
kubeObjectDetailItems: KubeObjectDetailRegistration[] = [];
|
||||
kubeObjectMenuItems: KubeObjectMenuRegistration[] = [];
|
||||
kubeWorkloadsOverviewItems: WorkloadsOverviewDetailRegistration[] = [];
|
||||
commands: CommandRegistration[] = [];
|
||||
welcomeMenus: WelcomeMenuRegistration[] = [];
|
||||
catalogEntityDetailItems: CatalogEntityDetailRegistration[] = [];
|
||||
topBarItems: TopBarRegistration[] = [];
|
||||
globalPages: registries.PageRegistration[] = [];
|
||||
clusterPages: registries.PageRegistration[] = [];
|
||||
clusterPageMenus: registries.ClusterPageMenuRegistration[] = [];
|
||||
kubeObjectStatusTexts: registries.KubeObjectStatusRegistration[] = [];
|
||||
appPreferences: registries.AppPreferenceRegistration[] = [];
|
||||
entitySettings: registries.EntitySettingRegistration[] = [];
|
||||
statusBarItems: registries.StatusBarRegistration[] = [];
|
||||
kubeObjectDetailItems: registries.KubeObjectDetailRegistration[] = [];
|
||||
kubeObjectMenuItems: registries.KubeObjectMenuRegistration[] = [];
|
||||
kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = [];
|
||||
commands: registries.CommandRegistration[] = [];
|
||||
welcomeMenus: registries.WelcomeMenuRegistration[] = [];
|
||||
catalogEntityDetailItems: registries.CatalogEntityDetailRegistration[] = [];
|
||||
topBarItems: registries.TopBarRegistration[] = [];
|
||||
|
||||
async navigate<P extends object>(pageId?: string, params?: P) {
|
||||
const { navigate } = await import("../renderer/navigation");
|
||||
|
||||
@ -26,23 +26,20 @@ import type { PageTarget, RegisteredPage } from "./page-registry";
|
||||
import type { LensExtension } from "../lens-extension";
|
||||
import { BaseRegistry } from "./base-registry";
|
||||
|
||||
export interface PageMenuRegistration {
|
||||
target?: PageTarget;
|
||||
title: React.ReactNode;
|
||||
components: PageMenuComponents;
|
||||
}
|
||||
|
||||
export interface ClusterPageMenuRegistration extends PageMenuRegistration {
|
||||
export interface ClusterPageMenuRegistration {
|
||||
id?: string;
|
||||
parentId?: string;
|
||||
target?: PageTarget;
|
||||
title: React.ReactNode;
|
||||
components: ClusterPageMenuComponents;
|
||||
}
|
||||
|
||||
export interface PageMenuComponents {
|
||||
export interface ClusterPageMenuComponents {
|
||||
Icon: React.ComponentType<IconProps>;
|
||||
}
|
||||
|
||||
export class PageMenuRegistry<T extends PageMenuRegistration> extends BaseRegistry<T> {
|
||||
add(items: T[], ext: LensExtension) {
|
||||
export class ClusterPageMenuRegistry extends BaseRegistry<ClusterPageMenuRegistration> {
|
||||
add(items: ClusterPageMenuRegistration[], ext: LensExtension) {
|
||||
const normalizedItems = items.map(menuItem => {
|
||||
menuItem.target = {
|
||||
extensionId: ext.name,
|
||||
@ -54,9 +51,7 @@ export class PageMenuRegistry<T extends PageMenuRegistration> extends BaseRegist
|
||||
|
||||
return super.add(normalizedItems);
|
||||
}
|
||||
}
|
||||
|
||||
export class ClusterPageMenuRegistry extends PageMenuRegistry<ClusterPageMenuRegistration> {
|
||||
getRootItems() {
|
||||
return this.getItems().filter((item) => !item.parentId);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ import { appEventBus } from "../common/event-bus";
|
||||
import { ipcMainOn } from "../common/ipc";
|
||||
import { initMenu } from "./menu";
|
||||
import { initTray } from "./tray";
|
||||
import { delay, Singleton } from "../common/utils";
|
||||
import { delay, iter, Singleton } from "../common/utils";
|
||||
import { ClusterFrameInfo, clusterFrameMap } from "../common/cluster-frames";
|
||||
import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
|
||||
import logger from "./logger";
|
||||
@ -38,6 +38,12 @@ function isHideable(window: BrowserWindow | null): boolean {
|
||||
return Boolean(window && !window.isDestroyed());
|
||||
}
|
||||
|
||||
export interface SendToViewArgs {
|
||||
channel: string;
|
||||
frameInfo?: ClusterFrameInfo;
|
||||
data?: any[];
|
||||
}
|
||||
|
||||
export class WindowManager extends Singleton {
|
||||
protected mainWindow: BrowserWindow;
|
||||
protected splashWindow: BrowserWindow;
|
||||
@ -175,7 +181,7 @@ export class WindowManager extends Singleton {
|
||||
return this.mainWindow;
|
||||
}
|
||||
|
||||
sendToView({ channel, frameInfo, data = [] }: { channel: string, frameInfo?: ClusterFrameInfo, data?: any[] }) {
|
||||
private sendToView({ channel, frameInfo, data = [] }: SendToViewArgs) {
|
||||
if (frameInfo) {
|
||||
this.mainWindow.webContents.sendToFrame([frameInfo.processId, frameInfo.frameId], channel, ...data);
|
||||
} else {
|
||||
@ -183,10 +189,22 @@ export class WindowManager extends Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
async navigateExtension(extId: string, pageId?: string, params?: Record<string, any>, frameId?: number) {
|
||||
await this.ensureMainWindow();
|
||||
|
||||
const frameInfo = iter.find(clusterFrameMap.values(), frameInfo => frameInfo.frameId === frameId);
|
||||
|
||||
this.sendToView({
|
||||
channel: "extension:navigate",
|
||||
frameInfo,
|
||||
data: [extId, pageId, params],
|
||||
});
|
||||
}
|
||||
|
||||
async navigate(url: string, frameId?: number) {
|
||||
await this.ensureMainWindow();
|
||||
|
||||
const frameInfo = Array.from(clusterFrameMap.values()).find((frameInfo) => frameInfo.frameId === frameId);
|
||||
const frameInfo = iter.find(clusterFrameMap.values(), frameInfo => frameInfo.frameId === frameId);
|
||||
const channel = frameInfo
|
||||
? IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER
|
||||
: IpcRendererNavigationEvents.NAVIGATE_IN_APP;
|
||||
|
||||
@ -77,6 +77,7 @@ export async function bootstrap(App: AppComponent) {
|
||||
initializers.intiKubeObjectDetailRegistry();
|
||||
initializers.initWelcomeMenuRegistry();
|
||||
initializers.initWorkloadsOverviewDetailRegistry();
|
||||
initializers.initIpcRendererListeners();
|
||||
|
||||
ExtensionLoader.createInstance().init();
|
||||
ExtensionDiscovery.createInstance().init();
|
||||
|
||||
@ -26,3 +26,4 @@ export * from "./kube-object-menu-registry";
|
||||
export * from "./registries";
|
||||
export * from "./welcome-menu-registry";
|
||||
export * from "./workloads-overview-detail-registry";
|
||||
export * from "./ipc";
|
||||
|
||||
30
src/renderer/initializers/ipc.ts
Normal file
30
src/renderer/initializers/ipc.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { ipcRendererOn } from "../../common/ipc";
|
||||
import { ExtensionLoader } from "../../extensions/extension-loader";
|
||||
import type { LensRendererExtension } from "../../extensions/lens-renderer-extension";
|
||||
|
||||
export function initIpcRendererListeners() {
|
||||
ipcRendererOn("extension:navigate", (event, extId: string, pageId ?: string, params?: Record<string, any>) => {
|
||||
ExtensionLoader.getInstance().getInstanceById<LensRendererExtension>(extId).navigate(pageId, params);
|
||||
});
|
||||
}
|
||||
@ -32,7 +32,6 @@ export function initRegistries() {
|
||||
registries.KubeObjectDetailRegistry.createInstance();
|
||||
registries.KubeObjectMenuRegistry.createInstance();
|
||||
registries.KubeObjectStatusRegistry.createInstance();
|
||||
registries.PageMenuRegistry.createInstance();
|
||||
registries.StatusBarRegistry.createInstance();
|
||||
registries.WelcomeMenuRegistry.createInstance();
|
||||
registries.WorkloadsOverviewDetailRegistry.createInstance();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user