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

register status-bar element, base class for extension's registry

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-10-22 14:24:37 +03:00
parent 59ca12ff31
commit 6572fad1c8
11 changed files with 85 additions and 77 deletions

View File

@ -1,6 +1,7 @@
import { LensRendererExtension, Registry } from "@k8slens/extensions";
import { Support } from "./src/support";
import React from "react";
import { Component, LensRendererExtension, Navigation, Registry } from "@k8slens/extensions";
import { supportPageRoute, supportPageURL } from "./src/support.route";
import { Support } from "./src/support";
export default class SupportPageRendererExtension extends LensRendererExtension {
async onActivate() {
@ -19,4 +20,18 @@ export default class SupportPageRendererExtension extends LensRendererExtension
})
)
}
registerStatusBarIcon(registry: Registry.StatusBarRegistry) {
this.disposers.push(
registry.add({
icon: (
<Component.Icon
material="support"
tooltip="Support"
onClick={() => Navigation.navigate(supportPageURL())}
/>
)
})
)
}
}

View File

@ -34,33 +34,33 @@ export class ExtensionLoader {
}
}
loadOnClusterRenderer() {
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer')
this.autoloadExtensions((instance: LensRendererExtension) => {
instance.registerPages(pageRegistry)
})
}
loadOnMainRenderer() {
logger.info('[EXTENSIONS-LOADER]: load on main renderer')
this.autoloadExtensions((instance: LensRendererExtension) => {
instance.registerPages(pageRegistry)
instance.registerAppPreferences(appPreferenceRegistry)
})
}
loadOnMain() {
logger.info('[EXTENSIONS-LOADER]: load on main')
this.autoloadExtensions((instance: LensMainExtension) => {
instance.registerAppMenus(menuRegistry);
instance.registerStatusBarIcon(statusBarRegistry);
})
}
loadOnClusterManagerRenderer() {
logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)')
this.autoloadExtensions((instance: LensRendererExtension) => {
instance.registerPages(pageRegistry)
instance.registerAppPreferences(appPreferenceRegistry)
instance.registerStatusBarIcon(statusBarRegistry)
})
}
loadOnClusterRenderer() {
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)')
this.autoloadExtensions((instance: LensRendererExtension) => {
instance.registerPages(pageRegistry)
})
}
protected autoloadExtensions(callback: (instance: LensExtension) => void) {
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
for (const [id, ext] of installedExtensions) {
let instance = this.instances.get(ext.manifestPath)
let instance = this.instances.get(ext.name)
if (!instance) {
const extensionModule = this.requireExtension(ext)
if (!extensionModule) {
@ -70,7 +70,7 @@ export class ExtensionLoader {
instance = new LensExtensionClass({ ...ext.manifest, manifestPath: ext.manifestPath, id: ext.manifestPath }, ext.manifest);
instance.enable();
callback(instance)
this.instances.set(ext.id, instance)
this.instances.set(ext.name, instance)
}
}
}, {

View File

@ -1,6 +1,7 @@
import { LensExtension } from "./lens-extension"
import type { PageRegistry } from "./registries/page-registry"
import type { AppPreferenceRegistry } from "./registries/app-preference-registry";
import type { StatusBarRegistry } from "./registries";
export class LensRendererExtension extends LensExtension {
registerPages(registry: PageRegistry) {
@ -10,4 +11,8 @@ export class LensRendererExtension extends LensExtension {
registerAppPreferences(registry: AppPreferenceRegistry) {
return
}
registerStatusBarIcon(registry: StatusBarRegistry) {
return
}
}

View File

@ -1,5 +1,5 @@
import { observable } from "mobx"
import React from "react"
import type React from "react"
import { BaseRegistry } from "./base-registry";
export interface AppPreferenceComponents {
Hint: React.ComponentType<any>;
@ -11,17 +11,7 @@ export interface AppPreferenceRegistration {
components: AppPreferenceComponents;
}
export class AppPreferenceRegistry {
preferences = observable.array<AppPreferenceRegistration>([], { deep: false });
add(preference: AppPreferenceRegistration) {
this.preferences.push(preference)
return () => {
this.preferences.replace(
this.preferences.filter(c => c !== preference)
)
};
}
export class AppPreferenceRegistry extends BaseRegistry<AppPreferenceRegistration> {
}
export const appPreferenceRegistry = new AppPreferenceRegistry()

View File

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

View File

@ -1,24 +1,14 @@
// Extensions API -> Global menu customize
// Extensions API -> Global menu customizations
import { observable } from "mobx";
import { MenuItemConstructorOptions } from "electron";
import type { MenuTopId } from "../../main/menu";
import type { MenuItemConstructorOptions } from "electron";
import { BaseRegistry } from "./base-registry";
export interface MenuRegistration extends MenuItemConstructorOptions {
parentId?: MenuTopId;
}
export class MenuRegistry {
protected items = observable.array([], { deep: false });
getItems(): MenuRegistration[] {
return this.items.toJS();
}
add(item: MenuRegistration) {
this.items.push(item);
return () => this.items.remove(item)
}
export class MenuRegistry extends BaseRegistry<MenuRegistration> {
}
export const menuRegistry = new MenuRegistry();

View File

@ -5,7 +5,8 @@ import type { RouteProps } from "react-router";
import type { IconProps } from "../../renderer/components/icon";
import type { IClassName } from "../../renderer/utils";
import type { TabRoute } from "../../renderer/components/layout/tab-layout";
import { computed, observable } from "mobx";
import { BaseRegistry } from "./base-registry";
import { computed } from "mobx";
export enum PageRegistryType {
GLOBAL = "lens-scope",
@ -26,21 +27,13 @@ export interface PageComponents {
MenuIcon?: React.ComponentType<IconProps>;
}
export class PageRegistry {
protected pages = observable.array<PageRegistration>([], { deep: false });
export class PageRegistry extends BaseRegistry<PageRegistration> {
@computed get globalPages() {
return this.pages.filter(page => page.type === PageRegistryType.GLOBAL);
return this.items.filter(page => page.type === PageRegistryType.GLOBAL);
}
@computed get clusterPages() {
return this.pages.filter(page => page.type === PageRegistryType.CLUSTER);
}
// fixme: validate route paths to avoid collisions
add(pageInit: PageRegistration) {
this.pages.push(pageInit);
return () => this.pages.remove(pageInit); // works because of {deep: false};
return this.items.filter(page => page.type === PageRegistryType.CLUSTER);
}
}

View File

@ -1,15 +1,13 @@
// Extensions API -> Status bar customizations
import { observable } from "mobx";
import React from "react";
import { BaseRegistry } from "./base-registry";
export interface StatusBarRegistration {
icon?: React.ReactNode;
}
export class StatusBarRegistry {
items = observable<StatusBarRegistration>([], { deep: false });
add(item: StatusBarRegistration) {
}
export class StatusBarRegistry extends BaseRegistry<StatusBarRegistration> {
}
export const statusBarRegistry = new StatusBarRegistry();

View File

@ -103,7 +103,6 @@ export class Preferences extends React.Component {
render() {
const { preferences } = userStore;
const extensionPreferences = appPreferenceRegistry.preferences;
const header = <h2><Trans>Preferences</Trans></h2>;
return (
<PageLayout showOnTop className="Preferences" header={header}>
@ -170,7 +169,7 @@ export class Preferences extends React.Component {
</small>
<div className="extensions flex column gaps">
{extensionPreferences.map(({ title, components: { Hint, Input } }, index) => {
{appPreferenceRegistry.getItems().map(({ title, components: { Hint, Input } }, index) => {
return (
<div key={index} className="preference">
<h2>{title}</h2>

View File

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { Icon } from "../icon";
import { WorkspaceMenu } from "../+workspaces/workspace-menu";
import { workspaceStore } from "../../../common/workspace-store";
import { navigate } from "../../navigation";
import { statusBarRegistry } from "../../../extensions/registries";
@observer
export class BottomBar extends React.Component {
@ -13,18 +13,19 @@ export class BottomBar extends React.Component {
const { currentWorkspace } = workspaceStore;
return (
<div className="BottomBar flex gaps">
<div id="current-workspace" className="flex gaps align-center box">
<div id="current-workspace" className="flex gaps align-center">
<Icon small material="layers"/>
<span className="workspace-name">{currentWorkspace.name}</span>
</div>
<WorkspaceMenu htmlFor="current-workspace"/>
<Icon
small
material="support"
tooltip="Support"
className="support-icon box right"
onClick={() => navigate("/support")}
<WorkspaceMenu
htmlFor="current-workspace"
/>
<div className="extensions box grow flex gaps justify-flex-end">
{statusBarRegistry.getItems().map(({ icon }, index) => {
if (!icon) return;
return <React.Fragment key={index}>{icon}</React.Fragment>
})}
</div>
</div>
)
}

View File

@ -16,7 +16,7 @@ import { extensionLoader } from "../extensions/extension-loader";
@observer
export class LensApp extends React.Component {
static async init() {
extensionLoader.loadOnMainRenderer();
extensionLoader.loadOnClusterManagerRenderer();
}
render() {