From 3405c496135c18f796c1431af25af4eed6bfe32a Mon Sep 17 00:00:00 2001 From: Roman Date: Sat, 15 May 2021 13:49:13 +0300 Subject: [PATCH] fix: app-crash when navigating to catalog from active cluster-view, refactoring `catalog-entity-store` Signed-off-by: Roman --- .../+catalog/catalog-entity.store.ts | 38 +++----------- src/renderer/components/+catalog/catalog.tsx | 14 ++++-- .../cluster-manager/cluster-view.tsx | 49 +++++++++---------- 3 files changed, 40 insertions(+), 61 deletions(-) diff --git a/src/renderer/components/+catalog/catalog-entity.store.ts b/src/renderer/components/+catalog/catalog-entity.store.ts index 8ae17d9fdd..dd3bead524 100644 --- a/src/renderer/components/+catalog/catalog-entity.store.ts +++ b/src/renderer/components/+catalog/catalog-entity.store.ts @@ -19,11 +19,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { action, autorun, computed, makeObservable, observable } from "mobx"; +import { action, computed, makeObservable } from "mobx"; import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; import { CatalogEntity, CatalogEntityActionContext } from "../../api/catalog-entity"; import { ItemObject, ItemStore } from "../../item.store"; -import { autoBind, disposer } from "../../utils"; import { CatalogCategory } from "../../../common/catalog"; export class CatalogEntityItem implements ItemObject { @@ -87,43 +86,20 @@ export class CatalogEntityItem implements ItemObject { } export class CatalogEntityStore extends ItemStore { - dispose = disposer(); - @observable.ref activeCategory?: CatalogCategory; - - constructor() { - super(); - - makeObservable(this); - autoBind(this); - this.bindAutoLoading(); - } - - @computed get entities() { - if (!this.activeCategory) { + getEntities(category?: CatalogCategory): CatalogEntityItem[] { + if (!category) { return catalogEntityRegistry.items.map(entity => new CatalogEntityItem(entity)); } - return catalogEntityRegistry.getItemsForCategory(this.activeCategory).map(entity => new CatalogEntityItem(entity)); + return catalogEntityRegistry.getItemsForCategory(category) + .map(entity => new CatalogEntityItem(entity)); } - protected bindAutoLoading() { - const disposer = autorun(() => { - this.loadItem(this.activeCategory); // preload active category - this.loadItems(this.entities); // preload all available entities - }); - - this.dispose.push(disposer); - } - - async loadItem(category: CatalogCategory): Promise { - return super.loadItem(() => category); - } - - async loadItems(entities: CatalogEntityItem[] = []) { + async loadItems(entities: CatalogEntityItem[]) { return super.loadItems(() => entities); } async loadAll() { - return this.loadItems(); + return this.loadItems(this.getEntities()); } } diff --git a/src/renderer/components/+catalog/catalog.tsx b/src/renderer/components/+catalog/catalog.tsx index 1f3c020b10..3d1487f48c 100644 --- a/src/renderer/components/+catalog/catalog.tsx +++ b/src/renderer/components/+catalog/catalog.tsx @@ -23,7 +23,7 @@ import "./catalog.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { ItemListLayout } from "../item-object-list"; -import { autorun, computed, makeObservable, observable } from "mobx"; +import { computed, makeObservable, observable, reaction } from "mobx"; import { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store"; import { navigate } from "../../navigation"; import { kebabCase } from "lodash"; @@ -64,6 +64,10 @@ export class Catalog extends React.Component { return catalogCategoryRegistry.items; } + @computed get items(): CatalogEntityItem[] { + return this.catalogEntityStore.getEntities(this.activeCategory); + } + constructor(props: {}) { super(props); makeObservable(this); @@ -71,10 +75,10 @@ export class Catalog extends React.Component { componentDidMount() { disposeOnUnmount(this, [ - () => this.catalogEntityStore.dispose(), // stop all events, loaders, etc. - autorun(() => { - this.catalogEntityStore.activeCategory = this.activeCategory; // sync - }), + // autofill catalog entities into store + reaction(() => this.items, items => this.catalogEntityStore.loadItems(items), { + fireImmediately: true, + }) ]); } diff --git a/src/renderer/components/cluster-manager/cluster-view.tsx b/src/renderer/components/cluster-manager/cluster-view.tsx index c36358d0c8..6717b86ebc 100644 --- a/src/renderer/components/cluster-manager/cluster-view.tsx +++ b/src/renderer/components/cluster-manager/cluster-view.tsx @@ -24,7 +24,7 @@ import React from "react"; import { computed, makeObservable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { ClusterStatus } from "./cluster-status"; -import { initView, lensViews, refreshViews } from "./lens-views"; +import { hasLoadedView, initView, refreshViews } from "./lens-views"; import { Cluster } from "../../../main/cluster"; import { ClusterStore } from "../../../common/cluster-store"; import { requestMain } from "../../../common/ipc"; @@ -43,50 +43,49 @@ export class ClusterView extends React.Component { return getMatchedClusterId(); } - @computed get cluster(): Cluster { + @computed get cluster(): Cluster | undefined { return ClusterStore.getInstance().getById(this.clusterId); } @computed get isReady(): boolean { const { cluster, clusterId } = this; - return [ - cluster?.available, - cluster?.ready, - lensViews.get(clusterId)?.isLoaded, // cluster's iframe is loaded & ready - ].every(Boolean); + return cluster?.ready && cluster?.available && hasLoadedView(clusterId); } componentDidMount() { + this.bindEvents(); + } + + bindEvents() { disposeOnUnmount(this, [ - reaction(() => this.isReady, () => this.refreshViews(), { - fireImmediately: true + reaction(() => this.clusterId, clusterId => { + initView(clusterId); // init cluster-view (iframe), requires parent container #lens-views to be in DOM + requestMain(clusterActivateHandler, clusterId, false); // activate and fetch cluster's state from main + catalogEntityRegistry.activeEntity = catalogEntityRegistry.getById(clusterId); + }, { + fireImmediately: true, + }), + + // show cluster's iframe when ready/connected + reaction(() => this.isReady, () => refreshViews(this.clusterId), { + fireImmediately: true, }), ]); } - /** - * Refresh cluster-views (iframes) visibility and catalog's active entity. - */ - refreshViews(clusterId = this.clusterId) { - try { - initView(clusterId); - requestMain(clusterActivateHandler, clusterId, false); - refreshViews(clusterId); - catalogEntityRegistry.activeEntity = catalogEntityRegistry.getById(clusterId); - } catch (error) { - console.error(`refreshing cluster-view: ${error}`); + renderStatus() { + const { clusterId, cluster, isReady } = this; + + if (cluster && !isReady) { + return ; } } render() { - const { clusterId, isReady } = this; - return (
- {!isReady && ( - - )} + {this.renderStatus()}
); }