mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make base store non Singleton (#6690)
* Remove Singleton from BaseStore to remove global shared state Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove more usages of Singleton Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace use of legacy global execHelm with injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove last use of legacy global execHelm Signed-off-by: Sebastian Malton <sebastian@malton.name> * Extract BaseStore deps into constructor argument Signed-off-by: Sebastian Malton <sebastian@malton.name> * Introduce method to make store migrations injectable - Use it for ClusterStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch HotbarStore to injectable migrations Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch UserStore to injectable migrations Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move migration utils into common/utils/ Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch WeblinkStore to injectable migrations Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove dead code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type error in base-store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove tests that reference lastSeenVersion - That value is not used anywhere in code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usage of legacy global .getInstance Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove usage of legacy global ClusterStore.getInstance Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add simple migrations dependency for stores without any preexisting migrations Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix messed up import Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add typing to transient injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Cleanup formatting Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix typing in tests to satisfy requirement to have cacheFile Signed-off-by: Sebastian Malton <sebastian@malton.name> * More consistent use of BaseStore.displayName Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add catching of error while starting main application Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move initializing sentry to runnable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unneeded appPathsInjectionToken - Only had once impl, which was in common anyway Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add support for multiple "runAfter" runnables - Needed so that several dependencies can be declared Signed-off-by: Sebastian Malton <sebastian@malton.name> * Use multiple runAfter support to fix crash on renderer Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove traces Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override to fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix base store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix runManyFor tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix hotbar store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix user store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override for getConfigurationFileModel to fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove overrides for configuration stores - Now that there is an override for getConfiguration Signed-off-by: Sebastian Malton <sebastian@malton.name> * Overhaul FS fakes with full in-memory filesystem - This increases our confidence in fs related logic Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove use of global shared Electron.App Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add fake access support Signed-off-by: Sebastian Malton <sebastian@malton.name> * Handle copy as part of fake FS Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add ensureDir/Sync support to fake FS Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type error Signed-off-by: Sebastian Malton <sebastian@malton.name> * Use pathExistsSync instead of fsInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add createReadStream to fake FS Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add stat to fake FS Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove dead code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix test failures due to incomplete overrides Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fully injectable-ize BaseStore so that ApplicationBuilder tests work Signed-off-by: Sebastian Malton <sebastian@malton.name> * Consolidate more bootstrapping into startFrame Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move initializing CatalogCategories to runnable in bootstrap Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert contextMenuOpen initializers into runnables Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert navigateForExtension init to runnable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make cluster state sync fully injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move init hotbar store into runnables Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make LensTheme fully injectable and runnable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Cleanup old code from missed from previous commit Signed-off-by: Sebastian Malton <sebastian@malton.name> * Manually split out terminal color names and fully type LensTheme Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix old imports Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unnecessart awaits Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove dead code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fully cherry pick injectablizing custom monaco themes Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix duplicate mock warning Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix incorrectly fully cherry picking new runnable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Complete cherry-pick of current cluster injcetablization Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix override file name Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix injecting before app paths are set up Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix injecting before app paths are set up Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix ordering of runnable and order of injection Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert all renderer runnables to late-inject style - To help fix issues around injection time Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix react-beautiful-dnd mocks Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update and fix WriteJson(Sync) to fix error in tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix HotbarStore.load being called twice is being buggy Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update listing-active-helm-repositories-in-preferences snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix sidebar-and-tab-navigation-tests - Move enabling extensions in tests to a proper location - Fix flushing promises Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove props from dnd mock to make snapshot diffs smaller Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix import Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests by overriding things that are no longer overriden by default - NOTE: They are overridden when using ApplicationBuilder Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix hotbar store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix cluster store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix extension-loader tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix extension-discovery tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix cluster-role-dialog tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix user store tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix kubeconfig sync tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix sidebar and tab tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unused code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix pick paths import type error and simplify signature Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type error in legacy ipc registration Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove another use of legacy requestOpenPathPicker Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace use of legacy global PathPicker.Pick Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix usage in light of changed prop names Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix catalog tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix more type errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix test flakiness by removing side effects from userStore preferences Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix loading Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type error Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix crash Signed-off-by: Sebastian Malton <sebastian@malton.name> * Cherry pick updated startFrameInjectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add tests to verify runMany behaviour in new possible incorrect configuration Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix init ordering during start frame Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix cluster state sync Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots after removing side-effects Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add override for technical test Signed-off-by: Sebastian Malton <sebastian@malton.name> * Correctly mark currentlyInClusterFrame as causedSideEffects Signed-off-by: Sebastian Malton <sebastian@malton.name> * Better formatting Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix behaviour regression Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add better logging Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix BaseStore sync Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update last snapshot Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add global override for randomBytes Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make startMainApplication not an injection time side effect Signed-off-by: Sebastian Malton <sebastian@malton.name> * Choose better names for start-frame runnable tokens Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove duplication of code in RunManyFor Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add unit tests and fix handling empty runAfter array Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace use of mobx from runManyFor with custom barrier Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add missing test Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
7c5faaaf1d
commit
25f37ac1d1
364 files changed
+10035
-5246
No files matched your search
@@ -13,6 +13,7 @@ import type { CategoryColumns, GetCategoryColumnsParams } from "../columns/get.i
|
||||
import getCategoryColumnsInjectable from "../columns/get.injectable";
|
||||
import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
|
||||
import extensionInjectable from "../../../../extensions/extension-loader/extension/extension.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../../../routes/currently-in-cluster-frame.injectable";
|
||||
|
||||
class TestCategory extends CatalogCategory {
|
||||
apiVersion = "catalog.k8slens.dev/v1alpha1";
|
||||
@@ -46,6 +47,8 @@ describe("Custom Category Columns", () => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(hotbarStoreInjectable, () => ({}));
|
||||
di.override(currentlyInClusterFrameInjectable, () => false);
|
||||
|
||||
getCategoryColumns = di.inject(getCategoryColumnsInjectable);
|
||||
});
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.in
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import { flushPromises } from "../../../common/test-utils/flush-promises";
|
||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||
import releaseChannelInjectable from "../../../common/vars/release-channel.injectable";
|
||||
import defaultUpdateChannelInjectable from "../../../features/application-update/common/selected-update-channel/default-update-channel.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../../routes/currently-in-cluster-frame.injectable";
|
||||
|
||||
class MockCatalogEntity extends CatalogEntity {
|
||||
public apiVersion = "api";
|
||||
@@ -61,11 +65,11 @@ describe("<Catalog />", () => {
|
||||
let catalogEntityItem: MockCatalogEntity;
|
||||
let render: DiRender;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
|
||||
di.override(currentlyInClusterFrameInjectable, () => false);
|
||||
di.override(broadcastMessageInjectable, () => async () => {});
|
||||
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
@@ -82,6 +86,13 @@ describe("<Catalog />", () => {
|
||||
Object.assign(catalogEntityStore, {
|
||||
selectedItem: computed(() => catalogEntityItem),
|
||||
});
|
||||
|
||||
di.override(releaseChannelInjectable, () => ({
|
||||
get: () => "latest" as const,
|
||||
init: async () => {},
|
||||
}));
|
||||
await di.inject(defaultUpdateChannelInjectable).init();
|
||||
di.inject(userStoreInjectable).load();
|
||||
});
|
||||
|
||||
describe("can use catalogEntityRegistry.addOnBeforeRun to add hooks for catalog entities", () => {
|
||||
|
||||
@@ -27,7 +27,7 @@ import type { PageParam } from "../../navigation";
|
||||
import type { ToggleKubeDetailsPane } from "../kube-detail-params/toggle-details.injectable";
|
||||
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
|
||||
import toggleKubeDetailsPaneInjectable from "../kube-detail-params/toggle-details.injectable";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
|
||||
export interface ClusterIssuesProps {
|
||||
|
||||
@@ -16,7 +16,7 @@ import type { PieChartData } from "../chart";
|
||||
import { PieChart } from "../chart";
|
||||
import { ClusterNoMetrics } from "./cluster-no-metrics";
|
||||
import { bytesToUnits, cssNames } from "../../utils";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { getMetricLastPoints } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import clusterOverviewStoreInjectable from "./cluster-overview-store/cluster-overview-store.injectable";
|
||||
|
||||
@@ -23,12 +23,13 @@ import installExtensionFromInputInjectable from "../install-extension-from-input
|
||||
import type { ExtensionInstallationStateStore } from "../../../../extensions/extension-installation-state-store/extension-installation-state-store";
|
||||
import extensionInstallationStateStoreInjectable from "../../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import { observable, when } from "mobx";
|
||||
import type { DeleteFile } from "../../../../common/fs/delete-file.injectable";
|
||||
import deleteFileInjectable from "../../../../common/fs/delete-file.injectable";
|
||||
import type { RemovePath } from "../../../../common/fs/remove.injectable";
|
||||
import removePathInjectable from "../../../../common/fs/remove.injectable";
|
||||
import type { DownloadJson } from "../../../../common/fetch/download-json.injectable";
|
||||
import type { DownloadBinary } from "../../../../common/fetch/download-binary.injectable";
|
||||
import downloadJsonInjectable from "../../../../common/fetch/download-json.injectable";
|
||||
import downloadBinaryInjectable from "../../../../common/fetch/download-binary.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../../../routes/currently-in-cluster-frame.injectable";
|
||||
|
||||
describe("Extensions", () => {
|
||||
let extensionLoader: ExtensionLoader;
|
||||
@@ -36,7 +37,7 @@ describe("Extensions", () => {
|
||||
let installExtensionFromInput: jest.MockedFunction<InstallExtensionFromInput>;
|
||||
let extensionInstallationStateStore: ExtensionInstallationStateStore;
|
||||
let render: DiRender;
|
||||
let deleteFileMock: jest.MockedFunction<DeleteFile>;
|
||||
let deleteFileMock: jest.MockedFunction<RemovePath>;
|
||||
let downloadJson: jest.MockedFunction<DownloadJson>;
|
||||
let downloadBinary: jest.MockedFunction<DownloadBinary>;
|
||||
|
||||
@@ -45,6 +46,7 @@ describe("Extensions", () => {
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(directoryForDownloadsInjectable, () => "some-directory-for-downloads");
|
||||
di.override(currentlyInClusterFrameInjectable, () => false);
|
||||
|
||||
render = renderFor(di);
|
||||
|
||||
@@ -52,7 +54,7 @@ describe("Extensions", () => {
|
||||
di.override(installExtensionFromInputInjectable, () => installExtensionFromInput);
|
||||
|
||||
deleteFileMock = jest.fn();
|
||||
di.override(deleteFileInjectable, () => deleteFileMock);
|
||||
di.override(removePathInjectable, () => deleteFileMock);
|
||||
|
||||
downloadJson = jest.fn().mockImplementation((url) => { throw new Error(`Unexpected call to downloadJson for url=${url}`); });
|
||||
di.override(downloadJsonInjectable, () => downloadJson);
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import {
|
||||
getInjectable,
|
||||
} from "@ogre-tools/injectable";
|
||||
import { UserStore } from "../../../../common/user-store";
|
||||
import { getBaseRegistryUrl } from "./get-base-registry-url";
|
||||
|
||||
const getBaseRegistryUrlInjectable = getInjectable({
|
||||
id: "get-base-registry-url",
|
||||
|
||||
instantiate: () => getBaseRegistryUrl({
|
||||
// TODO: use injection
|
||||
getRegistryUrlPreference: () => UserStore.getInstance().extensionRegistryUrl,
|
||||
}),
|
||||
});
|
||||
|
||||
export default getBaseRegistryUrlInjectable;
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import React from "react";
|
||||
import execFileInjectable from "../../../../common/fs/exec-file.injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import { defaultExtensionRegistryUrl } from "../../../../common/user-store/preferences-helpers";
|
||||
import userStoreInjectable from "../../../../common/user-store/user-store.injectable";
|
||||
import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable";
|
||||
|
||||
const getBaseRegistryUrlInjectable = getInjectable({
|
||||
id: "get-base-registry-url",
|
||||
|
||||
instantiate: (di) => {
|
||||
const { extensionRegistryUrl } = di.inject(userStoreInjectable);
|
||||
const showErrorNotification = di.inject(showErrorNotificationInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const execFile = di.inject(execFileInjectable);
|
||||
|
||||
return async () => {
|
||||
switch (extensionRegistryUrl.location) {
|
||||
case "custom":
|
||||
return extensionRegistryUrl.customUrl;
|
||||
|
||||
case "npmrc": {
|
||||
const filteredEnv = Object.fromEntries(
|
||||
Object.entries(process.env)
|
||||
.filter(([key]) => !key.startsWith("npm")),
|
||||
);
|
||||
const result = await execFile("npm", ["config", "get", "registry"], { env: filteredEnv });
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response.trim();
|
||||
}
|
||||
|
||||
showErrorNotification((
|
||||
<p>
|
||||
Failed to get configured registry from
|
||||
<code>.npmrc</code>
|
||||
. Falling back to default registry.
|
||||
</p>
|
||||
));
|
||||
logger.warn("[EXTENSIONS]: failed to get configured registry from .npmrc", result.error);
|
||||
}
|
||||
|
||||
// fallthrough
|
||||
default:
|
||||
case "default":
|
||||
return defaultExtensionRegistryUrl;
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default getBaseRegistryUrlInjectable;
|
||||
@@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import type { ExtensionRegistry } from "../../../../common/user-store/preferences-helpers";
|
||||
import { defaultExtensionRegistryUrl } from "../../../../common/user-store/preferences-helpers";
|
||||
import { promiseExecFile } from "../../../utils";
|
||||
import { Notifications } from "../../notifications";
|
||||
|
||||
interface Dependencies {
|
||||
getRegistryUrlPreference: () => ExtensionRegistry;
|
||||
}
|
||||
|
||||
export const getBaseRegistryUrl = ({ getRegistryUrlPreference }: Dependencies) => async () => {
|
||||
const extensionRegistryUrl = getRegistryUrlPreference();
|
||||
|
||||
switch (extensionRegistryUrl.location) {
|
||||
case "custom":
|
||||
return extensionRegistryUrl.customUrl;
|
||||
|
||||
case "npmrc": {
|
||||
try {
|
||||
const filteredEnv = Object.fromEntries(
|
||||
Object.entries(process.env)
|
||||
.filter(([key]) => !key.startsWith("npm")),
|
||||
);
|
||||
const { stdout } = await promiseExecFile("npm", ["config", "get", "registry"], { env: filteredEnv });
|
||||
|
||||
return stdout.trim();
|
||||
} catch (error) {
|
||||
Notifications.error((
|
||||
<p>
|
||||
Failed to get configured registry from
|
||||
<code>.npmrc</code>
|
||||
. Falling back to default registry.
|
||||
</p>
|
||||
));
|
||||
console.warn("[EXTENSIONS]: failed to get configured registry from .npmrc", error);
|
||||
}
|
||||
}
|
||||
|
||||
// fallthrough
|
||||
default:
|
||||
case "default":
|
||||
return defaultExtensionRegistryUrl;
|
||||
}
|
||||
};
|
||||
@@ -3,37 +3,30 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { requestOpenFilePickingDialog } from "../../ipc";
|
||||
import { supportedExtensionFormats } from "./supported-extension-formats";
|
||||
import attemptInstallsInjectable from "./attempt-installs.injectable";
|
||||
import directoryForDownloadsInjectable from "../../../common/app-paths/directory-for-downloads/directory-for-downloads.injectable";
|
||||
import openPathPickingDialogInjectable from "../../../features/path-picking-dialog/renderer/pick-paths.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
attemptInstalls: (filePaths: string[]) => Promise<void>;
|
||||
directoryForDownloads: string;
|
||||
}
|
||||
|
||||
const installFromSelectFileDialog = ({ attemptInstalls, directoryForDownloads }: Dependencies) => async () => {
|
||||
const { canceled, filePaths } = await requestOpenFilePickingDialog({
|
||||
defaultPath: directoryForDownloads,
|
||||
properties: ["openFile", "multiSelections"],
|
||||
message: `Select extensions to install (formats: ${supportedExtensionFormats.join(", ")}), `,
|
||||
buttonLabel: "Use configuration",
|
||||
filters: [{ name: "tarball", extensions: supportedExtensionFormats }],
|
||||
});
|
||||
|
||||
if (!canceled) {
|
||||
await attemptInstalls(filePaths);
|
||||
}
|
||||
};
|
||||
export type InstallFromSelectFileDialog = () => Promise<void>;
|
||||
|
||||
const installFromSelectFileDialogInjectable = getInjectable({
|
||||
id: "install-from-select-file-dialog",
|
||||
|
||||
instantiate: (di) => installFromSelectFileDialog({
|
||||
attemptInstalls: di.inject(attemptInstallsInjectable),
|
||||
directoryForDownloads: di.inject(directoryForDownloadsInjectable),
|
||||
}),
|
||||
instantiate: (di): InstallFromSelectFileDialog => {
|
||||
const attemptInstalls = di.inject(attemptInstallsInjectable);
|
||||
const directoryForDownloads = di.inject(directoryForDownloadsInjectable);
|
||||
const openPathPickingDialog = di.inject(openPathPickingDialogInjectable);
|
||||
|
||||
return () => openPathPickingDialog({
|
||||
defaultPath: directoryForDownloads,
|
||||
properties: ["openFile", "multiSelections"],
|
||||
message: `Select extensions to install (formats: ${supportedExtensionFormats.join(", ")}), `,
|
||||
buttonLabel: "Use configuration",
|
||||
filters: [{ name: "tarball", extensions: supportedExtensionFormats }],
|
||||
onPick: attemptInstalls,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default installFromSelectFileDialogInjectable;
|
||||
+1
-1
@@ -8,7 +8,7 @@ import { runInAction, action, observable, computed } from "mobx";
|
||||
import type { TargetHelmRelease } from "../target-helm-release.injectable";
|
||||
import type { RequestDetailedHelmRelease, DetailedHelmRelease } from "./request-detailed-helm-release.injectable";
|
||||
import requestDetailedHelmReleaseInjectable from "./request-detailed-helm-release.injectable";
|
||||
import type { LensTheme } from "../../../../themes/store";
|
||||
import type { LensTheme } from "../../../../themes/lens-theme";
|
||||
import type { RequestHelmReleaseConfiguration } from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
|
||||
import requestHelmReleaseConfigurationInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ResourceMetricsContext } from "../resource-metrics";
|
||||
import { observer } from "mobx-react";
|
||||
import { mapValues } from "lodash";
|
||||
import { type MetricsTab, metricTabOptions } from "../chart/options";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { BarChart, memoryOptions } from "../chart";
|
||||
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
import { ResourceMetricsContext } from "../resource-metrics";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ import type { DiRender } from "../../../test-utils/renderFor";
|
||||
import { renderFor } from "../../../test-utils/renderFor";
|
||||
import clusterRoleStoreInjectable from "../../+cluster-roles/store.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../../stores-apis-can-be-created.injectable";
|
||||
import directoryForUserDataInjectable from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
describe("ClusterRoleBindingDialog tests", () => {
|
||||
let render: DiRender;
|
||||
@@ -20,6 +21,7 @@ describe("ClusterRoleBindingDialog tests", () => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
di.override(directoryForUserDataInjectable, () => "/some-path-for-user-data");
|
||||
|
||||
render = renderFor(di);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import rendererExtensionsInjectable from "../../../../extensions/renderer-extensions.injectable";
|
||||
import { LensRendererExtension } from "../../../../extensions/lens-renderer-extension";
|
||||
import type { WelcomeBannerRegistration } from "../welcome-banner-items/welcome-banner-registration";
|
||||
import currentlyInClusterFrameInjectable from "../../../routes/currently-in-cluster-frame.injectable";
|
||||
|
||||
jest.mock("electron", () => ({
|
||||
ipcRenderer: {
|
||||
@@ -32,6 +33,9 @@ describe("<Welcome/>", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(currentlyInClusterFrameInjectable, () => false);
|
||||
|
||||
render = renderFor(di);
|
||||
welcomeBannersStub = [];
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { observer } from "mobx-react";
|
||||
import type { PieChartData } from "../chart";
|
||||
import { PieChart } from "../chart";
|
||||
import { object } from "../../utils";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { PascalCase } from "type-fest";
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { BarChart } from "../chart";
|
||||
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
import { ResourceMetricsContext } from "../resource-metrics";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { mapValues } from "lodash";
|
||||
import { type MetricsTab, metricTabOptions } from "../chart/options";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
@tailwind utilities;
|
||||
|
||||
@import "./flexbox";
|
||||
@import "../themes/theme-vars";
|
||||
@import "./fonts";
|
||||
|
||||
:root {
|
||||
|
||||
@@ -7,13 +7,15 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Input } from "../input";
|
||||
import { isUrl } from "../input/input_validators";
|
||||
import { WeblinkStore } from "../../../common/weblink-store";
|
||||
import type { WeblinkStore } from "../../../common/weblinks-store/weblink-store";
|
||||
import { computed, makeObservable, observable } from "mobx";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
|
||||
import weblinkStoreInjectable from "../../../common/weblinks-store/weblink-store.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
closeCommandOverlay: () => void;
|
||||
weblinkStore: WeblinkStore;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +42,7 @@ class NonInjectedWeblinkAddCommand extends React.Component<Dependencies> {
|
||||
}
|
||||
|
||||
onSubmit(name: string) {
|
||||
WeblinkStore.getInstance().add({
|
||||
this.props.weblinkStore.add({
|
||||
name: name || this.url,
|
||||
url: this.url,
|
||||
});
|
||||
@@ -64,7 +66,7 @@ class NonInjectedWeblinkAddCommand extends React.Component<Dependencies> {
|
||||
value={this.url}
|
||||
onChange={(v) => this.onChangeUrl(v)}
|
||||
onSubmit={(v) => this.onSubmitUrl(v)}
|
||||
showValidationLine={true}
|
||||
showValidationLine={true}
|
||||
/>
|
||||
{ this.nameHidden && (
|
||||
<small className="hint">
|
||||
@@ -93,7 +95,8 @@ class NonInjectedWeblinkAddCommand extends React.Component<Dependencies> {
|
||||
|
||||
export const WeblinkAddCommand = withInjectables<Dependencies>(NonInjectedWeblinkAddCommand, {
|
||||
getProps: (di, props) => ({
|
||||
closeCommandOverlay: di.inject(commandOverlayInjectable).close,
|
||||
...props,
|
||||
closeCommandOverlay: di.inject(commandOverlayInjectable).close,
|
||||
weblinkStore: di.inject(weblinkStoreInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -13,7 +13,7 @@ import type { ChartProps } from "./chart";
|
||||
import { Chart, ChartKind } from "./chart";
|
||||
import { bytesToUnits, cssNames, isObject } from "../../utils";
|
||||
import { ZebraStripesPlugin } from "./zebra-stripes.plugin";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
import assert from "assert";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
|
||||
@@ -11,7 +11,7 @@ import ChartJS from "chart.js";
|
||||
import type { ChartProps } from "./chart";
|
||||
import { Chart } from "./chart";
|
||||
import { cssNames } from "../../utils";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
|
||||
@@ -37,11 +37,18 @@ export class ClusterFrameHandler {
|
||||
@action
|
||||
public initView(clusterId: ClusterId) {
|
||||
const cluster = this.dependencies.getClusterById(clusterId);
|
||||
|
||||
if (!cluster) {
|
||||
this.dependencies.logger.warn(`[LENS-VIEW]: not initializing view; unknown clusterId="${clusterId}"`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const parentElem = document.getElementById("lens-views");
|
||||
|
||||
assert(parentElem, "DOM with #lens-views must be present");
|
||||
|
||||
if (!cluster || this.views.has(clusterId)) {
|
||||
if (this.views.has(clusterId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { ClusterStatus } from "./cluster-status";
|
||||
import type { ClusterFrameHandler } from "./cluster-frame-handler";
|
||||
import type { Cluster } from "../../../common/cluster/cluster";
|
||||
import { ClusterStore } from "../../../common/cluster-store/cluster-store";
|
||||
import { requestClusterActivation } from "../../ipc";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { NavigateToCatalog } from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
|
||||
@@ -20,18 +19,19 @@ import clusterViewRouteParametersInjectable from "./cluster-view-route-parameter
|
||||
import clusterFrameHandlerInjectable from "./cluster-frame-handler.injectable";
|
||||
import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry";
|
||||
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
|
||||
import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable";
|
||||
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
clusterId: IComputedValue<string>;
|
||||
clusterFrames: ClusterFrameHandler;
|
||||
navigateToCatalog: NavigateToCatalog;
|
||||
entityRegistry: CatalogEntityRegistry;
|
||||
getClusterById: GetClusterById;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedClusterView extends React.Component<Dependencies> {
|
||||
private readonly store = ClusterStore.getInstance();
|
||||
|
||||
constructor(props: Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
@@ -42,7 +42,7 @@ class NonInjectedClusterView extends React.Component<Dependencies> {
|
||||
}
|
||||
|
||||
@computed get cluster(): Cluster | undefined {
|
||||
return this.store.getById(this.clusterId);
|
||||
return this.props.getClusterById(this.clusterId);
|
||||
}
|
||||
|
||||
private readonly isViewLoaded = computed(() => this.props.clusterFrames.hasLoadedView(this.clusterId), {
|
||||
@@ -110,10 +110,11 @@ class NonInjectedClusterView extends React.Component<Dependencies> {
|
||||
|
||||
export const ClusterView = withInjectables<Dependencies>(NonInjectedClusterView, {
|
||||
getProps: (di) => ({
|
||||
clusterId: di.inject(clusterViewRouteParametersInjectable).clusterId,
|
||||
...di.inject(clusterViewRouteParametersInjectable),
|
||||
navigateToCatalog: di.inject(navigateToCatalogInjectable),
|
||||
clusterFrames: di.inject(clusterFrameHandlerInjectable),
|
||||
entityRegistry: di.inject(catalogEntityRegistryInjectable),
|
||||
getClusterById: di.inject(getClusterByIdInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||
import type { DiRender } from "../../test-utils/renderFor";
|
||||
import { renderFor } from "../../test-utils/renderFor";
|
||||
import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable";
|
||||
import statInjectable from "../../../../common/fs/stat/stat.injectable";
|
||||
import statInjectable from "../../../../common/fs/stat.injectable";
|
||||
|
||||
describe("ClusterLocalTerminalSettings", () => {
|
||||
let render: DiRender;
|
||||
|
||||
@@ -10,7 +10,6 @@ import { Input } from "../input";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import type { ShowNotification } from "../notifications";
|
||||
import { Icon } from "../icon";
|
||||
import { PathPicker } from "../path-picker";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
|
||||
import type { ValidateDirectory } from "../../../common/fs/validate-directory.injectable";
|
||||
@@ -19,6 +18,8 @@ import type { ResolveTilde } from "../../../common/path/resolve-tilde.injectable
|
||||
import resolveTildeInjectable from "../../../common/path/resolve-tilde.injectable";
|
||||
import Gutter from "../gutter/gutter";
|
||||
import isWindowsInjectable from "../../../common/vars/is-windows.injectable";
|
||||
import type { OpenPathPickingDialog } from "../../../features/path-picking-dialog/renderer/pick-paths.injectable";
|
||||
import openPathPickingDialogInjectable from "../../../features/path-picking-dialog/renderer/pick-paths.injectable";
|
||||
|
||||
export interface ClusterLocalTerminalSettingProps {
|
||||
cluster: Cluster;
|
||||
@@ -27,6 +28,7 @@ interface Dependencies {
|
||||
showErrorNotification: ShowNotification;
|
||||
validateDirectory: ValidateDirectory;
|
||||
resolveTilde: ResolveTilde;
|
||||
openPathPickingDialog: OpenPathPickingDialog;
|
||||
isWindows: boolean;
|
||||
}
|
||||
|
||||
@@ -36,6 +38,7 @@ const NonInjectedClusterLocalTerminalSetting = observer(({
|
||||
validateDirectory,
|
||||
resolveTilde,
|
||||
isWindows,
|
||||
openPathPickingDialog,
|
||||
}: Dependencies & ClusterLocalTerminalSettingProps) => {
|
||||
if (!cluster) {
|
||||
return null;
|
||||
@@ -95,8 +98,8 @@ const NonInjectedClusterLocalTerminalSetting = observer(({
|
||||
};
|
||||
|
||||
const openFilePicker = () => {
|
||||
PathPicker.pick({
|
||||
label: "Choose Working Directory",
|
||||
openPathPickingDialog({
|
||||
message: "Choose Working Directory",
|
||||
buttonLabel: "Pick",
|
||||
properties: ["openDirectory", "showHiddenFiles"],
|
||||
onPick: ([directory]) => setAndCommitDirectory(directory),
|
||||
@@ -168,5 +171,6 @@ export const ClusterLocalTerminalSetting = withInjectables<Dependencies, Cluster
|
||||
validateDirectory: di.inject(validateDirectoryInjectable),
|
||||
resolveTilde: di.inject(resolveTildeInjectable),
|
||||
isWindows: di.inject(isWindowsInjectable),
|
||||
openPathPickingDialog: di.inject(openPathPickingDialogInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -15,13 +15,15 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import moment from "moment-timezone";
|
||||
import type { Align, ListOnScrollProps } from "react-window";
|
||||
import { SearchStore } from "../../../search-store/search-store";
|
||||
import { UserStore } from "../../../../common/user-store";
|
||||
import type { UserStore } from "../../../../common/user-store";
|
||||
import { array, autoBind, cssNames } from "../../../utils";
|
||||
import type { VirtualListRef } from "../../virtual-list";
|
||||
import { VirtualList } from "../../virtual-list";
|
||||
import { ToBottom } from "./to-bottom";
|
||||
import type { LogTabViewModel } from "../logs/logs-view-model";
|
||||
import { Spinner } from "../../spinner";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import userStoreInjectable from "../../../../common/user-store/user-store.injectable";
|
||||
|
||||
export interface LogListProps {
|
||||
model: LogTabViewModel;
|
||||
@@ -33,8 +35,12 @@ export interface LogListRef {
|
||||
scrollToItem: (index: number, align: Align) => void;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
userStore: UserStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonForwardedLogList extends React.Component<LogListProps & { innerRef: ForwardedRef<LogListRef> }> {
|
||||
class NonForwardedLogList extends React.Component<Dependencies & LogListProps & { innerRef: ForwardedRef<LogListRef> }> {
|
||||
@observable isJumpButtonVisible = false;
|
||||
@observable isLastLineVisible = true;
|
||||
|
||||
@@ -122,7 +128,7 @@ class NonForwardedLogList extends React.Component<LogListProps & { innerRef: For
|
||||
|
||||
return this.props.model.timestampSplitLogs
|
||||
.get()
|
||||
.map(([logTimestamp, log]) => (`${logTimestamp && moment.tz(logTimestamp, UserStore.getInstance().localeTimezone).format()}${log}`));
|
||||
.map(([logTimestamp, log]) => (`${logTimestamp && moment.tz(logTimestamp, this.props.userStore.localeTimezone).format()}${log}`));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,6 +279,13 @@ class NonForwardedLogList extends React.Component<LogListProps & { innerRef: For
|
||||
}
|
||||
}
|
||||
|
||||
const InjectedNonForwardedLogList = withInjectables<Dependencies, LogListProps & { innerRef: ForwardedRef<LogListRef> }>(NonForwardedLogList, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
export const LogList = React.forwardRef<LogListRef, LogListProps>((props, ref) => (
|
||||
<NonForwardedLogList {...props} innerRef={ref} />
|
||||
<InjectedNonForwardedLogList {...props} innerRef={ref} />
|
||||
));
|
||||
@@ -10,9 +10,9 @@ import type { TerminalApi } from "../../../api/terminal-api";
|
||||
import terminalSpawningPoolInjectable from "./terminal-spawning-pool.injectable";
|
||||
import terminalConfigInjectable from "../../../../common/user-store/terminal-config.injectable";
|
||||
import terminalCopyOnSelectInjectable from "../../../../common/user-store/terminal-copy-on-select.injectable";
|
||||
import themeStoreInjectable from "../../../themes/store.injectable";
|
||||
import isMacInjectable from "../../../../common/vars/is-mac.injectable";
|
||||
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
|
||||
import xtermColorThemeInjectable from "../../../themes/terminal-colors.injectable";
|
||||
|
||||
export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal;
|
||||
|
||||
@@ -23,9 +23,9 @@ const createTerminalInjectable = getInjectable({
|
||||
spawningPool: di.inject(terminalSpawningPoolInjectable),
|
||||
terminalConfig: di.inject(terminalConfigInjectable),
|
||||
terminalCopyOnSelect: di.inject(terminalCopyOnSelectInjectable),
|
||||
themeStore: di.inject(themeStoreInjectable),
|
||||
isMac: di.inject(isMacInjectable),
|
||||
openLinkInBrowser: di.inject(openLinkInBrowserInjectable),
|
||||
xtermColorTheme: di.inject(xtermColorThemeInjectable),
|
||||
};
|
||||
|
||||
return (tabId, api) => new Terminal(dependencies, { tabId, api });
|
||||
|
||||
@@ -10,7 +10,6 @@ import { Terminal as XTerm } from "xterm";
|
||||
import { FitAddon } from "xterm-addon-fit";
|
||||
import type { TabId } from "../dock/store";
|
||||
import type { TerminalApi } from "../../../api/terminal-api";
|
||||
import type { ThemeStore } from "../../../themes/store";
|
||||
import { disposer } from "../../../utils";
|
||||
import { once } from "lodash";
|
||||
import { clipboard } from "electron";
|
||||
@@ -25,8 +24,8 @@ export interface TerminalDependencies {
|
||||
readonly spawningPool: HTMLElement;
|
||||
readonly terminalConfig: IComputedValue<TerminalConfig>;
|
||||
readonly terminalCopyOnSelect: IComputedValue<boolean>;
|
||||
readonly themeStore: ThemeStore;
|
||||
readonly isMac: boolean;
|
||||
readonly xtermColorTheme: IComputedValue<Record<string, string>>;
|
||||
openLinkInBrowser: OpenLinkInBrowser;
|
||||
}
|
||||
|
||||
@@ -75,10 +74,6 @@ export class Terminal {
|
||||
return this.dependencies.terminalConfig.get().fontSize;
|
||||
}
|
||||
|
||||
get theme(): Record<string/*paramName*/, string/*color*/> {
|
||||
return this.dependencies.themeStore.xtermColors;
|
||||
}
|
||||
|
||||
constructor(protected readonly dependencies: TerminalDependencies, {
|
||||
tabId,
|
||||
api,
|
||||
@@ -120,9 +115,12 @@ export class Terminal {
|
||||
|
||||
this.disposer.push(
|
||||
this.xterm.registerLinkProvider(linkProvider),
|
||||
reaction(() => this.theme, colors => this.xterm.setOption("theme", colors), {
|
||||
fireImmediately: true,
|
||||
}),
|
||||
reaction(() => this.dependencies.xtermColorTheme.get(),
|
||||
colors => this.xterm.options.theme = colors,
|
||||
{
|
||||
fireImmediately: true,
|
||||
},
|
||||
),
|
||||
reaction(() => this.fontSize, this.setFontSize, { fireImmediately: true }),
|
||||
reaction(() => this.fontFamily, this.setFontFamily, { fireImmediately: true }),
|
||||
() => onDataHandler.dispose(),
|
||||
|
||||
@@ -10,7 +10,7 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { cssNames } from "../../../utils";
|
||||
import type { Terminal } from "./terminal";
|
||||
import type { TerminalStore } from "./store";
|
||||
import type { LensTheme } from "../../../themes/store";
|
||||
import type { LensTheme } from "../../../themes/lens-theme";
|
||||
import type { DockTab, DockStore } from "../dock/store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import dockStoreInjectable from "../dock/store.injectable";
|
||||
|
||||
@@ -21,7 +21,7 @@ import { NoItems } from "../no-items";
|
||||
import { Spinner } from "../spinner";
|
||||
import type { ItemObject } from "../../../common/item.store";
|
||||
import type { Filter, PageFiltersStore } from "./page-filters/store";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { MenuActions } from "../menu/menu-actions";
|
||||
import { MenuItem } from "../menu";
|
||||
import { Checkbox } from "../checkbox";
|
||||
|
||||
@@ -4,30 +4,28 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { action } from "mobx";
|
||||
import { beforeFrameStartsInjectionToken } from "../../../before-frame-starts/before-frame-starts-injection-token";
|
||||
import { beforeFrameStartsInjectionToken } from "../../../before-frame-starts/tokens";
|
||||
import ipcRendererInjectable from "../../../utils/channel/ipc-renderer.injectable";
|
||||
import topBarStateInjectable from "./state.injectable";
|
||||
|
||||
// TODO: replace with a SyncBox
|
||||
const startTopbarStateSyncInjectable = getInjectable({
|
||||
id: "start-topbar-state-sync",
|
||||
instantiate: (di) => {
|
||||
const state = di.inject(topBarStateInjectable);
|
||||
const ipcRenderer = di.inject(ipcRendererInjectable);
|
||||
instantiate: (di) => ({
|
||||
id: "start-topbar-state-sync",
|
||||
run: () => {
|
||||
const state = di.inject(topBarStateInjectable);
|
||||
const ipcRenderer = di.inject(ipcRendererInjectable);
|
||||
|
||||
return {
|
||||
id: "start-topbar-state-sync",
|
||||
run: () => {
|
||||
ipcRenderer.on("history:can-go-back", action((event, canGoBack: boolean) => {
|
||||
state.prevEnabled = canGoBack;
|
||||
}));
|
||||
ipcRenderer.on("history:can-go-back", action((event, canGoBack: boolean) => {
|
||||
state.prevEnabled = canGoBack;
|
||||
}));
|
||||
|
||||
ipcRenderer.on("history:can-go-forward", action((event, canGoForward: boolean) => {
|
||||
state.nextEnabled = canGoForward;
|
||||
}));
|
||||
},
|
||||
};
|
||||
},
|
||||
ipcRenderer.on("history:can-go-forward", action((event, canGoForward: boolean) => {
|
||||
state.nextEnabled = canGoForward;
|
||||
}));
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeFrameStartsInjectionToken,
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ import toggleMaximizeWindowInjectable from "./toggle-maximize-window/toggle-maxi
|
||||
import topBarStateInjectable from "./state.injectable";
|
||||
import platformInjectable from "../../../../common/vars/platform.injectable";
|
||||
import goForwardInjectable from "./top-bar-items/navigation-to-forward/go-forward/go-forward.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../../../routes/currently-in-cluster-frame.injectable";
|
||||
|
||||
describe("<TopBar/>", () => {
|
||||
let di: DiContainer;
|
||||
@@ -42,6 +43,7 @@ describe("<TopBar/>", () => {
|
||||
di.override(closeWindowInjectable, () => closeWindow = jest.fn());
|
||||
di.override(maximizeWindowInjectable, () => maximizeWindow = jest.fn());
|
||||
di.override(toggleMaximizeWindowInjectable, () => toggleMaximizeWindow = jest.fn());
|
||||
di.override(currentlyInClusterFrameInjectable, () => false);
|
||||
|
||||
render = renderFor(di);
|
||||
});
|
||||
|
||||
@@ -6,17 +6,27 @@
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import moment from "moment-timezone";
|
||||
import { UserStore } from "../../../common/user-store";
|
||||
import type { UserStore } from "../../../common/user-store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||
|
||||
export interface LocaleDateProps {
|
||||
date: string;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class LocaleDate extends React.Component<LocaleDateProps> {
|
||||
render() {
|
||||
const { date } = this.props;
|
||||
|
||||
return moment.tz(date, UserStore.getInstance().localeTimezone).format();
|
||||
}
|
||||
interface Dependencies {
|
||||
userStore: UserStore;
|
||||
}
|
||||
|
||||
const NonInjectedLocaleDate = observer(({ date, userStore }: LocaleDateProps & Dependencies) => (
|
||||
<>
|
||||
{`${moment.tz(date, userStore.localeTimezone).format()}`}
|
||||
</>
|
||||
));
|
||||
|
||||
export const LocaleDate = withInjectables<Dependencies, LocaleDateProps>(NonInjectedLocaleDate, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -14,7 +14,7 @@ import { type MonacoValidator, monacoValidators } from "./monaco-validators";
|
||||
import { debounce, merge } from "lodash";
|
||||
import { autoBind, cssNames, disposer } from "../../utils";
|
||||
import type { UserStore } from "../../../common/user-store";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
|
||||
@@ -4,27 +4,16 @@
|
||||
*/
|
||||
|
||||
// Monaco editor themes customization
|
||||
import { editor } from "monaco-editor";
|
||||
import cloudsMidnight from "./monaco-themes/clouds-midnight.json";
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { editor } from "monaco-editor";
|
||||
|
||||
export type MonacoTheme = "vs" | "vs-dark" | "hc-black" | MonacoCustomTheme;
|
||||
export type MonacoCustomTheme = "clouds-midnight";
|
||||
|
||||
export interface MonacoThemeData extends editor.IStandaloneThemeData {
|
||||
name?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
// Registered names could be then used in "themes/*.json" in "{monacoTheme: [name]}"
|
||||
export const customThemes: Partial<Record<MonacoCustomTheme, MonacoThemeData>> = {
|
||||
"clouds-midnight": cloudsMidnight as MonacoThemeData,
|
||||
};
|
||||
|
||||
export function registerCustomThemes(): void {
|
||||
Object.entries(customThemes).forEach(([name, theme]) => {
|
||||
editor.defineTheme(name, theme);
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadCustomTheme(name: string): Promise<MonacoThemeData> {
|
||||
return import(`./monaco-themes/${name}.json`);
|
||||
}
|
||||
export const customMonacoThemeInjectionToken = getInjectionToken<MonacoThemeData>({
|
||||
id: "custom-monaco-theme-token",
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { customMonacoThemeInjectionToken } from "../monaco-themes";
|
||||
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
const cloudsMidnightThemeInjectable = getInjectable({
|
||||
id: "clouds-midnight-theme",
|
||||
instantiate: () => ({
|
||||
"name": "clouds-midnight",
|
||||
"base": "vs-dark" as const,
|
||||
"inherit": true,
|
||||
"rules": [
|
||||
{
|
||||
"background": "191919",
|
||||
"token": "",
|
||||
},
|
||||
{
|
||||
"foreground": "3c403b",
|
||||
"token": "comment",
|
||||
},
|
||||
{
|
||||
"foreground": "5d90cd",
|
||||
"token": "string",
|
||||
},
|
||||
{
|
||||
"foreground": "46a609",
|
||||
"token": "constant.numeric",
|
||||
},
|
||||
{
|
||||
"foreground": "39946a",
|
||||
"token": "constant.language",
|
||||
},
|
||||
{
|
||||
"foreground": "927c5d",
|
||||
"token": "keyword",
|
||||
},
|
||||
{
|
||||
"foreground": "927c5d",
|
||||
"token": "support.constant.property-value",
|
||||
},
|
||||
{
|
||||
"foreground": "927c5d",
|
||||
"token": "constant.other.color",
|
||||
},
|
||||
{
|
||||
"foreground": "366f1a",
|
||||
"token": "keyword.other.unit",
|
||||
},
|
||||
{
|
||||
"foreground": "a46763",
|
||||
"token": "entity.other.attribute-name.html",
|
||||
},
|
||||
{
|
||||
"foreground": "4b4b4b",
|
||||
"token": "keyword.operator",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "storage",
|
||||
},
|
||||
{
|
||||
"foreground": "858585",
|
||||
"token": "entity.other.inherited-class",
|
||||
},
|
||||
{
|
||||
"foreground": "606060",
|
||||
"token": "entity.name.tag",
|
||||
},
|
||||
{
|
||||
"foreground": "a165ac",
|
||||
"token": "constant.character.entity",
|
||||
},
|
||||
{
|
||||
"foreground": "a165ac",
|
||||
"token": "support.class.js",
|
||||
},
|
||||
{
|
||||
"foreground": "606060",
|
||||
"token": "entity.other.attribute-name",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "meta.selector.css",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "entity.name.tag.css",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "entity.other.attribute-name.id.css",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "entity.other.attribute-name.class.css",
|
||||
},
|
||||
{
|
||||
"foreground": "616161",
|
||||
"token": "meta.property-name.css",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "support.function",
|
||||
},
|
||||
{
|
||||
"foreground": "ffffff",
|
||||
"background": "e92e2e",
|
||||
"token": "invalid",
|
||||
},
|
||||
{
|
||||
"foreground": "e92e2e",
|
||||
"token": "punctuation.section.embedded",
|
||||
},
|
||||
{
|
||||
"foreground": "606060",
|
||||
"token": "punctuation.definition.tag",
|
||||
},
|
||||
{
|
||||
"foreground": "a165ac",
|
||||
"token": "constant.other.color.rgb-value.css",
|
||||
},
|
||||
{
|
||||
"foreground": "a165ac",
|
||||
"token": "support.constant.property-value.css",
|
||||
},
|
||||
],
|
||||
"colors": {
|
||||
"editor.foreground": "#929292",
|
||||
"editor.background": "#191919",
|
||||
"editor.selectionBackground": "#000000",
|
||||
"editor.lineHighlightBackground": "#D7D7D708",
|
||||
"editorCursor.foreground": "#7DA5DC",
|
||||
"editorWhitespace.foreground": "#BFBFBF",
|
||||
},
|
||||
}),
|
||||
injectionToken: customMonacoThemeInjectionToken,
|
||||
});
|
||||
|
||||
export default cloudsMidnightThemeInjectable;
|
||||
@@ -3,17 +3,19 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { FileFilter, OpenDialogOptions } from "electron";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import type { OpenPathPickingDialog } from "../../../features/path-picking-dialog/renderer/pick-paths.injectable";
|
||||
import openPathPickingDialogInjectable from "../../../features/path-picking-dialog/renderer/pick-paths.injectable";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Button } from "../button";
|
||||
import { requestOpenFilePickingDialog } from "../../ipc";
|
||||
|
||||
export interface PathPickOpts {
|
||||
label: string;
|
||||
onPick?: (paths: string[]) => any;
|
||||
onCancel?: () => any;
|
||||
message: string;
|
||||
onPick?: (paths: string[]) => void | Promise<void>;
|
||||
onCancel?: () => void | Promise<void>;
|
||||
defaultPath?: string;
|
||||
buttonLabel?: string;
|
||||
filters?: FileFilter[];
|
||||
@@ -26,40 +28,32 @@ export interface PathPickerProps extends PathPickOpts {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PathPicker extends React.Component<PathPickerProps> {
|
||||
static async pick(opts: PathPickOpts) {
|
||||
const { onPick, onCancel, label, ...dialogOptions } = opts;
|
||||
|
||||
const { canceled, filePaths } = await requestOpenFilePickingDialog({
|
||||
message: label,
|
||||
...dialogOptions,
|
||||
});
|
||||
|
||||
if (canceled) {
|
||||
await onCancel?.();
|
||||
} else {
|
||||
await onPick?.(filePaths);
|
||||
}
|
||||
}
|
||||
|
||||
async onClick() {
|
||||
const { className, disabled, ...pickOpts } = this.props;
|
||||
|
||||
return PathPicker.pick(pickOpts);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, label, disabled } = this.props;
|
||||
|
||||
return (
|
||||
<Button
|
||||
primary
|
||||
label={label}
|
||||
disabled={disabled}
|
||||
className={cssNames("PathPicker", className)}
|
||||
onClick={() => void this.onClick()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
interface Dependencies {
|
||||
openPathPickingDialog: OpenPathPickingDialog;
|
||||
}
|
||||
|
||||
const NonInjectedPathPicker = observer((props: PathPickerProps & Dependencies) => {
|
||||
const {
|
||||
className,
|
||||
disabled,
|
||||
openPathPickingDialog,
|
||||
...pickOpts
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Button
|
||||
primary
|
||||
label={pickOpts.message}
|
||||
disabled={disabled}
|
||||
className={cssNames("PathPicker", className)}
|
||||
onClick={() => void openPathPickingDialog(pickOpts)}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export const PathPicker = withInjectables<Dependencies, PathPickerProps>(NonInjectedPathPicker, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
openPathPickingDialog: di.inject(openPathPickingDialogInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -13,7 +13,7 @@ import { action, computed, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import ReactSelect, { components, createFilter } from "react-select";
|
||||
import type { Props as ReactSelectProps, GroupBase, MultiValue, OptionsOrGroups, PropsValue, SingleValue } from "react-select";
|
||||
import type { LensTheme } from "../../themes/store";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import { autoBind, cssNames } from "../../utils";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
|
||||
@@ -63,12 +63,15 @@ import type { FakeExtensionOptions } from "./get-extension-fake";
|
||||
import { getExtensionFakeForMain, getExtensionFakeForRenderer } from "./get-extension-fake";
|
||||
import namespaceApiInjectable from "../../../common/k8s-api/endpoints/namespace.api.injectable";
|
||||
import { Namespace } from "../../../common/k8s-api/endpoints";
|
||||
import { overrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes";
|
||||
import { getOverrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes";
|
||||
import applicationMenuItemCompositeInjectable from "../../../features/application-menu/main/application-menu-item-composite.injectable";
|
||||
import { getCompositePaths } from "../../../common/utils/composite/get-composite-paths/get-composite-paths";
|
||||
import { discoverFor } from "./discovery-of-html-elements";
|
||||
import { findComposite } from "../../../common/utils/composite/find-composite/find-composite";
|
||||
import shouldStartHiddenInjectable from "../../../main/electron-app/features/should-start-hidden.injectable";
|
||||
import fsInjectable from "../../../common/fs/fs.injectable";
|
||||
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
|
||||
import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable";
|
||||
|
||||
type Callback = (di: DiContainer) => void | Promise<void>;
|
||||
|
||||
@@ -114,6 +117,7 @@ export interface ApplicationBuilder {
|
||||
|
||||
allowKubeResource: (resourceName: KubeResource) => ApplicationBuilder;
|
||||
beforeApplicationStart: (callback: Callback) => ApplicationBuilder;
|
||||
afterApplicationStart: (callback: Callback) => ApplicationBuilder;
|
||||
beforeWindowStart: (callback: Callback) => ApplicationBuilder;
|
||||
afterWindowStart: (callback: Callback) => ApplicationBuilder;
|
||||
|
||||
@@ -170,12 +174,22 @@ export const getApplicationBuilder = () => {
|
||||
const { overrideForWindow, sendToWindow } = overrideChannels(mainDi);
|
||||
|
||||
const beforeApplicationStartCallbacks: Callback[] = [];
|
||||
const afterApplicationStartCallbacks: Callback[] = [];
|
||||
const beforeWindowStartCallbacks: Callback[] = [];
|
||||
const afterWindowStartCallbacks: Callback[] = [];
|
||||
|
||||
const fsState = new Map();
|
||||
const overrideFsWithFakes = getOverrideFsWithFakes();
|
||||
|
||||
overrideFsWithFakes(mainDi, fsState);
|
||||
overrideFsWithFakes(mainDi);
|
||||
|
||||
// Set up ~/.kube as existing as a folder
|
||||
{
|
||||
const { ensureDirSync } = mainDi.inject(fsInjectable);
|
||||
const joinPaths = mainDi.inject(joinPathsInjectable);
|
||||
const homeDirectoryPath = mainDi.inject(homeDirectoryPathInjectable);
|
||||
|
||||
ensureDirSync(joinPaths(homeDirectoryPath, ".kube"));
|
||||
}
|
||||
|
||||
let environment = environments.application;
|
||||
|
||||
@@ -210,7 +224,7 @@ export const getApplicationBuilder = () => {
|
||||
const windowDi = getRendererDi({ doGeneralOverrides: true });
|
||||
|
||||
overrideForWindow(windowDi, windowId);
|
||||
overrideFsWithFakes(windowDi, fsState);
|
||||
overrideFsWithFakes(windowDi);
|
||||
|
||||
runInAction(() => {
|
||||
windowDi.register(rendererExtensionsStateInjectable);
|
||||
@@ -276,6 +290,24 @@ export const getApplicationBuilder = () => {
|
||||
const namespaces = observable.set<string>();
|
||||
const namespaceItems = observable.array<Namespace>();
|
||||
const selectedNamespaces = observable.set<string>();
|
||||
const startMainApplication = mainDi.inject(startMainApplicationInjectable);
|
||||
|
||||
const startApplication = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => {
|
||||
mainDi.inject(lensProxyPortInjectable).set(42);
|
||||
|
||||
for (const callback of beforeApplicationStartCallbacks) {
|
||||
await callback(mainDi);
|
||||
}
|
||||
|
||||
mainDi.override(shouldStartHiddenInjectable, () => shouldStartHidden);
|
||||
await startMainApplication();
|
||||
|
||||
for (const callback of afterApplicationStartCallbacks) {
|
||||
await callback(mainDi);
|
||||
}
|
||||
|
||||
applicationHasStarted = true;
|
||||
};
|
||||
|
||||
const builder: ApplicationBuilder = {
|
||||
mainDi,
|
||||
@@ -556,7 +588,7 @@ export const getApplicationBuilder = () => {
|
||||
},
|
||||
|
||||
enable: (...extensions) => {
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
builder.afterWindowStart((windowDi) => {
|
||||
const rendererExtensionInstances = extensions.map((options) =>
|
||||
getExtensionFakeForRenderer(
|
||||
windowDi,
|
||||
@@ -571,7 +603,7 @@ export const getApplicationBuilder = () => {
|
||||
);
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
builder.afterApplicationStart((mainDi) => {
|
||||
const mainExtensionInstances = extensions.map((extension) =>
|
||||
getExtensionFakeForMain(mainDi, extension.id, extension.name, extension.mainOptions || {}),
|
||||
);
|
||||
@@ -585,7 +617,7 @@ export const getApplicationBuilder = () => {
|
||||
},
|
||||
|
||||
disable: (...extensions) => {
|
||||
builder.beforeWindowStart(windowDi => {
|
||||
builder.afterWindowStart(windowDi => {
|
||||
extensions
|
||||
.map((ext) => ext.id)
|
||||
.forEach(
|
||||
@@ -593,7 +625,7 @@ export const getApplicationBuilder = () => {
|
||||
);
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart(mainDi => {
|
||||
builder.afterApplicationStart(mainDi => {
|
||||
extensions
|
||||
.map((ext) => ext.id)
|
||||
.forEach(
|
||||
@@ -623,6 +655,16 @@ export const getApplicationBuilder = () => {
|
||||
return builder;
|
||||
},
|
||||
|
||||
afterApplicationStart(callback) {
|
||||
if (applicationHasStarted) {
|
||||
callback(mainDi);
|
||||
}
|
||||
|
||||
afterApplicationStartCallbacks.push(callback);
|
||||
|
||||
return builder;
|
||||
},
|
||||
|
||||
beforeWindowStart(callback) {
|
||||
const alreadyRenderedWindows = builder.applicationWindow.getAll();
|
||||
|
||||
@@ -648,29 +690,11 @@ export const getApplicationBuilder = () => {
|
||||
},
|
||||
|
||||
startHidden: async () => {
|
||||
mainDi.inject(lensProxyPortInjectable).set(42);
|
||||
|
||||
for (const callback of beforeApplicationStartCallbacks) {
|
||||
await callback(mainDi);
|
||||
}
|
||||
|
||||
mainDi.override(shouldStartHiddenInjectable, () => true);
|
||||
await mainDi.inject(startMainApplicationInjectable);
|
||||
|
||||
applicationHasStarted = true;
|
||||
await startApplication({ shouldStartHidden: true });
|
||||
},
|
||||
|
||||
async render() {
|
||||
mainDi.inject(lensProxyPortInjectable).set(42);
|
||||
|
||||
for (const callback of beforeApplicationStartCallbacks) {
|
||||
await callback(mainDi);
|
||||
}
|
||||
|
||||
mainDi.override(shouldStartHiddenInjectable, () => false);
|
||||
await mainDi.inject(startMainApplicationInjectable);
|
||||
|
||||
applicationHasStarted = true;
|
||||
await startApplication({ shouldStartHidden: false });
|
||||
|
||||
return builder
|
||||
.applicationWindow
|
||||
|
||||
Reference in new issue
Block a user