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

Fix cluster view closing sometimes

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-07-27 15:49:06 -04:00
parent c426eb9899
commit b86b118e3e
6 changed files with 67 additions and 45 deletions

View File

@ -91,7 +91,7 @@ export class KubernetesCluster extends CatalogEntity<KubernetesClusterMetadata,
} }
async onRun() { async onRun() {
requestMain(navigateToClusterHandler, this.getId()); await requestMain(navigateToClusterHandler, this.getId());
} }
onDetailsOpen(): void { onDetailsOpen(): void {

View File

@ -36,6 +36,20 @@ export class ClusterFrames extends Singleton {
return [...this.mapping.values()]; return [...this.mapping.values()];
} }
public getClusterIdFromFrameInfo(query: ClusterFrameInfo): ClusterId | undefined {
for (const [clusterId, info] of this.mapping) {
if (
info.frameId === query.frameId
&& info.processId === query.processId
&& info.windowId === query.windowId
) {
return clusterId;
}
}
return undefined;
}
public set(clusterId: ClusterId, info: ClusterFrameInfo): void { public set(clusterId: ClusterId, info: ClusterFrameInfo): void {
this.mapping.set(clusterId, info); this.mapping.set(clusterId, info);
} }

View File

@ -109,6 +109,22 @@ export function* filter<T>(src: Iterable<T>, fn: (from: T) => any): Iterable<T>
} }
} }
/**
* Creates a new iterator that iterates (lazily) over its input and yields the
* items that are not `null` or `undefined` value from `fn`.
* @param src A type that can be iterated over
* @param fn The function that is called for each value
*/
export function* keepDefined<T>(src: Iterable<T | undefined | null>): Iterable<T> {
for (const from of src) {
if (from === null || from === undefined) {
continue;
}
yield from;
}
}
/** /**
* Creates a new iterator that iterates (lazily) over its input and yields the * Creates a new iterator that iterates (lazily) over its input and yields the
* result of `fn` when it is `truthy` * result of `fn` when it is `truthy`

View File

@ -22,7 +22,7 @@
import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron"; import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron";
import windowStateKeeper from "electron-window-state"; import windowStateKeeper from "electron-window-state";
import { appEventBus } from "../common/event-bus"; import { appEventBus } from "../common/event-bus";
import { delay, iter, Singleton, toJS } from "../common/utils"; import { delay, iter, Singleton } from "../common/utils";
import { ClusterFrameInfo, ClusterFrames } from "../common/cluster-frames"; import { ClusterFrameInfo, ClusterFrames } from "../common/cluster-frames";
import { IpcRendererNavigationEvents } from "../renderer/navigation/events"; import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
import logger from "./logger"; import logger from "./logger";
@ -42,7 +42,7 @@ export interface SendToViewArgs {
export interface NavigateFrameInfoSpecifier { export interface NavigateFrameInfoSpecifier {
windowId?: number; windowId?: number;
clusterId?: number; clusterId?: string;
frameId?: number; frameId?: number;
} }
@ -237,49 +237,39 @@ export class WindowManager extends Singleton {
* @param specifics The fallback options for specifying a target * @param specifics The fallback options for specifying a target
*/ */
private getNavigateTarget(specifics: NavigateFrameInfoSpecifier[]): [ClusterFrameInfo | undefined, number | undefined] { private getNavigateTarget(specifics: NavigateFrameInfoSpecifier[]): [ClusterFrameInfo | undefined, number | undefined] {
function helper(): ClusterFrameInfo | undefined | number { function* helper(): Iterable<ClusterFrameInfo | number | undefined> {
const clusterFrames = ClusterFrames.getInstance(); const clusterFrames = ClusterFrames.getInstance();
for (const fallback of specifics) { for (const fallback of specifics) {
if (typeof fallback.clusterId === "string") { if (typeof fallback.clusterId === "string") {
const res = clusterFrames.getFrameInfoByClusterId(fallback.clusterId); yield clusterFrames.getFrameInfoByClusterId(fallback.clusterId);
continue;
if (res == null) { // intentional
return res;
} else {
continue;
}
} }
if (typeof fallback.frameId === "number") { if (typeof fallback.frameId === "number") {
const res = clusterFrames.getFrameInfoByFrameId(fallback.frameId); yield clusterFrames.getFrameInfoByFrameId(fallback.frameId);
continue;
if (res == null) { // intentional
return res;
} else {
continue;
}
} }
if (typeof fallback.windowId === "number") { if (typeof fallback.windowId === "number") {
return fallback.windowId; yield fallback.windowId;
} }
} }
return undefined; return undefined;
} }
const target = helper(); const target = iter.first(iter.keepDefined(helper()));
if (target == null) { // intentional
return [undefined, undefined];
}
if (typeof target === "number") { if (typeof target === "number") {
return [undefined, target]; return [undefined, target];
} }
return [target, target.windowId]; if (target) {
return [target, target.windowId];
}
return [undefined, undefined];
} }
/** /**
@ -289,18 +279,26 @@ export class WindowManager extends Singleton {
*/ */
async navigate(url: string, ...specifics: NavigateFrameInfoSpecifier[]): Promise<void> { async navigate(url: string, ...specifics: NavigateFrameInfoSpecifier[]): Promise<void> {
const [frameInfo, windowId] = this.getNavigateTarget(specifics); const [frameInfo, windowId] = this.getNavigateTarget(specifics);
console.log("[WINDOW-MANAGER]: navigate to", url, "with", specifics, toJS(frameInfo), { windowId });
const browserWindow = await this.ensureWindow(windowId); const browserWindow = await this.ensureWindow(windowId);
const channel = frameInfo const channel = frameInfo
? IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER ? IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER
: IpcRendererNavigationEvents.NAVIGATE_IN_APP; : IpcRendererNavigationEvents.NAVIGATE_IN_APP;
const clusterId = frameInfo
? ClusterFrames.getInstance().getClusterIdFromFrameInfo(frameInfo)
: undefined;
this.sendToView(browserWindow, { if (clusterId && url.startsWith(`/cluster/${clusterId}`)) {
channel, this.sendToView(browserWindow, {
frameInfo, channel: IpcRendererNavigationEvents.NAVIGATE_IN_APP,
data: [url], data: [url],
}); });
} else {
this.sendToView(browserWindow, {
channel,
frameInfo,
data: [url],
});
}
} }
reload() { reload() {

View File

@ -63,15 +63,6 @@ export class ClusterView extends React.Component<Props> {
} }
componentDidMount() { componentDidMount() {
this.bindEvents();
}
componentWillUnmount() {
refreshViews();
catalogEntityRegistry.activeEntity = null;
}
bindEvents() {
disposeOnUnmount(this, [ disposeOnUnmount(this, [
reaction(() => this.clusterId, async (clusterId) => { reaction(() => this.clusterId, async (clusterId) => {
refreshViews(clusterId); // refresh visibility of active cluster refreshViews(clusterId); // refresh visibility of active cluster
@ -82,9 +73,7 @@ export class ClusterView extends React.Component<Props> {
fireImmediately: true, fireImmediately: true,
}), }),
reaction(() => [this.cluster?.ready, this.cluster?.disconnected], (values) => { reaction(() => [this.cluster?.ready, this.cluster?.disconnected], ([, disconnected]) => {
const disconnected = values[1];
if (hasLoadedView(this.clusterId) && disconnected) { if (hasLoadedView(this.clusterId) && disconnected) {
navigate(`${catalogURL()}/${previousActiveTab.get()}`); // redirect to catalog when active cluster get disconnected/not available navigate(`${catalogURL()}/${previousActiveTab.get()}`); // redirect to catalog when active cluster get disconnected/not available
} }
@ -92,6 +81,11 @@ export class ClusterView extends React.Component<Props> {
]); ]);
} }
componentWillUnmount() {
refreshViews();
catalogEntityRegistry.activeEntity = null;
}
renderStatus(): React.ReactNode { renderStatus(): React.ReactNode {
const { clusterId, cluster, isReady } = this; const { clusterId, cluster, isReady } = this;

View File

@ -86,7 +86,7 @@ export async function autoCleanOnRemove(clusterId: ClusterId, iframe: HTMLIFrame
} }
export function refreshViews(visibleClusterId?: string) { export function refreshViews(visibleClusterId?: string) {
logger.info(`[LENS-VIEW]: refreshing iframe views, visible cluster id=${visibleClusterId}`); console.info(`[LENS-VIEW]: refreshing iframe views, visible cluster id=${visibleClusterId}`);
const cluster = ClusterStore.getInstance().getById(visibleClusterId); const cluster = ClusterStore.getInstance().getById(visibleClusterId);
lensViews.forEach(({ clusterId, view, isLoaded }) => { lensViews.forEach(({ clusterId, view, isLoaded }) => {