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

Fully split apart the user preferences storage

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-03-17 14:17:41 -04:00
parent 037c62d426
commit 4055732d41
86 changed files with 720 additions and 806 deletions

View File

@ -2,8 +2,6 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { UserStore } from "../user-store";
import userStoreInjectable from "../user-store/user-store.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { defaultThemeId } from "../vars"; import { defaultThemeId } from "../vars";
@ -14,10 +12,16 @@ import releaseChannelInjectable from "../vars/release-channel.injectable";
import defaultUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/default-update-channel.injectable"; import defaultUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/default-update-channel.injectable";
import writeJsonSyncInjectable from "../fs/write-json-sync.injectable"; import writeJsonSyncInjectable from "../fs/write-json-sync.injectable";
import writeFileSyncInjectable from "../fs/write-file-sync.injectable"; import writeFileSyncInjectable from "../fs/write-file-sync.injectable";
import type { UserPreferencesState } from "../../features/user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../features/user-preferences/common/state.injectable";
import userPreferencesPersistentStorageInjectable from "../../features/user-preferences/common/storage.injectable";
import type { ResetTheme } from "../../features/user-preferences/common/reset-theme.injectable";
import resetThemeInjectable from "../../features/user-preferences/common/reset-theme.injectable";
import type { ClusterStoreModel } from "../../features/cluster/storage/common/storage.injectable"; import type { ClusterStoreModel } from "../../features/cluster/storage/common/storage.injectable";
describe("user store tests", () => { describe("user store tests", () => {
let userStore: UserStore; let state: UserPreferencesState;
let resetTheme: ResetTheme;
let di: DiContainer; let di: DiContainer;
beforeEach(async () => { beforeEach(async () => {
@ -33,6 +37,8 @@ describe("user store tests", () => {
await di.inject(defaultUpdateChannelInjectable).init(); await di.inject(defaultUpdateChannelInjectable).init();
state = di.inject(userPreferencesStateInjectable);
resetTheme = di.inject(resetThemeInjectable);
}); });
describe("for an empty config", () => { describe("for an empty config", () => {
@ -42,25 +48,23 @@ describe("user store tests", () => {
writeJsonSync("/some-directory-for-user-data/lens-user-store.json", {}); writeJsonSync("/some-directory-for-user-data/lens-user-store.json", {});
writeJsonSync("/some-directory-for-user-data/kube_config", {}); writeJsonSync("/some-directory-for-user-data/kube_config", {});
userStore = di.inject(userStoreInjectable); di.inject(userPreferencesPersistentStorageInjectable).loadAndStartSyncing();
userStore.load();
}); });
it("allows setting and getting preferences", () => { it("allows setting and getting preferences", () => {
userStore.httpsProxy = "abcd://defg"; state.httpsProxy = "abcd://defg";
expect(userStore.httpsProxy).toBe("abcd://defg"); expect(state.httpsProxy).toBe("abcd://defg");
expect(userStore.colorTheme).toBe(defaultThemeId); expect(state.colorTheme).toBe(defaultThemeId);
userStore.colorTheme = "light"; state.colorTheme = "light";
expect(userStore.colorTheme).toBe("light"); expect(state.colorTheme).toBe("light");
}); });
it("correctly resets theme to default value", async () => { it("correctly resets theme to default value", async () => {
userStore.colorTheme = "some other theme"; state.colorTheme = "some other theme";
userStore.resetTheme(); resetTheme();
expect(userStore.colorTheme).toBe(defaultThemeId); expect(state.colorTheme).toBe(defaultThemeId);
}); });
}); });
@ -92,18 +96,16 @@ describe("user store tests", () => {
di.override(storeMigrationVersionInjectable, () => "10.0.0"); di.override(storeMigrationVersionInjectable, () => "10.0.0");
userStore = di.inject(userStoreInjectable); di.inject(userPreferencesPersistentStorageInjectable).loadAndStartSyncing();
userStore.load();
}); });
it("skips clusters for adding to kube-sync with files under extension_data/", () => { it("skips clusters for adding to kube-sync with files under extension_data/", () => {
expect(userStore.syncKubeconfigEntries.has("/some-directory-for-user-data/extension_data/foo/bar")).toBe(false); expect(state.syncKubeconfigEntries.has("/some-directory-for-user-data/extension_data/foo/bar")).toBe(false);
expect(userStore.syncKubeconfigEntries.has("/some/other/path")).toBe(true); expect(state.syncKubeconfigEntries.has("/some/other/path")).toBe(true);
}); });
it("allows access to the colorTheme preference", () => { it("allows access to the colorTheme preference", () => {
expect(userStore.colorTheme).toBe("light"); expect(state.colorTheme).toBe("light");
}); });
}); });
}); });

View File

@ -9,7 +9,7 @@ import isProductionInjectable from "../vars/is-production.injectable";
import sentryDataSourceNameInjectable from "../vars/sentry-dsn-url.injectable"; import sentryDataSourceNameInjectable from "../vars/sentry-dsn-url.injectable";
import { Dedupe, Offline } from "@sentry/integrations"; import { Dedupe, Offline } from "@sentry/integrations";
import { inspect } from "util"; import { inspect } from "util";
import userStoreInjectable from "../user-store/user-store.injectable"; import userPreferencesStateInjectable from "../../features/user-preferences/common/state.injectable";
export type InitializeSentryReportingWith = (initSentry: (opts: BrowserOptions | ElectronMainOptions) => void) => void; export type InitializeSentryReportingWith = (initSentry: (opts: BrowserOptions | ElectronMainOptions) => void) => void;
@ -20,7 +20,7 @@ const initializeSentryReportingWithInjectable = getInjectable({
instantiate: (di): InitializeSentryReportingWith => { instantiate: (di): InitializeSentryReportingWith => {
const sentryDataSourceName = di.inject(sentryDataSourceNameInjectable); const sentryDataSourceName = di.inject(sentryDataSourceNameInjectable);
const isProduction = di.inject(isProductionInjectable); const isProduction = di.inject(isProductionInjectable);
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
if (!sentryDataSourceName) { if (!sentryDataSourceName) {
return () => {}; return () => {};
@ -28,7 +28,7 @@ const initializeSentryReportingWithInjectable = getInjectable({
return (initSentry) => initSentry({ return (initSentry) => initSentry({
beforeSend: (event) => { beforeSend: (event) => {
if (userStore.allowErrorReporting) { if (state.allowErrorReporting) {
return event; return event;
} }

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { HttpsProxyAgent } from "hpagent"; import { HttpsProxyAgent } from "hpagent";
import userStoreInjectable from "../user-store/user-store.injectable"; import userPreferencesStateInjectable from "../../features/user-preferences/common/state.injectable";
import type { Fetch } from "./fetch.injectable"; import type { Fetch } from "./fetch.injectable";
import fetchInjectable from "./fetch.injectable"; import fetchInjectable from "./fetch.injectable";
@ -12,7 +12,7 @@ const proxyFetchInjectable = getInjectable({
id: "proxy-fetch", id: "proxy-fetch",
instantiate: (di): Fetch => { instantiate: (di): Fetch => {
const fetch = di.inject(fetchInjectable); const fetch = di.inject(fetchInjectable);
const { httpsProxy, allowUntrustedCAs } = di.inject(userStoreInjectable); const { httpsProxy, allowUntrustedCAs } = di.inject(userPreferencesStateInjectable);
const agent = httpsProxy const agent = httpsProxy
? new HttpsProxyAgent({ ? new HttpsProxyAgent({
proxy: httpsProxy, proxy: httpsProxy,

View File

@ -22,6 +22,7 @@ const fsInjectable = getInjectable({
access, access,
stat, stat,
unlink, unlink,
rename,
}, },
ensureDir, ensureDir,
ensureDirSync, ensureDirSync,
@ -58,6 +59,7 @@ const fsInjectable = getInjectable({
createReadStream, createReadStream,
stat, stat,
unlink, unlink,
rename,
}; };
}, },
causesSideEffects: true, causesSideEffects: true,

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import userInfoInjectable from "../user-store/user-info.injectable"; import userInfoInjectable from "../vars/user-info.injectable";
const homeDirectoryPathInjectable = getInjectable({ const homeDirectoryPathInjectable = getInjectable({
id: "home-directory-path", id: "home-directory-path",

View File

@ -1,9 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "@k8slens/test-utils";
import userStoreFileNameMigrationInjectable from "./file-name-migration.injectable";
export default getGlobalOverride(userStoreFileNameMigrationInjectable, () => async () => {});

View File

@ -1,7 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export * from "./user-store";
export type { KubeconfigSyncEntry, KubeconfigSyncValue, UserPreferencesModel } from "./preferences-helpers";

View File

@ -1,11 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { MigrationDeclaration } from "../persistent-storage/migrations.injectable";
export const userStoreMigrationInjectionToken = getInjectionToken<MigrationDeclaration>({
id: "user-store-migration-token",
});

View File

@ -1,30 +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 "./user-store";
import selectedUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
import loggerInjectable from "../logger.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import persistentStorageMigrationsInjectable from "../persistent-storage/migrations.injectable";
import { userStoreMigrationInjectionToken } from "./migrations-token";
import userStorePreferenceDescriptorsInjectable from "./preference-descriptors.injectable";
import createPersistentStorageInjectable from "../persistent-storage/create.injectable";
const userStoreInjectable = getInjectable({
id: "user-store",
instantiate: (di) => new UserStore({
selectedUpdateChannel: di.inject(selectedUpdateChannelInjectable),
emitAppEvent: di.inject(emitAppEventInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
migrations: di.inject(persistentStorageMigrationsInjectable, userStoreMigrationInjectionToken),
preferenceDescriptors: di.inject(userStorePreferenceDescriptorsInjectable),
createPersistentStorage: di.inject(createPersistentStorageInjectable),
}),
});
export default userStoreInjectable;

View File

@ -1,157 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { action, observable, makeObservable, isObservableArray, isObservableSet, isObservableMap, runInAction } from "mobx";
import { getOrInsertSet, toggle, object } from "@k8slens/utilities";
import type { UserPreferencesModel, StoreType } from "./preferences-helpers";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
// TODO: Remove coupling with Feature
import type { SelectedUpdateChannel } from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
import type { ReleaseChannel } from "../../features/application-update/common/update-channels";
import type { PreferenceDescriptors } from "./preference-descriptors.injectable";
import type { CreatePersistentStorage, PersistentStorage } from "../persistent-storage/create.injectable";
import type { Logger } from "../logger";
import type { Migrations } from "conf/dist/source/types";
import { toJS } from "../utils";
export interface UserStoreModel {
preferences: UserPreferencesModel;
}
interface Dependencies {
readonly selectedUpdateChannel: SelectedUpdateChannel;
readonly preferenceDescriptors: PreferenceDescriptors;
readonly logger: Logger;
readonly storeMigrationVersion: string;
readonly migrations: Migrations<Record<string, unknown>>;
emitAppEvent: EmitAppEvent;
createPersistentStorage: CreatePersistentStorage;
}
export class UserStore {
private readonly store: PersistentStorage;
constructor(protected readonly dependencies: Dependencies) {
this.store = this.dependencies.createPersistentStorage<UserStoreModel>({
configName: "lens-user-store",
projectVersion: this.dependencies.storeMigrationVersion,
migrations: this.dependencies.migrations,
fromStore: action(({ preferences }) => {
this.dependencies.logger.debug("UserStore.fromStore()", { preferences });
for (const [key, { fromStore }] of object.entries(this.dependencies.preferenceDescriptors)) {
const curVal = this[key];
const newVal = fromStore((preferences)?.[key] as never) as never;
if (isObservableArray(curVal)) {
curVal.replace(newVal);
} else if (isObservableSet(curVal) || isObservableMap(curVal)) {
curVal.replace(newVal);
} else {
this[key] = newVal;
}
}
// TODO: Switch to action-based saving instead saving stores by reaction
if (preferences?.updateChannel) {
this.dependencies.selectedUpdateChannel.setValue(preferences?.updateChannel as ReleaseChannel);
}
}),
toJSON: () => {
const preferences = object.fromEntries(
object.entries(this.dependencies.preferenceDescriptors)
.map(([key, { toStore }]) => [key, toStore(this[key] as never)]),
) as UserPreferencesModel;
return toJS({
preferences: {
...preferences,
updateChannel: this.dependencies.selectedUpdateChannel.value.get().id,
},
});
},
});
makeObservable(this);
}
@observable allowErrorReporting!: StoreType<PreferenceDescriptors["allowErrorReporting"]>;
@observable allowUntrustedCAs!: StoreType<PreferenceDescriptors["allowUntrustedCAs"]>;
@observable colorTheme!: StoreType<PreferenceDescriptors["colorTheme"]>;
@observable terminalTheme!: StoreType<PreferenceDescriptors["terminalTheme"]>;
@observable localeTimezone!: StoreType<PreferenceDescriptors["localeTimezone"]>;
@observable downloadMirror!: StoreType<PreferenceDescriptors["downloadMirror"]>;
@observable httpsProxy!: StoreType<PreferenceDescriptors["httpsProxy"]>;
@observable shell!: StoreType<PreferenceDescriptors["shell"]>;
@observable downloadBinariesPath!: StoreType<PreferenceDescriptors["downloadBinariesPath"]>;
@observable kubectlBinariesPath!: StoreType<PreferenceDescriptors["kubectlBinariesPath"]>;
@observable terminalCopyOnSelect!: StoreType<PreferenceDescriptors["terminalCopyOnSelect"]>;
@observable terminalConfig!: StoreType<PreferenceDescriptors["terminalConfig"]>;
@observable extensionRegistryUrl!: StoreType<PreferenceDescriptors["extensionRegistryUrl"]>;
/**
* Download kubectl binaries matching cluster version
*/
@observable downloadKubectlBinaries!: StoreType<PreferenceDescriptors["downloadKubectlBinaries"]>;
/**
* Whether the application should open itself at login.
*/
@observable openAtLogin!: StoreType<PreferenceDescriptors["openAtLogin"]>;
/**
* The column IDs under each configurable table ID that have been configured
* to not be shown
*/
@observable hiddenTableColumns!: StoreType<PreferenceDescriptors["hiddenTableColumns"]>;
/**
* Monaco editor configs
*/
@observable editorConfiguration!: StoreType<PreferenceDescriptors["editorConfiguration"]>;
/**
* The set of file/folder paths to be synced
*/
@observable syncKubeconfigEntries!: StoreType<PreferenceDescriptors["syncKubeconfigEntries"]>;
/**
* Checks if a column (by ID) for a table (by ID) is configured to be hidden
* @param tableId The ID of the table to be checked against
* @param columnIds The list of IDs the check if one is hidden
* @returns true if at least one column under the table is set to hidden
*/
isTableColumnHidden(tableId: string, ...columnIds: (string | undefined)[]): boolean {
if (columnIds.length === 0) {
return false;
}
const config = this.hiddenTableColumns.get(tableId);
if (!config) {
return false;
}
return columnIds.some(columnId => columnId && config.has(columnId));
}
/**
* Toggles the hidden configuration of a table's column
*/
toggleTableColumnVisibility(tableId: string, columnId: string) {
toggle(getOrInsertSet(this.hiddenTableColumns, tableId), columnId);
}
resetTheme() {
runInAction(() => {
this.colorTheme = this.dependencies.preferenceDescriptors.colorTheme.fromStore(undefined);
});
}
load() {
this.store.loadAndStartSyncing();
}
}

View File

@ -12,10 +12,10 @@ import { getLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-exten
import { issuesTrackerUrl } from "../../common/vars"; import { issuesTrackerUrl } from "../../common/vars";
import { buildVersionInjectionToken } from "../../common/vars/build-semantic-version.injectable"; import { buildVersionInjectionToken } from "../../common/vars/build-semantic-version.injectable";
import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import enabledExtensionsInjectable from "../../features/extensions/enabled/common/enabled-extensions.injectable"; import enabledExtensionsInjectable from "../../features/extensions/enabled/common/enabled-extensions.injectable";
import userPreferencesStateInjectable from "../../features/user-preferences/common/state.injectable";
const userStore = asLegacyGlobalForExtensionApi(userStoreInjectable); const userStore = asLegacyGlobalForExtensionApi(userPreferencesStateInjectable);
const enabledExtensions = asLegacyGlobalForExtensionApi(enabledExtensionsInjectable); const enabledExtensions = asLegacyGlobalForExtensionApi(enabledExtensionsInjectable);
export const App = { export const App = {

View File

@ -4,8 +4,8 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application";
import initUserStoreInjectable from "../../../../main/stores/init-user-store.injectable";
import clustersPersistentStorageInjectable from "../common/storage.injectable"; import clustersPersistentStorageInjectable from "../common/storage.injectable";
import loadUserPreferencesStorageInjectable from "../../../user-preferences/renderer/load-storage.injectable";
const initClusterStoreInjectable = getInjectable({ const initClusterStoreInjectable = getInjectable({
id: "init-cluster-store", id: "init-cluster-store",
@ -15,7 +15,7 @@ const initClusterStoreInjectable = getInjectable({
storage.loadAndStartSyncing(); storage.loadAndStartSyncing();
}, },
runAfter: initUserStoreInjectable, runAfter: loadUserPreferencesStorageInjectable,
}), }),
injectionToken: beforeApplicationIsLoadingInjectionToken, injectionToken: beforeApplicationIsLoadingInjectionToken,
}); });

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens"; import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
import initUserStoreInjectable from "../../../../renderer/stores/init-user-store.injectable"; import initUserStoreInjectable from "../../../user-preferences/renderer/load-storage.injectable";
import clustersPersistentStorageInjectable from "../common/storage.injectable"; import clustersPersistentStorageInjectable from "../common/storage.injectable";
const initClusterStoreInjectable = getInjectable({ const initClusterStoreInjectable = getInjectable({

View File

@ -6,16 +6,16 @@ import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import { defaultExtensionRegistryUrl, defaultExtensionRegistryUrlLocation } from "../../../../../../common/user-store/preferences-helpers";
import { Input } from "../../../../../../renderer/components/input"; import { Input } from "../../../../../../renderer/components/input";
import { isUrl } from "../../../../../../renderer/components/input/input_validators"; import { isUrl } from "../../../../../../renderer/components/input/input_validators";
import type { UserStore } from "../../../../../../common/user-store";
import { runInAction } from "mobx"; import { runInAction } from "mobx";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
import { defaultExtensionRegistryUrlLocation, defaultExtensionRegistryUrl } from "../../../../../user-preferences/common/preferences-helpers";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const extensionInstallRegistryOptions = [ const extensionInstallRegistryOptions = [
@ -33,8 +33,8 @@ const extensionInstallRegistryOptions = [
}, },
] as const; ] as const;
const NonInjectedExtensionInstallRegistry = observer(({ userStore }: Dependencies) => { const NonInjectedExtensionInstallRegistry = observer(({ state }: Dependencies) => {
const [customUrl, setCustomUrl] = React.useState(userStore.extensionRegistryUrl.customUrl || ""); const [customUrl, setCustomUrl] = React.useState(state.extensionRegistryUrl.customUrl || "");
return ( return (
<section id="extensionRegistryUrl"> <section id="extensionRegistryUrl">
@ -42,14 +42,14 @@ const NonInjectedExtensionInstallRegistry = observer(({ userStore }: Dependencie
<Select <Select
id="extension-install-registry-input" id="extension-install-registry-input"
options={extensionInstallRegistryOptions} options={extensionInstallRegistryOptions}
value={userStore.extensionRegistryUrl.location} value={state.extensionRegistryUrl.location}
onChange={(value) => onChange={(value) =>
runInAction(() => { runInAction(() => {
userStore.extensionRegistryUrl.location = state.extensionRegistryUrl.location =
value?.value ?? defaultExtensionRegistryUrlLocation; value?.value ?? defaultExtensionRegistryUrlLocation;
if (userStore.extensionRegistryUrl.location === "custom") { if (state.extensionRegistryUrl.location === "custom") {
userStore.extensionRegistryUrl.customUrl = ""; state.extensionRegistryUrl.customUrl = "";
} }
}) })
} }
@ -69,20 +69,16 @@ const NonInjectedExtensionInstallRegistry = observer(({ userStore }: Dependencie
validators={isUrl} validators={isUrl}
value={customUrl} value={customUrl}
onChange={setCustomUrl} onChange={setCustomUrl}
onBlur={() => (userStore.extensionRegistryUrl.customUrl = customUrl)} onBlur={() => (state.extensionRegistryUrl.customUrl = customUrl)}
placeholder="Custom Extension Registry URL..." placeholder="Custom Extension Registry URL..."
disabled={userStore.extensionRegistryUrl.location !== "custom"} disabled={state.extensionRegistryUrl.location !== "custom"}
/> />
</section> </section>
); );
}); });
export const ExtensionInstallRegistry = withInjectables<Dependencies>( export const ExtensionInstallRegistry = withInjectables<Dependencies>(NonInjectedExtensionInstallRegistry, {
NonInjectedExtensionInstallRegistry, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,33 +5,29 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Switch } from "../../../../../../renderer/components/switch"; import { Switch } from "../../../../../../renderer/components/switch";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedStartUp = observer(({ userStore }: Dependencies) => ( const NonInjectedStartUp = observer(({ state }: Dependencies) => (
<section id="other"> <section id="other">
<SubTitle title="Start-up" /> <SubTitle title="Start-up" />
<Switch <Switch
checked={userStore.openAtLogin} checked={state.openAtLogin}
onChange={() => (userStore.openAtLogin = !userStore.openAtLogin)} onChange={() => (state.openAtLogin = !state.openAtLogin)}
> >
Automatically start Lens on login Automatically start Lens on login
</Switch> </Switch>
</section> </section>
)); ));
export const StartUp = withInjectables<Dependencies>( export const StartUp = withInjectables<Dependencies>(NonInjectedStartUp, {
NonInjectedStartUp, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -7,26 +7,26 @@ import { SubTitle } from "../../../../../../renderer/components/layout/sub-title
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserStore } from "../../../../../../common/user-store";
import type { LensTheme } from "../../../../../../renderer/themes/lens-theme"; import type { LensTheme } from "../../../../../../renderer/themes/lens-theme";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import defaultLensThemeInjectable from "../../../../../../renderer/themes/default-theme.injectable"; import defaultLensThemeInjectable from "../../../../../../renderer/themes/default-theme.injectable";
import { lensThemeDeclarationInjectionToken } from "../../../../../../renderer/themes/declaration"; import { lensThemeDeclarationInjectionToken } from "../../../../../../renderer/themes/declaration";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
defaultTheme: LensTheme; defaultTheme: LensTheme;
themes: LensTheme[]; themes: LensTheme[];
} }
const NonInjectedTheme = observer(({ const NonInjectedTheme = observer(({
userStore, state,
themes, themes,
defaultTheme, defaultTheme,
}: Dependencies) => { }: Dependencies) => {
const themeOptions = [ const themeOptions = [
{ {
value: "system", // TODO: replace with a sentinal value that isn't string (and serialize it differently) value: "system", // TODO: replace with a sentinel value that isn't string (and serialize it differently)
label: "Sync with computer", label: "Sync with computer",
}, },
...themes.map(theme => ({ ...themes.map(theme => ({
@ -41,9 +41,9 @@ const NonInjectedTheme = observer(({
<Select <Select
id="theme-input" id="theme-input"
options={themeOptions} options={themeOptions}
value={userStore.colorTheme} value={state.colorTheme}
onChange={(value) => onChange={(value) =>
(userStore.colorTheme = value?.value ?? defaultTheme.name) (state.colorTheme = value?.value ?? defaultTheme.name)
} }
themeName="lens" themeName="lens"
/> />
@ -53,7 +53,7 @@ const NonInjectedTheme = observer(({
export const Theme = withInjectables<Dependencies>(NonInjectedTheme, { export const Theme = withInjectables<Dependencies>(NonInjectedTheme, {
getProps: (di) => ({ getProps: (di) => ({
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
defaultTheme: di.inject(defaultLensThemeInjectable), defaultTheme: di.inject(defaultLensThemeInjectable),
themes: di.injectMany(lensThemeDeclarationInjectionToken), themes: di.injectMany(lensThemeDeclarationInjectionToken),
}), }),

View File

@ -5,15 +5,15 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import currentTimezoneInjectable from "../../../../../../common/user-store/current-timezone.injectable"; import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import currentTimezoneInjectable from "../../../../../../common/vars/current-timezone.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
currentTimezone: string; currentTimezone: string;
} }
@ -23,9 +23,8 @@ const timezoneOptions = moment.tz.names()
label: timezone.replace("_", " "), label: timezone.replace("_", " "),
})); }));
const NonInjectedTimezone = observer(({ const NonInjectedTimezone = observer(({
userStore, state,
currentTimezone, currentTimezone,
}: Dependencies) => ( }: Dependencies) => (
<section id="locale"> <section id="locale">
@ -33,17 +32,16 @@ const NonInjectedTimezone = observer(({
<Select <Select
id="timezone-input" id="timezone-input"
options={timezoneOptions} options={timezoneOptions}
value={userStore.localeTimezone} value={state.localeTimezone}
onChange={value => userStore.localeTimezone = value?.value ?? currentTimezone} onChange={value => state.localeTimezone = value?.value ?? currentTimezone}
themeName="lens" themeName="lens"
/> />
</section> </section>
)); ));
export const Timezone = withInjectables<Dependencies>(NonInjectedTimezone, { export const Timezone = withInjectables<Dependencies>(NonInjectedTimezone, {
getProps: (di) => ({ getProps: (di) => ({
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
currentTimezone: di.inject(currentTimezoneInjectable), currentTimezone: di.inject(currentTimezoneInjectable),
}), }),
}); });

View File

@ -5,16 +5,16 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Input } from "../../../../../../renderer/components/input"; import { Input } from "../../../../../../renderer/components/input";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedEditorFontFamily = observer(({ userStore: { editorConfiguration }}: Dependencies) => ( const NonInjectedEditorFontFamily = observer(({ state: { editorConfiguration }}: Dependencies) => (
<section> <section>
<SubTitle title="Font family" /> <SubTitle title="Font family" />
<Input <Input
@ -26,12 +26,8 @@ const NonInjectedEditorFontFamily = observer(({ userStore: { editorConfiguration
</section> </section>
)); ));
export const EditorFontFamily = withInjectables<Dependencies>( export const EditorFontFamily = withInjectables<Dependencies>(NonInjectedEditorFontFamily, {
NonInjectedEditorFontFamily, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,16 +5,16 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Input, InputValidators } from "../../../../../../renderer/components/input"; import { Input, InputValidators } from "../../../../../../renderer/components/input";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedEditorFontSize = observer(({ userStore: { editorConfiguration }}: Dependencies) => ( const NonInjectedEditorFontSize = observer(({ state: { editorConfiguration }}: Dependencies) => (
<section> <section>
<SubTitle title="Font size" /> <SubTitle title="Font size" />
<Input <Input
@ -28,12 +28,8 @@ const NonInjectedEditorFontSize = observer(({ userStore: { editorConfiguration }
</section> </section>
)); ));
export const EditorFontSize = withInjectables<Dependencies>( export const EditorFontSize = withInjectables<Dependencies>(NonInjectedEditorFontSize, {
NonInjectedEditorFontSize, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,15 +5,15 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import { defaultEditorConfig } from "../../../../../../common/user-store/preferences-helpers";
import { capitalize } from "lodash/fp"; import { capitalize } from "lodash/fp";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import { defaultEditorConfig } from "../../../../../user-preferences/common/preferences-helpers";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const lineNumberOptions = ([ const lineNumberOptions = ([
@ -26,7 +26,7 @@ const lineNumberOptions = ([
label: capitalize(lineNumbers), label: capitalize(lineNumbers),
})); }));
const NonInjectedLineNumbers = observer(({ userStore: { editorConfiguration }}: Dependencies) => ( const NonInjectedLineNumbers = observer(({ state: { editorConfiguration }}: Dependencies) => (
<section> <section>
<SubTitle title="Line numbers"/> <SubTitle title="Line numbers"/>
<Select <Select
@ -37,15 +37,10 @@ const NonInjectedLineNumbers = observer(({ userStore: { editorConfiguration }}:
themeName="lens" themeName="lens"
/> />
</section> </section>
)); ));
export const LineNumbers = withInjectables<Dependencies>( export const LineNumbers = withInjectables<Dependencies>(NonInjectedLineNumbers, {
NonInjectedLineNumbers, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,15 +5,15 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Switch } from "../../../../../../renderer/components/switch"; import { Switch } from "../../../../../../renderer/components/switch";
import { SubHeader } from "../../../../../../renderer/components/layout/sub-header"; import { SubHeader } from "../../../../../../renderer/components/layout/sub-header";
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const minimapPositionOptions = (["left", "right"] as const) const minimapPositionOptions = (["left", "right"] as const)
@ -23,7 +23,7 @@ const minimapPositionOptions = (["left", "right"] as const)
})); }));
const NonInjectedMinimap = observer(({ userStore: { editorConfiguration }}: Dependencies) => ( const NonInjectedMinimap = observer(({ state: { editorConfiguration }}: Dependencies) => (
<section> <section>
<SubTitle title="Minimap"/> <SubTitle title="Minimap"/>
@ -50,12 +50,8 @@ const NonInjectedMinimap = observer(({ userStore: { editorConfiguration }}: Depe
</section> </section>
)); ));
export const Minimap = withInjectables<Dependencies>( export const Minimap = withInjectables<Dependencies>(NonInjectedMinimap, {
NonInjectedMinimap, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,16 +5,16 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { Input, InputValidators } from "../../../../../../renderer/components/input"; import { Input, InputValidators } from "../../../../../../renderer/components/input";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedTabSize = observer(({ userStore: { editorConfiguration }}: Dependencies) => ( const NonInjectedTabSize = observer(({ state: { editorConfiguration }}: Dependencies) => (
<section> <section>
<SubTitle title="Tab size" /> <SubTitle title="Tab size" />
<Input <Input
@ -28,12 +28,8 @@ const NonInjectedTabSize = observer(({ userStore: { editorConfiguration }}: Depe
</section> </section>
)); ));
export const TabSize = withInjectables<Dependencies>( export const TabSize = withInjectables<Dependencies>(NonInjectedTabSize, {
NonInjectedTabSize, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -7,13 +7,11 @@ import { computed, makeObservable, observable, reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import React from "react"; import React from "react";
import { Notice } from "../../../../../../renderer/components/+extensions/notice"; import { Notice } from "../../../../../../renderer/components/+extensions/notice";
import type { UserStore } from "../../../../../../common/user-store";
import { iter, tuple } from "@k8slens/utilities"; import { iter, tuple } from "@k8slens/utilities";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { PathPicker } from "../../../../../../renderer/components/path-picker/path-picker"; import { PathPicker } from "../../../../../../renderer/components/path-picker/path-picker";
import { Spinner } from "../../../../../../renderer/components/spinner"; import { Spinner } from "../../../../../../renderer/components/spinner";
import { RemovableItem } from "../../../removable-item/removable-item"; import { RemovableItem } from "../../../removable-item/removable-item";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import isWindowsInjectable from "../../../../../../common/vars/is-windows.injectable"; import isWindowsInjectable from "../../../../../../common/vars/is-windows.injectable";
import loggerInjectable from "../../../../../../common/logger.injectable"; import loggerInjectable from "../../../../../../common/logger.injectable";
import type { Logger } from "../../../../../../common/logger"; import type { Logger } from "../../../../../../common/logger";
@ -21,13 +19,15 @@ import type { DiscoverAllKubeconfigSyncKinds } from "./discover-all-sync-kinds.i
import type { DiscoverKubeconfigSyncKind, SyncKind } from "./discover-sync-kind.injectable"; import type { DiscoverKubeconfigSyncKind, SyncKind } from "./discover-sync-kind.injectable";
import discoverKubeconfigSyncKindInjectable from "./discover-sync-kind.injectable"; import discoverKubeconfigSyncKindInjectable from "./discover-sync-kind.injectable";
import discoverAllKubeconfigSyncKindsInjectable from "./discover-all-sync-kinds.injectable"; import discoverAllKubeconfigSyncKindsInjectable from "./discover-all-sync-kinds.injectable";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Entry extends SyncKind { interface Entry extends SyncKind {
filePath: string; filePath: string;
} }
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
isWindows: boolean; isWindows: boolean;
logger: Logger; logger: Logger;
discoverAllKubeconfigSyncKinds: DiscoverAllKubeconfigSyncKinds; discoverAllKubeconfigSyncKinds: DiscoverAllKubeconfigSyncKinds;
@ -47,7 +47,7 @@ class NonInjectedKubeconfigSync extends React.Component<Dependencies> {
async componentDidMount() { async componentDidMount() {
const mapEntries = await Promise.all( const mapEntries = await Promise.all(
iter.map( iter.map(
this.props.userStore.syncKubeconfigEntries, this.props.state.syncKubeconfigEntries,
([filePath]) => this.props.discoverKubeconfigSyncKind(filePath), ([filePath]) => this.props.discoverKubeconfigSyncKind(filePath),
), ),
); );
@ -59,7 +59,7 @@ class NonInjectedKubeconfigSync extends React.Component<Dependencies> {
reaction( reaction(
() => Array.from(this.syncs.entries(), ([filePath, kind]) => tuple.from(filePath, kind)), () => Array.from(this.syncs.entries(), ([filePath, kind]) => tuple.from(filePath, kind)),
syncs => { syncs => {
this.props.userStore.syncKubeconfigEntries.replace(syncs); this.props.state.syncKubeconfigEntries.replace(syncs);
}, },
), ),
]); ]);
@ -177,7 +177,7 @@ class NonInjectedKubeconfigSync extends React.Component<Dependencies> {
export const KubeconfigSync = withInjectables<Dependencies>(NonInjectedKubeconfigSync, { export const KubeconfigSync = withInjectables<Dependencies>(NonInjectedKubeconfigSync, {
getProps: (di) => ({ getProps: (di) => ({
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
isWindows: di.inject(isWindowsInjectable), isWindows: di.inject(isWindowsInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
discoverAllKubeconfigSyncKinds: di.inject(discoverAllKubeconfigSyncKindsInjectable), discoverAllKubeconfigSyncKinds: di.inject(discoverAllKubeconfigSyncKindsInjectable),

View File

@ -5,34 +5,29 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Switch } from "../../../../../../../renderer/components/switch"; import { Switch } from "../../../../../../../renderer/components/switch";
import type { UserPreferencesState } from "../../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedKubectlBinaryDownload = observer(({ userStore }: Dependencies) => ( const NonInjectedKubectlBinaryDownload = observer(({ state }: Dependencies) => (
<section> <section>
<SubTitle title="Kubectl binary download" /> <SubTitle title="Kubectl binary download" />
<Switch <Switch
checked={userStore.downloadKubectlBinaries} checked={state.downloadKubectlBinaries}
onChange={() => userStore.downloadKubectlBinaries = !userStore.downloadKubectlBinaries} onChange={() => state.downloadKubectlBinaries = !state.downloadKubectlBinaries}
> >
Download kubectl binaries matching the Kubernetes cluster version Download kubectl binaries matching the Kubernetes cluster version
</Switch> </Switch>
</section> </section>
)); ));
export const KubectlBinaryDownload = withInjectables<Dependencies>( export const KubectlBinaryDownload = withInjectables<Dependencies>(NonInjectedKubectlBinaryDownload, {
NonInjectedKubectlBinaryDownload, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,24 +5,24 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Input, InputValidators } from "../../../../../../../renderer/components/input"; import { Input, InputValidators } from "../../../../../../../renderer/components/input";
import directoryForBinariesInjectable from "../../../../../../../common/app-paths/directory-for-binaries/directory-for-binaries.injectable"; import directoryForBinariesInjectable from "../../../../../../../common/app-paths/directory-for-binaries/directory-for-binaries.injectable";
import type { UserPreferencesState } from "../../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
defaultPathForGeneralBinaries: string; defaultPathForGeneralBinaries: string;
} }
const NonInjectedKubectlDirectoryForBinaries = observer( const NonInjectedKubectlDirectoryForBinaries = observer(
({ userStore, defaultPathForGeneralBinaries }: Dependencies) => { ({ state, defaultPathForGeneralBinaries }: Dependencies) => {
const [downloadPath, setDownloadPath] = useState(userStore.downloadBinariesPath || ""); const [downloadPath, setDownloadPath] = useState(state.downloadBinariesPath || "");
const pathValidator = downloadPath ? InputValidators.isPath : undefined; const pathValidator = downloadPath ? InputValidators.isPath : undefined;
const save = () => { const save = () => {
userStore.downloadBinariesPath = downloadPath; state.downloadBinariesPath = downloadPath;
}; };
return ( return (
@ -35,7 +35,7 @@ const NonInjectedKubectlDirectoryForBinaries = observer(
validators={pathValidator} validators={pathValidator}
onChange={setDownloadPath} onChange={setDownloadPath}
onBlur={save} onBlur={save}
disabled={!userStore.downloadKubectlBinaries} disabled={!state.downloadKubectlBinaries}
/> />
<div className="hint">The directory to download binaries into.</div> <div className="hint">The directory to download binaries into.</div>
</section> </section>
@ -43,13 +43,9 @@ const NonInjectedKubectlDirectoryForBinaries = observer(
}, },
); );
export const KubectlDirectoryForBinaries = withInjectables<Dependencies>( export const KubectlDirectoryForBinaries = withInjectables<Dependencies>(NonInjectedKubectlDirectoryForBinaries, {
NonInjectedKubectlDirectoryForBinaries, getProps: (di) => ({
defaultPathForGeneralBinaries: di.inject(directoryForBinariesInjectable),
{ state: di.inject(userPreferencesStateInjectable),
getProps: (di) => ({ }),
defaultPathForGeneralBinaries: di.inject(directoryForBinariesInjectable), });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,14 +5,14 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Select } from "../../../../../../../renderer/components/select"; import { Select } from "../../../../../../../renderer/components/select";
import { defaultPackageMirror, packageMirrors } from "../../../../../../../common/user-store/preferences-helpers"; import { defaultPackageMirror, packageMirrors } from "../../../../../../user-preferences/common/preferences-helpers";
import type { UserPreferencesState } from "../../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const downloadMirrorOptions = Array.from(packageMirrors, ([name, mirror]) => ({ const downloadMirrorOptions = Array.from(packageMirrors, ([name, mirror]) => ({
@ -24,27 +24,23 @@ const downloadMirrorOptions = Array.from(packageMirrors, ([name, mirror]) => ({
})); }));
const NonInjectedKubectlDownloadMirror = observer(({ userStore }: Dependencies) => ( const NonInjectedKubectlDownloadMirror = observer(({ state }: Dependencies) => (
<section> <section>
<SubTitle title="Download mirror" /> <SubTitle title="Download mirror" />
<Select <Select
id="download-mirror-input" id="download-mirror-input"
placeholder="Download mirror for kubectl" placeholder="Download mirror for kubectl"
options={downloadMirrorOptions} options={downloadMirrorOptions}
value={userStore.downloadMirror} value={state.downloadMirror}
onChange={option => userStore.downloadMirror = option?.value ?? defaultPackageMirror} onChange={option => state.downloadMirror = option?.value ?? defaultPackageMirror}
isDisabled={!userStore.downloadKubectlBinaries} isDisabled={!state.downloadKubectlBinaries}
themeName="lens" themeName="lens"
/> />
</section> </section>
)); ));
export const KubectlDownloadMirror = withInjectables<Dependencies>( export const KubectlDownloadMirror = withInjectables<Dependencies>(NonInjectedKubectlDownloadMirror, {
NonInjectedKubectlDownloadMirror, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,50 +5,48 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Input, InputValidators } from "../../../../../../../renderer/components/input"; import { Input, InputValidators } from "../../../../../../../renderer/components/input";
import directoryForKubectlBinariesInjectable from "../../../../../../../common/app-paths/directory-for-kubectl-binaries/directory-for-kubectl-binaries.injectable"; import directoryForKubectlBinariesInjectable from "../../../../../../../common/app-paths/directory-for-kubectl-binaries/directory-for-kubectl-binaries.injectable";
import type { UserPreferencesState } from "../../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
defaultPathForKubectlBinaries: string; defaultPathForKubectlBinaries: string;
} }
const NonInjectedKubectlPathToBinary = observer( const NonInjectedKubectlPathToBinary = observer(({
({ userStore, defaultPathForKubectlBinaries }: Dependencies) => { state,
const [binariesPath, setBinariesPath] = useState(userStore.kubectlBinariesPath || ""); defaultPathForKubectlBinaries,
const pathValidator = binariesPath ? InputValidators.isPath : undefined; }: Dependencies) => {
const [binariesPath, setBinariesPath] = useState(state.kubectlBinariesPath || "");
const pathValidator = binariesPath ? InputValidators.isPath : undefined;
const save = () => { const save = () => {
userStore.kubectlBinariesPath = binariesPath; state.kubectlBinariesPath = binariesPath;
}; };
return ( return (
<section> <section>
<SubTitle title="Path to kubectl binary" /> <SubTitle title="Path to kubectl binary" />
<Input <Input
theme="round-black" theme="round-black"
placeholder={defaultPathForKubectlBinaries} placeholder={defaultPathForKubectlBinaries}
value={binariesPath} value={binariesPath}
validators={pathValidator} validators={pathValidator}
onChange={setBinariesPath} onChange={setBinariesPath}
onBlur={save} onBlur={save}
disabled={userStore.downloadKubectlBinaries} disabled={state.downloadKubectlBinaries}
/> />
</section> </section>
); );
}, },
); );
export const KubectlPathToBinary = withInjectables<Dependencies>( export const KubectlPathToBinary = withInjectables<Dependencies>(NonInjectedKubectlPathToBinary, {
NonInjectedKubectlPathToBinary, getProps: (di) => ({
defaultPathForKubectlBinaries: di.inject(directoryForKubectlBinariesInjectable),
{ state: di.inject(userPreferencesStateInjectable),
getProps: (di) => ({ }),
defaultPathForKubectlBinaries: di.inject(directoryForKubectlBinariesInjectable), });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,23 +5,21 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Switch } from "../../../../../../renderer/components/switch"; import { Switch } from "../../../../../../renderer/components/switch";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedAllowUntrustedCertificates = observer(({ userStore }: Dependencies) => ( const NonInjectedAllowUntrustedCertificates = observer(({ state }: Dependencies) => (
<section className="small"> <section className="small">
<SubTitle title="Certificate Trust" /> <SubTitle title="Certificate Trust" />
<Switch <Switch
checked={userStore.allowUntrustedCAs} checked={state.allowUntrustedCAs}
onChange={() => onChange={() => state.allowUntrustedCAs = !state.allowUntrustedCAs}
(userStore.allowUntrustedCAs = !userStore.allowUntrustedCAs)
}
> >
Allow untrusted Certificate Authorities Allow untrusted Certificate Authorities
</Switch> </Switch>
@ -33,12 +31,8 @@ const NonInjectedAllowUntrustedCertificates = observer(({ userStore }: Dependenc
</section> </section>
)); ));
export const AllowUntrustedCertificates = withInjectables<Dependencies>( export const AllowUntrustedCertificates = withInjectables<Dependencies>(NonInjectedAllowUntrustedCertificates, {
NonInjectedAllowUntrustedCertificates, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,43 +5,39 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Input } from "../../../../../../renderer/components/input"; import { Input } from "../../../../../../renderer/components/input";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedHttpProxyUrl = observer( const NonInjectedHttpProxyUrl = observer(({
({ userStore }: Dependencies) => { state,
const [proxy, setProxy] = React.useState(userStore.httpsProxy || ""); }: Dependencies) => {
const [proxy, setProxy] = React.useState(state.httpsProxy || "");
return ( return (
<section> <section>
<SubTitle title="HTTP Proxy" /> <SubTitle title="HTTP Proxy" />
<Input <Input
theme="round-black" theme="round-black"
placeholder="Type HTTP proxy url (example: http://proxy.acme.org:8080)" placeholder="Type HTTP proxy url (example: http://proxy.acme.org:8080)"
value={proxy} value={proxy}
onChange={(v) => setProxy(v)} onChange={(v) => setProxy(v)}
onBlur={() => (userStore.httpsProxy = proxy)} onBlur={() => (state.httpsProxy = proxy)}
/> />
<small className="hint"> <small className="hint">
Proxy is used only for non-cluster communication. Proxy is used only for non-cluster communication.
</small> </small>
</section> </section>
); );
}, });
);
export const HttpProxyUrl = withInjectables<Dependencies>( export const HttpProxyUrl = withInjectables<Dependencies>(NonInjectedHttpProxyUrl, {
NonInjectedHttpProxyUrl, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,16 +5,16 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Checkbox } from "../../../../../../renderer/components/checkbox"; import { Checkbox } from "../../../../../../renderer/components/checkbox";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedAutomaticErrorReporting = observer(({ userStore }: Dependencies) => ( const NonInjectedAutomaticErrorReporting = observer(({ state }: Dependencies) => (
<div <div
id="sentry" id="sentry"
className="small" className="small"
@ -23,8 +23,8 @@ const NonInjectedAutomaticErrorReporting = observer(({ userStore }: Dependencies
<SubTitle title="Automatic Error Reporting" /> <SubTitle title="Automatic Error Reporting" />
<Checkbox <Checkbox
label="Allow automatic error reporting" label="Allow automatic error reporting"
value={userStore.allowErrorReporting} value={state.allowErrorReporting}
onChange={(value) => (userStore.allowErrorReporting = value)} onChange={(value) => (state.allowErrorReporting = value)}
/> />
<div className="hint"> <div className="hint">
<span> <span>
@ -36,12 +36,8 @@ const NonInjectedAutomaticErrorReporting = observer(({ userStore }: Dependencies
</div> </div>
)); ));
export const AutomaticErrorReporting = withInjectables<Dependencies>( export const AutomaticErrorReporting = withInjectables<Dependencies>(NonInjectedAutomaticErrorReporting, {
NonInjectedAutomaticErrorReporting, getProps: (di) => ({
state: di.inject(userPreferencesStateInjectable),
{ }),
getProps: (di) => ({ });
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,38 +5,31 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Switch } from "../../../../../../renderer/components/switch"; import { Switch } from "../../../../../../renderer/components/switch";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedCopyPasteFromTerminal = observer( const NonInjectedCopyPasteFromTerminal = observer(({
({ userStore }: Dependencies) => { state,
}: Dependencies) => (
<section id="terminalSelection">
<SubTitle title="Terminal copy & paste" />
<Switch
checked={state.terminalCopyOnSelect}
onChange={() => state.terminalCopyOnSelect = !state.terminalCopyOnSelect}
>
Copy on select and paste on right-click
</Switch>
</section>
));
return ( export const CopyPasteFromTerminal = withInjectables<Dependencies>(NonInjectedCopyPasteFromTerminal, {
<section id="terminalSelection"> getProps: (di) => ({
<SubTitle title="Terminal copy & paste" /> state: di.inject(userPreferencesStateInjectable),
<Switch }),
checked={userStore.terminalCopyOnSelect} });
onChange={() => userStore.terminalCopyOnSelect = !userStore.terminalCopyOnSelect}
>
Copy on select and paste on right-click
</Switch>
</section>
);
},
);
export const CopyPasteFromTerminal = withInjectables<Dependencies>(
NonInjectedCopyPasteFromTerminal,
{
getProps: (di) => ({
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -7,10 +7,10 @@ import type { IComputedValue } from "mobx";
import { action, computed } from "mobx"; import { action, computed } from "mobx";
import React from "react"; import React from "react";
import type { SingleValue } from "react-select"; import type { SingleValue } from "react-select";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { defaultTerminalFontFamily } from "../../../../../../common/vars"; import { defaultTerminalFontFamily } from "../../../../../../common/vars";
import type { SelectOption } from "../../../../../../renderer/components/select"; import type { SelectOption } from "../../../../../../renderer/components/select";
import { terminalFontInjectionToken } from "../../../../../terminal/renderer/fonts/token"; import { terminalFontInjectionToken } from "../../../../../terminal/renderer/fonts/token";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
export interface TerminalFontPreferencePresenter { export interface TerminalFontPreferencePresenter {
readonly options: IComputedValue<SelectOption<string>[]>; readonly options: IComputedValue<SelectOption<string>[]>;
@ -21,7 +21,7 @@ export interface TerminalFontPreferencePresenter {
const terminalFontPreferencePresenterInjectable = getInjectable({ const terminalFontPreferencePresenterInjectable = getInjectable({
id: "terminal-font-preference-presenter", id: "terminal-font-preference-presenter",
instantiate: (di): TerminalFontPreferencePresenter => { instantiate: (di): TerminalFontPreferencePresenter => {
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
const terminalFonts = di.injectMany(terminalFontInjectionToken); const terminalFonts = di.injectMany(terminalFontInjectionToken);
return { return {
@ -30,18 +30,18 @@ const terminalFontPreferencePresenterInjectable = getInjectable({
<span <span
style={{ style={{
fontFamily: `${font.name}, var(--font-terminal)`, fontFamily: `${font.name}, var(--font-terminal)`,
fontSize: userStore.terminalConfig.fontSize, fontSize: state.terminalConfig.fontSize,
}} }}
> >
{font.name} {font.name}
</span> </span>
), ),
value: font.name, value: font.name,
isSelected: userStore.terminalConfig.fontFamily === font.name, isSelected: state.terminalConfig.fontFamily === font.name,
}))), }))),
current: computed(() => userStore.terminalConfig.fontFamily), current: computed(() => state.terminalConfig.fontFamily),
onSelection: action(selection => { onSelection: action(selection => {
userStore.terminalConfig.fontFamily = selection?.value ?? defaultTerminalFontFamily; state.terminalConfig.fontFamily = selection?.value ?? defaultTerminalFontFamily;
}), }),
}; };
}, },

View File

@ -5,40 +5,32 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Input } from "../../../../../../renderer/components/input"; import { Input } from "../../../../../../renderer/components/input";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedTerminalFontSize = observer( const NonInjectedTerminalFontSize = observer(({
({ userStore }: Dependencies) => { state,
}: Dependencies) => (
<section>
<SubTitle title="Font size" />
<Input
theme="round-black"
type="number"
min={10}
max={50}
defaultValue={state.terminalConfig.fontSize.toString()}
onChange={(value) => state.terminalConfig.fontSize = Number(value)} />
</section>
));
return ( export const TerminalFontSize = withInjectables<Dependencies>(NonInjectedTerminalFontSize, {
<section> getProps: (di) => ({
<SubTitle title="Font size" /> state: di.inject(userPreferencesStateInjectable),
<Input }),
theme="round-black" });
type="number"
min={10}
max={50}
defaultValue={userStore.terminalConfig.fontSize.toString()}
onChange={(value) => userStore.terminalConfig.fontSize = Number(value)}
/>
</section>
);
},
);
export const TerminalFontSize = withInjectables<Dependencies>(
NonInjectedTerminalFontSize,
{
getProps: (di) => ({
userStore: di.inject(userStoreInjectable),
}),
},
);

View File

@ -5,42 +5,35 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Input } from "../../../../../../renderer/components/input"; import { Input } from "../../../../../../renderer/components/input";
import defaultShellInjectable from "./default-shell/default-shell.injectable"; import defaultShellInjectable from "./default-shell/default-shell.injectable";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
defaultShell: string; defaultShell: string;
} }
const NonInjectedTerminalShellPath = observer( const NonInjectedTerminalShellPath = observer(({
({ userStore, defaultShell }: Dependencies) => { state,
defaultShell,
}: Dependencies) => (
<section id="shell">
<SubTitle title="Terminal Shell Path" />
<Input
theme="round-black"
placeholder={defaultShell}
value={state.shell ?? ""}
onChange={(value) => state.shell = value}
/>
</section>
));
return ( export const TerminalShellPath = withInjectables<Dependencies>(NonInjectedTerminalShellPath, {
<section id="shell"> getProps: (di) => ({
<SubTitle title="Terminal Shell Path" /> state: di.inject(userPreferencesStateInjectable),
<Input defaultShell: di.inject(defaultShellInjectable),
theme="round-black" }),
placeholder={defaultShell} });
value={userStore.shell ?? ""}
onChange={(value) => userStore.shell = value}
/>
</section>
);
},
);
export const TerminalShellPath = withInjectables<Dependencies>(
NonInjectedTerminalShellPath,
{
getProps: (di) => ({
userStore: di.inject(userStoreInjectable),
defaultShell: di.inject(defaultShellInjectable),
}),
},
);

View File

@ -5,26 +5,25 @@
import React from "react"; import React from "react";
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import type { LensTheme } from "../../../../../../renderer/themes/lens-theme"; import type { LensTheme } from "../../../../../../renderer/themes/lens-theme";
import { lensThemeDeclarationInjectionToken } from "../../../../../../renderer/themes/declaration"; import { lensThemeDeclarationInjectionToken } from "../../../../../../renderer/themes/declaration";
import type { UserPreferencesState } from "../../../../../user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../../user-preferences/common/state.injectable";
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
themes: LensTheme[]; themes: LensTheme[];
} }
const NonInjectedTerminalTheme = observer(({ const NonInjectedTerminalTheme = observer(({
userStore, state,
themes, themes,
}: Dependencies) => { }: Dependencies) => {
const themeOptions = [ const themeOptions = [
{ {
value: "", // TODO: replace with a sentinal value that isn't string (and serialize it differently) value: "", // TODO: replace with a sentinel value that isn't string (and serialize it differently)
label: "Match Lens Theme", label: "Match Lens Theme",
}, },
...themes.map(theme => ({ ...themes.map(theme => ({
@ -40,8 +39,8 @@ const NonInjectedTerminalTheme = observer(({
id="terminal-theme-input" id="terminal-theme-input"
themeName="lens" themeName="lens"
options={themeOptions} options={themeOptions}
value={userStore.terminalTheme} value={state.terminalTheme}
onChange={option => userStore.terminalTheme = option?.value ?? ""} onChange={option => state.terminalTheme = option?.value ?? ""}
/> />
</section> </section>
); );
@ -50,7 +49,7 @@ const NonInjectedTerminalTheme = observer(({
export const TerminalTheme = withInjectables<Dependencies>(NonInjectedTerminalTheme, { export const TerminalTheme = withInjectables<Dependencies>(NonInjectedTerminalTheme, {
getProps: (di) => ({ getProps: (di) => ({
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
themes: di.injectMany(lensThemeDeclarationInjectionToken), themes: di.injectMany(lensThemeDeclarationInjectionToken),
}), }),
}); });

View File

@ -8,9 +8,9 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable"; import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable";
import electronAppInjectable from "../../../main/electron-app/electron-app.injectable"; import electronAppInjectable from "../../../main/electron-app/electron-app.injectable";
import computeShellEnvironmentInjectable from "./compute-shell-environment.injectable"; import computeShellEnvironmentInjectable from "./compute-shell-environment.injectable";
import userShellSettingInjectable from "../../../common/user-store/shell-setting.injectable";
import emitShellSyncFailedInjectable from "./emit-failure.injectable"; import emitShellSyncFailedInjectable from "./emit-failure.injectable";
import { unionPATHs } from "@k8slens/utilities"; import { unionPATHs } from "@k8slens/utilities";
import userShellSettingInjectable from "../../user-preferences/common/shell-setting.injectable";
const setupShellInjectable = getInjectable({ const setupShellInjectable = getInjectable({
id: "setup-shell", id: "setup-shell",

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens"; import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
import initUserStoreInjectable from "../../../../renderer/stores/init-user-store.injectable"; import initUserStoreInjectable from "../../../user-preferences/renderer/load-storage.injectable";
import systemThemeConfigurationInjectable from "../../../../renderer/themes/system-theme.injectable"; import systemThemeConfigurationInjectable from "../../../../renderer/themes/system-theme.injectable";
import requestInitialSystemThemeTypeInjectable from "./request-initial.injectable"; import requestInitialSystemThemeTypeInjectable from "./request-initial.injectable";

View File

@ -4,12 +4,12 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable"; import userPreferencesStateInjectable from "./state.injectable";
const httpsProxyConfigurationInjectable = getInjectable({ const httpsProxyConfigurationInjectable = getInjectable({
id: "https-proxy-configuration", id: "https-proxy-configuration",
instantiate: (di) => { instantiate: (di) => {
const userStore = di.inject(userStoreInjectable); const userStore = di.inject(userPreferencesStateInjectable);
return computed(() => userStore.httpsProxy); return computed(() => userStore.httpsProxy);
}, },

View File

@ -0,0 +1,38 @@
/**
* 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 userPreferencesStateInjectable from "./state.injectable";
/**
* Checks if a column (by ID) for a table (by ID) is configured to be hidden
* @param tableId The ID of the table to be checked against
* @param columnIds The list of IDs the check if one is hidden
* @returns true if at least one column under the table is set to hidden
*/
export type IsTableColumnHidden = (tableId: string, ...columnIds: (string | undefined)[]) => boolean;
const isTableColumnHiddenInjectable = getInjectable({
id: "is-table-column-hidden",
instantiate: (di): IsTableColumnHidden => {
const state = di.inject(userPreferencesStateInjectable);
return (tableId, ...columnIds) => {
if (columnIds.length === 0) {
return false;
}
const config = state.hiddenTableColumns.get(tableId);
if (!config) {
return false;
}
return columnIds.some(columnId => columnId && config.has(columnId));
};
},
});
export default isTableColumnHiddenInjectable;

View File

@ -3,11 +3,11 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import userStoreInjectable from "./user-store.injectable"; import userPreferencesStateInjectable from "./state.injectable";
const kubeconfigSyncsInjectable = getInjectable({ const kubeconfigSyncsInjectable = getInjectable({
id: "kubeconfig-syncs", id: "kubeconfig-syncs",
instantiate: (di) => di.inject(userStoreInjectable).syncKubeconfigEntries, instantiate: (di) => di.inject(userPreferencesStateInjectable).syncKubeconfigEntries,
}); });
export default kubeconfigSyncsInjectable; export default kubeconfigSyncsInjectable;

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable"; import userPreferencesStateInjectable from "./state.injectable";
export type LensColorThemePreference = { export type LensColorThemePreference = {
useSystemTheme: true; useSystemTheme: true;
@ -16,11 +16,11 @@ export type LensColorThemePreference = {
const lensColorThemePreferenceInjectable = getInjectable({ const lensColorThemePreferenceInjectable = getInjectable({
id: "lens-color-theme-preference", id: "lens-color-theme-preference",
instantiate: (di) => { instantiate: (di) => {
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
return computed((): LensColorThemePreference => { return computed((): LensColorThemePreference => {
// TODO: remove magic strings // TODO: remove magic strings
if (userStore.colorTheme === "system") { if (state.colorTheme === "system") {
return { return {
useSystemTheme: true, useSystemTheme: true,
}; };
@ -28,7 +28,7 @@ const lensColorThemePreferenceInjectable = getInjectable({
return { return {
useSystemTheme: false, useSystemTheme: false,
lensThemeId: userStore.colorTheme, lensThemeId: state.colorTheme,
}; };
}); });
}, },

View File

@ -0,0 +1,11 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { MigrationDeclaration } from "../../../common/persistent-storage/migrations.injectable";
export const userPreferencesMigrationInjectionToken = getInjectionToken<MigrationDeclaration>({
id: "user-preferences-migration-token",
});

View File

@ -6,17 +6,17 @@ import { getInjectable } from "@ogre-tools/injectable";
import { merge } from "lodash"; import { merge } from "lodash";
import type { ObservableMap } from "mobx"; import type { ObservableMap } from "mobx";
import { observable } from "mobx"; import { observable } from "mobx";
import homeDirectoryPathInjectable from "../os/home-directory-path.injectable"; import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable";
import joinPathsInjectable from "../path/join-paths.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import { defaultThemeId } from "../vars"; import { defaultThemeId } from "../../../common/vars";
import currentTimezoneInjectable from "./current-timezone.injectable"; import currentTimezoneInjectable from "../../../common/vars/current-timezone.injectable";
import type { EditorConfiguration, ExtensionRegistry, KubeconfigSyncEntry, KubeconfigSyncValue, TerminalConfig } from "./preferences-helpers"; import type { EditorConfiguration, ExtensionRegistry, KubeconfigSyncEntry, KubeconfigSyncValue, TerminalConfig } from "./preferences-helpers";
import { defaultExtensionRegistryUrlLocation, defaultEditorConfig, defaultTerminalConfig, defaultPackageMirror, getPreferenceDescriptor, packageMirrors } from "./preferences-helpers"; import { defaultExtensionRegistryUrlLocation, defaultEditorConfig, defaultTerminalConfig, defaultPackageMirror, getPreferenceDescriptor, packageMirrors } from "./preferences-helpers";
export type PreferenceDescriptors = ReturnType<typeof userStorePreferenceDescriptorsInjectable["instantiate"]>; export type PreferenceDescriptors = ReturnType<typeof userPreferenceDescriptorsInjectable["instantiate"]>;
const userStorePreferenceDescriptorsInjectable = getInjectable({ const userPreferenceDescriptorsInjectable = getInjectable({
id: "user-store-preference-descriptors", id: "user-preference-descriptors",
instantiate: (di) => { instantiate: (di) => {
const currentTimezone = di.inject(currentTimezoneInjectable); const currentTimezone = di.inject(currentTimezoneInjectable);
const joinPaths = di.inject(joinPathsInjectable); const joinPaths = di.inject(joinPathsInjectable);
@ -140,4 +140,4 @@ const userStorePreferenceDescriptorsInjectable = getInjectable({
}, },
}); });
export default userStorePreferenceDescriptorsInjectable; export default userPreferenceDescriptorsInjectable;

View File

@ -4,7 +4,7 @@
*/ */
import type { editor } from "monaco-editor"; import type { editor } from "monaco-editor";
import { defaultEditorFontFamily, defaultFontSize, defaultTerminalFontFamily } from "../vars"; import { defaultFontSize, defaultTerminalFontFamily, defaultEditorFontFamily } from "../../../common/vars";
import type { PreferenceDescriptors } from "./preference-descriptors.injectable"; import type { PreferenceDescriptors } from "./preference-descriptors.injectable";
export interface KubeconfigSyncEntry extends KubeconfigSyncValue { export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
@ -95,5 +95,5 @@ export type UserStoreFlatModel = {
}; };
export type UserPreferencesModel = { export type UserPreferencesModel = {
[field in keyof PreferenceDescriptors]: PreferencesModelType<field>; [field in keyof PreferenceDescriptors]?: PreferencesModelType<field>;
} & { updateChannel: string }; } & { updateChannel: string };

View File

@ -0,0 +1,24 @@
/**
* 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 { action } from "mobx";
import userPreferenceDescriptorsInjectable from "./preference-descriptors.injectable";
import userPreferencesStateInjectable from "./state.injectable";
export type ResetTheme = () => void;
const resetThemeInjectable = getInjectable({
id: "reset-theme",
instantiate: (di): ResetTheme => {
const state = di.inject(userPreferencesStateInjectable);
const preferenceDescriptors = di.inject(userPreferenceDescriptorsInjectable);
return action(() => {
state.colorTheme = preferenceDescriptors.colorTheme.fromStore(undefined);
});
},
});
export default resetThemeInjectable;

View File

@ -4,16 +4,16 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import userInfoInjectable from "./user-info.injectable"; import userInfoInjectable from "../../../common/vars/user-info.injectable";
import userStoreInjectable from "./user-store.injectable"; import userPreferencesStateInjectable from "./state.injectable";
const userShellSettingInjectable = getInjectable({ const userShellSettingInjectable = getInjectable({
id: "user-shell-setting", id: "user-shell-setting",
instantiate: (di) => { instantiate: (di) => {
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
const userInfo = di.inject(userInfoInjectable); const userInfo = di.inject(userInfoInjectable);
return computed(() => userStore.shell || userInfo.shell); return computed(() => state.shell || userInfo.shell);
}, },
}); });

View File

@ -0,0 +1,19 @@
/**
* 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 { observable } from "mobx";
import type { PreferenceDescriptors } from "./preference-descriptors.injectable";
import type { StoreType } from "./preferences-helpers";
export type UserPreferencesState = {
-readonly [Field in keyof PreferenceDescriptors]: StoreType<PreferenceDescriptors[Field]>;
};
const userPreferencesStateInjectable = getInjectable({
id: "user-preferences-state",
instantiate: () => observable.object({} as UserPreferencesState),
});
export default userPreferencesStateInjectable;

View File

@ -0,0 +1,88 @@
/**
* 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 { action } from "mobx";
import prefixedLoggerInjectable from "../../../common/logger/prefixed-logger.injectable";
import createPersistentStorageInjectable from "../../../common/persistent-storage/create.injectable";
import persistentStorageMigrationsInjectable from "../../../common/persistent-storage/migrations.injectable";
import { userPreferencesMigrationInjectionToken } from "./migrations-token";
import { toJS } from "../../../common/utils";
import storeMigrationVersionInjectable from "../../../common/vars/store-migration-version.injectable";
import selectedUpdateChannelInjectable from "../../application-update/common/selected-update-channel/selected-update-channel.injectable";
import type { ReleaseChannel } from "../../application-update/common/update-channels";
import userPreferencesStateInjectable from "./state.injectable";
import userPreferenceDescriptorsInjectable from "./preference-descriptors.injectable";
import type { UserPreferencesModel } from "./preferences-helpers";
export interface UserStoreModel {
preferences: UserPreferencesModel;
}
const userPreferencesPersistentStorageInjectable = getInjectable({
id: "user-preferences-persistent-storage",
instantiate: (di) => {
const createPersistentStorage = di.inject(createPersistentStorageInjectable);
const logger = di.inject(prefixedLoggerInjectable, "USER-PREFERENCES");
const descriptors = di.inject(userPreferenceDescriptorsInjectable);
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
const state = di.inject(userPreferencesStateInjectable);
return createPersistentStorage<UserStoreModel>({
configName: "lens-user-store",
projectVersion: di.inject(storeMigrationVersionInjectable),
migrations: di.inject(persistentStorageMigrationsInjectable, userPreferencesMigrationInjectionToken),
fromStore: action(({ preferences = {}}) => {
logger.debug("fromStore()", { preferences });
state.allowErrorReporting = descriptors.allowErrorReporting.fromStore(preferences.allowErrorReporting);
state.allowUntrustedCAs = descriptors.allowUntrustedCAs.fromStore(preferences.allowUntrustedCAs);
state.colorTheme = descriptors.colorTheme.fromStore(preferences.colorTheme);
state.downloadBinariesPath = descriptors.downloadBinariesPath.fromStore(preferences.downloadBinariesPath);
state.downloadKubectlBinaries = descriptors.downloadKubectlBinaries.fromStore(preferences.downloadKubectlBinaries);
state.downloadMirror = descriptors.downloadMirror.fromStore(preferences.downloadMirror);
state.editorConfiguration = descriptors.editorConfiguration.fromStore(preferences.editorConfiguration);
state.extensionRegistryUrl = descriptors.extensionRegistryUrl.fromStore(preferences.extensionRegistryUrl);
state.hiddenTableColumns = descriptors.hiddenTableColumns.fromStore(preferences.hiddenTableColumns);
state.httpsProxy = descriptors.httpsProxy.fromStore(preferences.httpsProxy);
state.kubectlBinariesPath = descriptors.kubectlBinariesPath.fromStore(preferences.kubectlBinariesPath);
state.localeTimezone = descriptors.localeTimezone.fromStore(preferences.localeTimezone);
state.openAtLogin = descriptors.openAtLogin.fromStore(preferences.openAtLogin);
state.shell = descriptors.shell.fromStore(preferences.shell);
state.syncKubeconfigEntries = descriptors.syncKubeconfigEntries.fromStore(preferences.syncKubeconfigEntries);
state.terminalConfig = descriptors.terminalConfig.fromStore(preferences.terminalConfig);
state.terminalCopyOnSelect = descriptors.terminalCopyOnSelect.fromStore(preferences.terminalCopyOnSelect);
state.terminalTheme = descriptors.terminalTheme.fromStore(preferences.terminalTheme);
// TODO: Switch to action-based saving instead saving stores by reaction
selectedUpdateChannel.setValue(preferences?.updateChannel as ReleaseChannel);
}),
toJSON: () => toJS({
preferences: {
allowErrorReporting: descriptors.allowErrorReporting.toStore(state.allowErrorReporting),
allowUntrustedCAs: descriptors.allowUntrustedCAs.toStore(state.allowUntrustedCAs),
colorTheme: descriptors.colorTheme.toStore(state.colorTheme),
downloadBinariesPath: descriptors.downloadBinariesPath.toStore(state.downloadBinariesPath),
downloadKubectlBinaries: descriptors.downloadKubectlBinaries.toStore(state.downloadKubectlBinaries),
downloadMirror: descriptors.downloadMirror.toStore(state.downloadMirror),
editorConfiguration: descriptors.editorConfiguration.toStore(state.editorConfiguration),
extensionRegistryUrl: descriptors.extensionRegistryUrl.toStore(state.extensionRegistryUrl),
hiddenTableColumns: descriptors.hiddenTableColumns.toStore(state.hiddenTableColumns),
httpsProxy: descriptors.httpsProxy.toStore(state.httpsProxy),
kubectlBinariesPath: descriptors.kubectlBinariesPath.toStore(state.kubectlBinariesPath),
localeTimezone: descriptors.localeTimezone.toStore(state.localeTimezone),
openAtLogin: descriptors.openAtLogin.toStore(state.openAtLogin),
shell: descriptors.shell.toStore(state.shell),
syncKubeconfigEntries: descriptors.syncKubeconfigEntries.toStore(state.syncKubeconfigEntries),
terminalConfig: descriptors.terminalConfig.toStore(state.terminalConfig),
terminalCopyOnSelect: descriptors.terminalCopyOnSelect.toStore(state.terminalCopyOnSelect),
terminalTheme: descriptors.terminalTheme.toStore(state.terminalTheme),
updateChannel: selectedUpdateChannel.value.get().id,
},
}),
});
},
});
export default userPreferencesPersistentStorageInjectable;

View File

@ -3,16 +3,15 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed, toJS } from "mobx";
import { toJS } from "../utils"; import userPreferencesStateInjectable from "./state.injectable";
import userStoreInjectable from "./user-store.injectable";
const terminalConfigInjectable = getInjectable({ const terminalConfigInjectable = getInjectable({
id: "terminal-config", id: "terminal-config",
instantiate: (di) => { instantiate: (di) => {
const store = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
return computed(() => toJS(store.terminalConfig)); return computed(() => toJS(state.terminalConfig));
}, },
}); });

View File

@ -4,14 +4,14 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable"; import userPreferencesStateInjectable from "./state.injectable";
const terminalCopyOnSelectInjectable = getInjectable({ const terminalCopyOnSelectInjectable = getInjectable({
id: "terminal-copy-on-select", id: "terminal-copy-on-select",
instantiate: (di) => { instantiate: (di) => {
const store = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
return computed(() => store.terminalCopyOnSelect); return computed(() => state.terminalCopyOnSelect);
}, },
}); });

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable"; import userPreferencesStateInjectable from "./state.injectable";
export type TerminalThemePreference = { export type TerminalThemePreference = {
matchLensTheme: true; matchLensTheme: true;
@ -16,11 +16,11 @@ export type TerminalThemePreference = {
const terminalThemePreferenceInjectable = getInjectable({ const terminalThemePreferenceInjectable = getInjectable({
id: "terminal-theme-preference", id: "terminal-theme-preference",
instantiate: (di) => { instantiate: (di) => {
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
return computed((): TerminalThemePreference => { return computed((): TerminalThemePreference => {
// NOTE: remove use of magic strings // NOTE: remove use of magic strings
if (!userStore.terminalTheme) { if (!state.terminalTheme) {
return { return {
matchLensTheme: true, matchLensTheme: true,
}; };
@ -28,7 +28,7 @@ const terminalThemePreferenceInjectable = getInjectable({
return { return {
matchLensTheme: false, matchLensTheme: false,
themeId: userStore.terminalTheme, themeId: state.terminalTheme,
}; };
}); });
}, },

View File

@ -0,0 +1,23 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getOrInsertSet, toggle } from "@k8slens/utilities";
import { getInjectable } from "@ogre-tools/injectable";
import { action } from "mobx";
import userPreferencesStateInjectable from "./state.injectable";
export type ToggleTableColumnVisibility = (tableId: string, columnId: string) => void;
const toggleTableColumnVisibilityInjectable = getInjectable({
id: "toggle-table-column-visibility",
instantiate: (di): ToggleTableColumnVisibility => {
const state = di.inject(userPreferencesStateInjectable);
return action((tableId, columnId) => {
toggle(getOrInsertSet(state.hiddenTableColumns, tableId), columnId);
});
},
});
export default toggleTableColumnVisibilityInjectable;

View File

@ -5,14 +5,14 @@
// Switch representation of hiddenTableColumns in store // Switch representation of hiddenTableColumns in store
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { userStoreMigrationInjectionToken } from "../../../common/user-store/migrations-token"; import { userPreferencesMigrationInjectionToken } from "../common/migrations-token";
interface PreV500Alpha3UserPreferencesModel { interface PreV500Alpha3UserPreferencesModel {
hiddenTableColumns?: Record<string, string[]>; hiddenTableColumns?: Record<string, string[]>;
} }
const v500Alpha3UserStoreMigrationInjectable = getInjectable({ const v500Alpha3UserPreferencesStorageMigrationInjectable = getInjectable({
id: "v5.0.0-alpha.3-user-store-migration", id: "v5.0.0-alpha.3-preferences-storage-migration",
instantiate: () => ({ instantiate: () => ({
version: "5.0.0-alpha.3", version: "5.0.0-alpha.3",
run(store) { run(store) {
@ -29,8 +29,8 @@ const v500Alpha3UserStoreMigrationInjectable = getInjectable({
}); });
}, },
}), }),
injectionToken: userStoreMigrationInjectionToken, injectionToken: userPreferencesMigrationInjectionToken,
}); });
export default v500Alpha3UserStoreMigrationInjectable; export default v500Alpha3UserPreferencesStorageMigrationInjectable;

View File

@ -3,7 +3,6 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { KubeconfigSyncEntry, UserPreferencesModel } from "../../../common/user-store";
import { isErrnoException } from "@k8slens/utilities"; import { isErrnoException } from "@k8slens/utilities";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
@ -11,15 +10,16 @@ import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import isLogicalChildPathInjectable from "../../../common/path/is-logical-child-path.injectable"; import isLogicalChildPathInjectable from "../../../common/path/is-logical-child-path.injectable";
import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable"; import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { userStoreMigrationInjectionToken } from "../../../common/user-store/migrations-token"; import { userPreferencesMigrationInjectionToken } from "../../../features/user-preferences/common/migrations-token";
import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable"; import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable";
import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable"; import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable"; import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable";
import type { ClusterStoreModel } from "../../../features/cluster/storage/common/storage.injectable"; import type { ClusterStoreModel } from "../../../features/cluster/storage/common/storage.injectable";
import type { UserPreferencesModel, KubeconfigSyncEntry } from "../common/preferences-helpers";
const v503Beta1UserStoreMigrationInjectable = getInjectable({ const v503Beta1UserPreferencesStorageMigrationInjectable = getInjectable({
id: "v5.0.3-beta.1-user-store-migration", id: "v5.0.3-beta.1-preferences-storage-migration",
instantiate: (di) => { instantiate: (di) => {
const userDataPath = di.inject(directoryForUserDataInjectable); const userDataPath = di.inject(directoryForUserDataInjectable);
const kubeConfigsPath = di.inject(directoryForKubeConfigsInjectable); const kubeConfigsPath = di.inject(directoryForKubeConfigsInjectable);
@ -85,7 +85,7 @@ const v503Beta1UserStoreMigrationInjectable = getInjectable({
}, },
}; };
}, },
injectionToken: userStoreMigrationInjectionToken, injectionToken: userPreferencesMigrationInjectionToken,
}); });
export default v503Beta1UserStoreMigrationInjectable; export default v503Beta1UserPreferencesStorageMigrationInjectable;

View File

@ -3,28 +3,29 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import fse from "fs-extra"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { isErrnoException } from "@k8slens/utilities"; import { isErrnoException } from "@k8slens/utilities";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import joinPathsInjectable from "../path/join-paths.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import fsInjectable from "../../../common/fs/fs.injectable";
export type UserStoreFileNameMigration = () => Promise<void>; export type UserStoreFileNameMigration = () => Promise<void>;
const userStoreFileNameMigrationInjectable = getInjectable({ const userPreferencesStorageFileNameMigrationInjectable = getInjectable({
id: "user-store-file-name-migration", id: "preferences-storage-file-name-migration",
instantiate: (di): UserStoreFileNameMigration => { instantiate: (di): UserStoreFileNameMigration => {
const userDataPath = di.inject(directoryForUserDataInjectable); const userDataPath = di.inject(directoryForUserDataInjectable);
const joinPaths = di.inject(joinPathsInjectable); const joinPaths = di.inject(joinPathsInjectable);
const configJsonPath = joinPaths(userDataPath, "config.json"); const configJsonPath = joinPaths(userDataPath, "config.json");
const lensUserStoreJsonPath = joinPaths(userDataPath, "lens-user-store.json"); const lensUserStoreJsonPath = joinPaths(userDataPath, "lens-user-store.json");
const { rename, rm } = di.inject(fsInjectable);
return async () => { return async () => {
try { try {
await fse.move(configJsonPath, lensUserStoreJsonPath); await rename(configJsonPath, lensUserStoreJsonPath);
} catch (error) { } catch (error) {
if (error instanceof Error && error.message === "dest already exists.") { if (error instanceof Error && error.message === "dest already exists.") {
await fse.remove(configJsonPath); await rm(configJsonPath);
} else if (isErrnoException(error) && error.code === "ENOENT" && error.path === configJsonPath) { } else if (isErrnoException(error) && error.code === "ENOENT" && error.path === configJsonPath) {
// (No such file or directory) // (No such file or directory)
return; // file already moved return; // file already moved
@ -35,7 +36,6 @@ const userStoreFileNameMigrationInjectable = getInjectable({
} }
}; };
}, },
causesSideEffects: true,
}); });
export default userStoreFileNameMigrationInjectable; export default userPreferencesStorageFileNameMigrationInjectable;

View File

@ -0,0 +1,26 @@
/**
* 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 { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application";
import initDefaultUpdateChannelInjectable from "../../../renderer/vars/default-update-channel/init.injectable";
import userPreferencesPersistentStorageInjectable from "../common/storage.injectable";
import userPreferencesStorageFileNameMigrationInjectable from "./file-name-migration.injectable";
const loadUserPreferencesStorageInjectable = getInjectable({
id: "load-user-preferences-storage",
instantiate: (di) => ({
run: async () => {
const storage = di.inject(userPreferencesPersistentStorageInjectable);
const userStoreFileNameMigration = di.inject(userPreferencesStorageFileNameMigrationInjectable);
await userStoreFileNameMigration();
storage.loadAndStartSyncing();
},
runAfter: initDefaultUpdateChannelInjectable,
}),
injectionToken: beforeApplicationIsLoadingInjectionToken,
});
export default loadUserPreferencesStorageInjectable;

View File

@ -4,18 +4,18 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { reaction } from "mobx"; import { reaction } from "mobx";
import userStoreInjectable from "../../common/user-store/user-store.injectable"; import setLoginItemSettingsInjectable from "../../../main/electron-app/features/set-login-item-settings.injectable";
import setLoginItemSettingsInjectable from "../electron-app/features/set-login-item-settings.injectable";
import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
import userPreferencesStateInjectable from "../common/state.injectable";
const setupSyncOpenAtLoginWithOsInjectable = getInjectable({ const setupSyncOpenAtLoginWithOsInjectable = getInjectable({
id: "setup-sync-open-at-login-with-os", id: "setup-sync-open-at-login-with-os",
instantiate: (di) => ({ instantiate: (di) => ({
run: () => { run: () => {
const setLoginItemSettings = di.inject(setLoginItemSettingsInjectable); const setLoginItemSettings = di.inject(setLoginItemSettingsInjectable);
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
reaction(() => userStore.openAtLogin, openAtLogin => { reaction(() => state.openAtLogin, openAtLogin => {
setLoginItemSettings({ setLoginItemSettings({
openAtLogin, openAtLogin,
openAsHidden: true, openAsHidden: true,

View File

@ -0,0 +1,23 @@
/**
* 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 { beforeFrameStartsSecondInjectionToken } from "../../../renderer/before-frame-starts/tokens";
import initDefaultUpdateChannelInjectable from "../../../renderer/vars/default-update-channel/init.injectable";
import userPreferencesPersistentStorageInjectable from "../common/storage.injectable";
const loadUserPreferencesStorageInjectable = getInjectable({
id: "load-user-preferences-storage",
instantiate: (di) => ({
run: () => {
const storage = di.inject(userPreferencesPersistentStorageInjectable);
return storage.loadAndStartSyncing();
},
runAfter: initDefaultUpdateChannelInjectable,
}),
injectionToken: beforeFrameStartsSecondInjectionToken,
});
export default loadUserPreferencesStorageInjectable;

View File

@ -17,8 +17,6 @@ import type { ConfigToModels } from "../kubeconfig-sync/config-to-models.injecta
import configToModelsInjectable from "../kubeconfig-sync/config-to-models.injectable"; import configToModelsInjectable from "../kubeconfig-sync/config-to-models.injectable";
import kubeconfigSyncManagerInjectable from "../kubeconfig-sync/manager.injectable"; import kubeconfigSyncManagerInjectable from "../kubeconfig-sync/manager.injectable";
import type { KubeconfigSyncManager } from "../kubeconfig-sync/manager"; import type { KubeconfigSyncManager } from "../kubeconfig-sync/manager";
import type { KubeconfigSyncValue } from "../../../common/user-store";
import kubeconfigSyncsInjectable from "../../../common/user-store/kubeconfig-syncs.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import type { Stat } from "../../../common/fs/stat.injectable"; import type { Stat } from "../../../common/fs/stat.injectable";
@ -35,6 +33,8 @@ import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable
import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable"; import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable";
import type { KubeconfigManager } from "../../kubeconfig-manager/kubeconfig-manager"; import type { KubeconfigManager } from "../../kubeconfig-manager/kubeconfig-manager";
import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable";
import type { KubeconfigSyncValue } from "../../../features/user-preferences/common/preferences-helpers";
import kubeconfigSyncsInjectable from "../../../features/user-preferences/common/kubeconfig-syncs.injectable";
describe("kubeconfig-sync.source tests", () => { describe("kubeconfig-sync.source tests", () => {
let computeKubeconfigDiff: ComputeKubeconfigDiff; let computeKubeconfigDiff: ComputeKubeconfigDiff;

View File

@ -7,7 +7,7 @@ import directoryForKubeConfigsInjectable from "../../../common/app-paths/directo
import { KubeconfigSyncManager } from "./manager"; import { KubeconfigSyncManager } from "./manager";
import kubeconfigSyncLoggerInjectable from "./logger.injectable"; import kubeconfigSyncLoggerInjectable from "./logger.injectable";
import watchKubeconfigFileChangesInjectable from "./watch-file-changes.injectable"; import watchKubeconfigFileChangesInjectable from "./watch-file-changes.injectable";
import kubeconfigSyncsInjectable from "../../../common/user-store/kubeconfig-syncs.injectable"; import kubeconfigSyncsInjectable from "../../../features/user-preferences/common/kubeconfig-syncs.injectable";
const kubeconfigSyncManagerInjectable = getInjectable({ const kubeconfigSyncManagerInjectable = getInjectable({
id: "kubeconfig-sync-manager", id: "kubeconfig-sync-manager",

View File

@ -8,9 +8,9 @@ import { action, observable, computed, makeObservable, observe } from "mobx";
import type { CatalogEntity } from "../../../common/catalog"; import type { CatalogEntity } from "../../../common/catalog";
import type { Disposer } from "@k8slens/utilities"; import type { Disposer } from "@k8slens/utilities";
import { iter } from "@k8slens/utilities"; import { iter } from "@k8slens/utilities";
import type { KubeconfigSyncValue } from "../../../common/user-store";
import type { Logger } from "../../../common/logger"; import type { Logger } from "../../../common/logger";
import type { WatchKubeconfigFileChanges } from "./watch-file-changes.injectable"; import type { WatchKubeconfigFileChanges } from "./watch-file-changes.injectable";
import type { KubeconfigSyncValue } from "../../../features/user-preferences/common/preferences-helpers";
interface KubeconfigSyncManagerDependencies { interface KubeconfigSyncManagerDependencies {
readonly directoryForKubeConfigs: string; readonly directoryForKubeConfigs: string;

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import httpsProxyConfigurationInjectable from "../../../common/user-store/https-proxy.injectable"; import httpsProxyConfigurationInjectable from "../../../features/user-preferences/common/https-proxy.injectable";
const execHelmEnvInjectable = getInjectable({ const execHelmEnvInjectable = getInjectable({
id: "exec-helm-env", id: "exec-helm-env",

View File

@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { KubectlDependencies } from "./kubectl"; import type { KubectlDependencies } from "./kubectl";
import { Kubectl } from "./kubectl"; import { Kubectl } from "./kubectl";
import directoryForKubectlBinariesInjectable from "../../common/app-paths/directory-for-kubectl-binaries/directory-for-kubectl-binaries.injectable"; import directoryForKubectlBinariesInjectable from "../../common/app-paths/directory-for-kubectl-binaries/directory-for-kubectl-binaries.injectable";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import kubectlDownloadingNormalizedArchInjectable from "./normalized-arch.injectable"; import kubectlDownloadingNormalizedArchInjectable from "./normalized-arch.injectable";
import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable"; import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable";
import kubectlBinaryNameInjectable from "./binary-name.injectable"; import kubectlBinaryNameInjectable from "./binary-name.injectable";
@ -20,6 +19,7 @@ import getBasenameOfPathInjectable from "../../common/path/get-basename.injectab
import loggerInjectable from "../../common/logger.injectable"; import loggerInjectable from "../../common/logger.injectable";
import execFileInjectable from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable";
import unlinkInjectable from "../../common/fs/unlink.injectable"; import unlinkInjectable from "../../common/fs/unlink.injectable";
import userPreferencesStateInjectable from "../../features/user-preferences/common/state.injectable";
export type CreateKubectl = (version: string) => Kubectl; export type CreateKubectl = (version: string) => Kubectl;
@ -28,7 +28,7 @@ const createKubectlInjectable = getInjectable({
instantiate: (di): CreateKubectl => { instantiate: (di): CreateKubectl => {
const dependencies: KubectlDependencies = { const dependencies: KubectlDependencies = {
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
directoryForKubectlBinaries: di.inject(directoryForKubectlBinariesInjectable), directoryForKubectlBinaries: di.inject(directoryForKubectlBinariesInjectable),
normalizedDownloadArch: di.inject(kubectlDownloadingNormalizedArchInjectable), normalizedDownloadArch: di.inject(kubectlDownloadingNormalizedArchInjectable),
normalizedDownloadPlatform: di.inject(normalizedPlatformInjectable), normalizedDownloadPlatform: di.inject(normalizedPlatformInjectable),

View File

@ -7,7 +7,6 @@ import fs from "fs";
import { ensureDir, pathExists } from "fs-extra"; import { ensureDir, pathExists } from "fs-extra";
import * as lockFile from "proper-lockfile"; import * as lockFile from "proper-lockfile";
import { SemVer, coerce } from "semver"; import { SemVer, coerce } from "semver";
import { defaultPackageMirror, packageMirrors } from "../../common/user-store/preferences-helpers";
import got from "got/dist/source"; import got from "got/dist/source";
import { promisify } from "util"; import { promisify } from "util";
import stream from "stream"; import stream from "stream";
@ -20,6 +19,7 @@ import type { Logger } from "../../common/logger";
import type { ExecFile } from "../../common/fs/exec-file.injectable"; import type { ExecFile } from "../../common/fs/exec-file.injectable";
import { hasTypedProperty, isObject, isString, json } from "@k8slens/utilities"; import { hasTypedProperty, isObject, isString, json } from "@k8slens/utilities";
import type { Unlink } from "../../common/fs/unlink.injectable"; import type { Unlink } from "../../common/fs/unlink.injectable";
import { packageMirrors, defaultPackageMirror } from "../../features/user-preferences/common/preferences-helpers";
const initScriptVersionString = "# lens-initscript v3"; const initScriptVersionString = "# lens-initscript v3";
@ -30,7 +30,7 @@ export interface KubectlDependencies {
readonly kubectlBinaryName: string; readonly kubectlBinaryName: string;
readonly bundledKubectlBinaryPath: string; readonly bundledKubectlBinaryPath: string;
readonly baseBundeledBinariesDirectory: string; readonly baseBundeledBinariesDirectory: string;
readonly userStore: { readonly state: {
readonly kubectlBinariesPath?: string; readonly kubectlBinariesPath?: string;
readonly downloadBinariesPath?: string; readonly downloadBinariesPath?: string;
readonly downloadKubectlBinaries: boolean; readonly downloadKubectlBinaries: boolean;
@ -91,12 +91,12 @@ export class Kubectl {
} }
public getPathFromPreferences() { public getPathFromPreferences() {
return this.dependencies.userStore.kubectlBinariesPath || this.getBundledPath(); return this.dependencies.state.kubectlBinariesPath || this.getBundledPath();
} }
protected getDownloadDir() { protected getDownloadDir() {
if (this.dependencies.userStore.downloadBinariesPath) { if (this.dependencies.state.downloadBinariesPath) {
return this.dependencies.joinPaths(this.dependencies.userStore.downloadBinariesPath, "kubectl"); return this.dependencies.joinPaths(this.dependencies.state.downloadBinariesPath, "kubectl");
} }
return this.dependencies.directoryForKubectlBinaries; return this.dependencies.directoryForKubectlBinaries;
@ -107,7 +107,7 @@ export class Kubectl {
return this.getBundledPath(); return this.getBundledPath();
} }
if (this.dependencies.userStore.downloadKubectlBinaries === false) { if (this.dependencies.state.downloadKubectlBinaries === false) {
return this.getPathFromPreferences(); return this.getPathFromPreferences();
} }
@ -231,7 +231,7 @@ export class Kubectl {
} }
public async ensureKubectl(): Promise<boolean> { public async ensureKubectl(): Promise<boolean> {
if (this.dependencies.userStore.downloadKubectlBinaries === false) { if (this.dependencies.state.downloadKubectlBinaries === false) {
return true; return true;
} }
@ -303,7 +303,7 @@ export class Kubectl {
protected async writeInitScripts() { protected async writeInitScripts() {
const binariesDir = this.dependencies.baseBundeledBinariesDirectory; const binariesDir = this.dependencies.baseBundeledBinariesDirectory;
const kubectlPath = this.dependencies.userStore.downloadKubectlBinaries const kubectlPath = this.dependencies.state.downloadKubectlBinaries
? this.dirname ? this.dirname
: this.dependencies.getDirnameOfPath(this.getPathFromPreferences()); : this.dependencies.getDirnameOfPath(this.getPathFromPreferences());
@ -370,7 +370,7 @@ export class Kubectl {
protected getDownloadMirror(): string { protected getDownloadMirror(): string {
// MacOS packages are only available from default // MacOS packages are only available from default
const { url } = packageMirrors.get(this.dependencies.userStore.downloadMirror) const { url } = packageMirrors.get(this.dependencies.state.downloadMirror)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
?? packageMirrors.get(defaultPackageMirror)!; ?? packageMirrors.get(defaultPackageMirror)!;

View File

@ -3,17 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { UserStore } from "../../../common/user-store";
import type { ShellSessionArgs, ShellSessionDependencies } from "../shell-session"; import type { ShellSessionArgs, ShellSessionDependencies } from "../shell-session";
import { ShellSession } from "../shell-session"; import { ShellSession } from "../shell-session";
import type { ModifyTerminalShellEnv } from "../shell-env-modifier/modify-terminal-shell-env.injectable"; import type { ModifyTerminalShellEnv } from "../shell-env-modifier/modify-terminal-shell-env.injectable";
import type { JoinPaths } from "../../../common/path/join-paths.injectable"; import type { JoinPaths } from "../../../common/path/join-paths.injectable";
import type { GetDirnameOfPath } from "../../../common/path/get-dirname.injectable"; import type { GetDirnameOfPath } from "../../../common/path/get-dirname.injectable";
import type { GetBasenameOfPath } from "../../../common/path/get-basename.injectable"; import type { GetBasenameOfPath } from "../../../common/path/get-basename.injectable";
import type { UserPreferencesState } from "../../../features/user-preferences/common/state.injectable";
export interface LocalShellSessionDependencies extends ShellSessionDependencies { export interface LocalShellSessionDependencies extends ShellSessionDependencies {
readonly directoryForBinaries: string; readonly directoryForBinaries: string;
readonly userStore: UserStore; readonly state: UserPreferencesState;
modifyTerminalShellEnv: ModifyTerminalShellEnv; modifyTerminalShellEnv: ModifyTerminalShellEnv;
joinPaths: JoinPaths; joinPaths: JoinPaths;
getDirnameOfPath: GetDirnameOfPath; getDirnameOfPath: GetDirnameOfPath;
@ -50,8 +50,8 @@ export class LocalShellSession extends ShellSession {
} }
protected async getShellArgs(shell: string): Promise<string[]> { protected async getShellArgs(shell: string): Promise<string[]> {
const pathFromPreferences = this.dependencies.userStore.kubectlBinariesPath || this.kubectl.getBundledPath(); const pathFromPreferences = this.dependencies.state.kubectlBinariesPath || this.kubectl.getBundledPath();
const kubectlPathDir = this.dependencies.userStore.downloadKubectlBinaries const kubectlPathDir = this.dependencies.state.downloadKubectlBinaries
? this.dependencies.directoryContainingKubectl ? this.dependencies.directoryContainingKubectl
: this.dependencies.getDirnameOfPath(pathFromPreferences); : this.dependencies.getDirnameOfPath(pathFromPreferences);

View File

@ -12,19 +12,19 @@ import isMacInjectable from "../../../common/vars/is-mac.injectable";
import type { Cluster } from "../../../common/cluster/cluster"; import type { Cluster } from "../../../common/cluster/cluster";
import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; import isWindowsInjectable from "../../../common/vars/is-windows.injectable";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
import type WebSocket from "ws"; import type WebSocket from "ws";
import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable"; import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable";
import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import getBasenameOfPathInjectable from "../../../common/path/get-basename.injectable"; import getBasenameOfPathInjectable from "../../../common/path/get-basename.injectable";
import computeShellEnvironmentInjectable from "../../../features/shell-sync/main/compute-shell-environment.injectable"; import computeShellEnvironmentInjectable from "../../../features/shell-sync/main/compute-shell-environment.injectable";
import spawnPtyInjectable from "../spawn-pty.injectable"; import spawnPtyInjectable from "../spawn-pty.injectable";
import userShellSettingInjectable from "../../../common/user-store/shell-setting.injectable";
import appNameInjectable from "../../../common/vars/app-name.injectable"; import appNameInjectable from "../../../common/vars/app-name.injectable";
import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable";
import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
import statInjectable from "../../../common/fs/stat.injectable"; import statInjectable from "../../../common/fs/stat.injectable";
import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable";
import userPreferencesStateInjectable from "../../../features/user-preferences/common/state.injectable";
import userShellSettingInjectable from "../../../features/user-preferences/common/shell-setting.injectable";
export interface OpenLocalShellSessionArgs { export interface OpenLocalShellSessionArgs {
websocket: WebSocket; websocket: WebSocket;
@ -44,7 +44,7 @@ const openLocalShellSessionInjectable = getInjectable({
isMac: di.inject(isMacInjectable), isMac: di.inject(isMacInjectable),
isWindows: di.inject(isWindowsInjectable), isWindows: di.inject(isWindowsInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
userShellSetting: di.inject(userShellSettingInjectable), userShellSetting: di.inject(userShellSettingInjectable),
appName: di.inject(appNameInjectable), appName: di.inject(appNameInjectable),
buildVersion: di.inject(buildVersionInjectable), buildVersion: di.inject(buildVersionInjectable),

View File

@ -14,7 +14,6 @@ import loggerInjectable from "../../../common/logger.injectable";
import createKubeJsonApiForClusterInjectable from "../../../common/k8s-api/create-kube-json-api-for-cluster.injectable"; import createKubeJsonApiForClusterInjectable from "../../../common/k8s-api/create-kube-json-api-for-cluster.injectable";
import computeShellEnvironmentInjectable from "../../../features/shell-sync/main/compute-shell-environment.injectable"; import computeShellEnvironmentInjectable from "../../../features/shell-sync/main/compute-shell-environment.injectable";
import spawnPtyInjectable from "../spawn-pty.injectable"; import spawnPtyInjectable from "../spawn-pty.injectable";
import userShellSettingInjectable from "../../../common/user-store/shell-setting.injectable";
import appNameInjectable from "../../../common/vars/app-name.injectable"; import appNameInjectable from "../../../common/vars/app-name.injectable";
import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable";
import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
@ -22,6 +21,7 @@ import statInjectable from "../../../common/fs/stat.injectable";
import createKubeApiInjectable from "../../../common/k8s-api/create-kube-api.injectable"; import createKubeApiInjectable from "../../../common/k8s-api/create-kube-api.injectable";
import loadProxyKubeconfigInjectable from "../../cluster/load-proxy-kubeconfig.injectable"; import loadProxyKubeconfigInjectable from "../../cluster/load-proxy-kubeconfig.injectable";
import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable";
import userShellSettingInjectable from "../../../features/user-preferences/common/shell-setting.injectable";
export interface NodeShellSessionArgs { export interface NodeShellSessionArgs {
websocket: WebSocket; websocket: WebSocket;

View File

@ -1,26 +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 userStoreFileNameMigrationInjectable from "../../common/user-store/file-name-migration.injectable";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application";
import initDefaultUpdateChannelInjectable from "../vars/default-update-channel/init.injectable";
const initUserStoreInjectable = getInjectable({
id: "init-user-store",
instantiate: (di) => ({
run: async () => {
const userStore = di.inject(userStoreInjectable);
const userStoreFileNameMigration = di.inject(userStoreFileNameMigrationInjectable);
await userStoreFileNameMigration();
userStore.load();
},
runAfter: initDefaultUpdateChannelInjectable,
}),
injectionToken: beforeApplicationIsLoadingInjectionToken,
});
export default initUserStoreInjectable;

View File

@ -7,15 +7,15 @@ import { getInjectable } from "@ogre-tools/injectable";
import React from "react"; import React from "react";
import execFileInjectable from "../../../../common/fs/exec-file.injectable"; import execFileInjectable from "../../../../common/fs/exec-file.injectable";
import loggerInjectable from "../../../../common/logger.injectable"; import loggerInjectable from "../../../../common/logger.injectable";
import { defaultExtensionRegistryUrl } from "../../../../common/user-store/preferences-helpers"; import { defaultExtensionRegistryUrl } from "../../../../features/user-preferences/common/preferences-helpers";
import userStoreInjectable from "../../../../common/user-store/user-store.injectable"; import userPreferencesStateInjectable from "../../../../features/user-preferences/common/state.injectable";
import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable"; import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable";
const getBaseRegistryUrlInjectable = getInjectable({ const getBaseRegistryUrlInjectable = getInjectable({
id: "get-base-registry-url", id: "get-base-registry-url",
instantiate: (di) => { instantiate: (di) => {
const { extensionRegistryUrl } = di.inject(userStoreInjectable); const { extensionRegistryUrl } = di.inject(userPreferencesStateInjectable);
const showErrorNotification = di.inject(showErrorNotificationInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable);
const logger = di.inject(loggerInjectable); const logger = di.inject(loggerInjectable);
const execFile = di.inject(execFileInjectable); const execFile = di.inject(execFileInjectable);

View File

@ -15,7 +15,6 @@ import { disposeOnUnmount, observer } from "mobx-react";
import moment from "moment-timezone"; import moment from "moment-timezone";
import type { Align, ListOnScrollProps } from "react-window"; import type { Align, ListOnScrollProps } from "react-window";
import { SearchStore } from "../../../search-store/search-store"; import { SearchStore } from "../../../search-store/search-store";
import type { UserStore } from "../../../../common/user-store";
import { array, cssNames } from "@k8slens/utilities"; import { array, cssNames } from "@k8slens/utilities";
import type { VirtualListRef } from "../../virtual-list"; import type { VirtualListRef } from "../../virtual-list";
import { VirtualList } from "../../virtual-list"; import { VirtualList } from "../../virtual-list";
@ -23,8 +22,9 @@ import { ToBottom } from "./to-bottom";
import type { LogTabViewModel } from "../logs/logs-view-model"; import type { LogTabViewModel } from "../logs/logs-view-model";
import { Spinner } from "../../spinner"; import { Spinner } from "../../spinner";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../../common/user-store/user-store.injectable";
import autoBindReact from "auto-bind/react"; import autoBindReact from "auto-bind/react";
import type { UserPreferencesState } from "../../../../features/user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../../features/user-preferences/common/state.injectable";
export interface LogListProps { export interface LogListProps {
model: LogTabViewModel; model: LogTabViewModel;
@ -37,7 +37,7 @@ export interface LogListRef {
} }
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
@observer @observer
@ -129,7 +129,7 @@ class NonForwardedLogList extends React.Component<Dependencies & LogListProps &
return this.props.model.timestampSplitLogs return this.props.model.timestampSplitLogs
.get() .get()
.map(([logTimestamp, log]) => (`${logTimestamp && moment.tz(logTimestamp, this.props.userStore.localeTimezone).format()}${log}`)); .map(([logTimestamp, log]) => (`${logTimestamp && moment.tz(logTimestamp, this.props.state.localeTimezone).format()}${log}`));
} }
/** /**
@ -283,7 +283,7 @@ class NonForwardedLogList extends React.Component<Dependencies & LogListProps &
const InjectedNonForwardedLogList = withInjectables<Dependencies, LogListProps & { innerRef: ForwardedRef<LogListRef> }>(NonForwardedLogList, { const InjectedNonForwardedLogList = withInjectables<Dependencies, LogListProps & { innerRef: ForwardedRef<LogListRef> }>(NonForwardedLogList, {
getProps: (di, props) => ({ getProps: (di, props) => ({
...props, ...props,
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
}), }),
}); });

View File

@ -8,13 +8,12 @@ import { Terminal } from "./terminal";
import type { TabId } from "../dock/store"; import type { TabId } from "../dock/store";
import type { TerminalApi } from "../../../api/terminal-api"; import type { TerminalApi } from "../../../api/terminal-api";
import terminalSpawningPoolInjectable from "./terminal-spawning-pool.injectable"; 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 isMacInjectable from "../../../../common/vars/is-mac.injectable"; import isMacInjectable from "../../../../common/vars/is-mac.injectable";
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable"; import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
import xtermColorThemeInjectable from "../../../themes/terminal-colors.injectable"; import xtermColorThemeInjectable from "../../../themes/terminal-colors.injectable";
import loggerInjectable from "../../../../common/logger.injectable"; import loggerInjectable from "../../../../common/logger.injectable";
import terminalConfigInjectable from "../../../../features/user-preferences/common/terminal-config.injectable";
import terminalCopyOnSelectInjectable from "../../../../features/user-preferences/common/terminal-copy-on-select.injectable";
export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal; export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal;

View File

@ -14,11 +14,11 @@ import { disposer } from "@k8slens/utilities";
import { once } from "lodash"; import { once } from "lodash";
import { clipboard } from "electron"; import { clipboard } from "electron";
import type { Logger } from "../../../../common/logger"; import type { Logger } from "../../../../common/logger";
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
import assert from "assert"; import assert from "assert";
import { TerminalChannels } from "../../../../common/terminal/channels"; import { TerminalChannels } from "../../../../common/terminal/channels";
import { LinkProvider } from "xterm-link-provider"; import { LinkProvider } from "xterm-link-provider";
import type { OpenLinkInBrowser } from "../../../../common/utils/open-link-in-browser.injectable"; import type { OpenLinkInBrowser } from "../../../../common/utils/open-link-in-browser.injectable";
import type { TerminalConfig } from "../../../../features/user-preferences/common/preferences-helpers";
export interface TerminalDependencies { export interface TerminalDependencies {
readonly spawningPool: HTMLElement; readonly spawningPool: HTMLElement;

View File

@ -25,15 +25,17 @@ import type { LensTheme } from "../../themes/lens-theme";
import { MenuActions } from "../menu/menu-actions"; import { MenuActions } from "../menu/menu-actions";
import { MenuItem } from "../menu"; import { MenuItem } from "../menu";
import { Checkbox } from "../checkbox"; import { Checkbox } from "../checkbox";
import type { UserStore } from "../../../common/user-store";
import type { ItemListStore } from "./list-layout"; import type { ItemListStore } from "./list-layout";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
import pageFiltersStoreInjectable from "./page-filters/store.injectable"; import pageFiltersStoreInjectable from "./page-filters/store.injectable";
import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable"; import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable";
import openConfirmDialogInjectable from "../confirm-dialog/open.injectable"; import openConfirmDialogInjectable from "../confirm-dialog/open.injectable";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";
import autoBindReact from "auto-bind/react"; import autoBindReact from "auto-bind/react";
import type { ToggleTableColumnVisibility } from "../../../features/user-preferences/common/toggle-table-column-visibility.injectable";
import toggleTableColumnVisibilityInjectable from "../../../features/user-preferences/common/toggle-table-column-visibility.injectable";
import type { IsTableColumnHidden } from "../../../features/user-preferences/common/is-table-column-hidden.injectable";
import isTableColumnHiddenInjectable from "../../../features/user-preferences/common/is-table-column-hidden.injectable";
export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStores extends boolean> { export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStores extends boolean> {
getFilters: () => Filter[]; getFilters: () => Filter[];
@ -74,9 +76,10 @@ export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStor
interface Dependencies { interface Dependencies {
activeTheme: IComputedValue<LensTheme>; activeTheme: IComputedValue<LensTheme>;
userStore: UserStore;
pageFiltersStore: PageFiltersStore; pageFiltersStore: PageFiltersStore;
openConfirmDialog: OpenConfirmDialog; openConfirmDialog: OpenConfirmDialog;
toggleTableColumnVisibility: ToggleTableColumnVisibility;
isTableColumnHidden: IsTableColumnHidden;
} }
@observer @observer
@ -342,7 +345,7 @@ class NonInjectedItemListLayoutContent<
showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean { showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean {
const { tableId, isConfigurable } = this.props; const { tableId, isConfigurable } = this.props;
return !isConfigurable || !tableId || !this.props.userStore.isTableColumnHidden(tableId, columnId, showWithColumn); return !isConfigurable || !tableId || !this.props.isTableColumnHidden(tableId, columnId, showWithColumn);
} }
renderColumnVisibilityMenu(tableId: string) { renderColumnVisibilityMenu(tableId: string) {
@ -365,7 +368,7 @@ class NonInjectedItemListLayoutContent<
<Checkbox <Checkbox
label={cellProps.title ?? `<${cellProps.className}>`} label={cellProps.title ?? `<${cellProps.className}>`}
value={this.showColumn(cellProps)} value={this.showColumn(cellProps)}
onChange={() => this.props.userStore.toggleTableColumnVisibility(tableId, cellProps.id)} onChange={() => this.props.toggleTableColumnVisibility(tableId, cellProps.id)}
/> />
</MenuItem> </MenuItem>
)) ))
@ -379,8 +382,9 @@ export const ItemListLayoutContent = withInjectables<Dependencies, ItemListLayou
getProps: (di, props) => ({ getProps: (di, props) => ({
...props, ...props,
activeTheme: di.inject(activeThemeInjectable), activeTheme: di.inject(activeThemeInjectable),
userStore: di.inject(userStoreInjectable),
pageFiltersStore: di.inject(pageFiltersStoreInjectable), pageFiltersStore: di.inject(pageFiltersStoreInjectable),
openConfirmDialog: di.inject(openConfirmDialogInjectable), openConfirmDialog: di.inject(openConfirmDialogInjectable),
toggleTableColumnVisibility: di.inject(toggleTableColumnVisibilityInjectable),
isTableColumnHidden: di.inject(isTableColumnHiddenInjectable),
}), }),
}) as <Item extends ItemObject, PreLoadStores extends boolean>(props: ItemListLayoutContentProps<Item, PreLoadStores>) => React.ReactElement; }) as <Item extends ItemObject, PreLoadStores extends boolean>(props: ItemListLayoutContentProps<Item, PreLoadStores>) => React.ReactElement;

View File

@ -6,27 +6,27 @@
import React from "react"; import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import moment from "moment-timezone"; import moment from "moment-timezone";
import type { UserStore } from "../../../common/user-store";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../common/user-store/user-store.injectable"; import type { UserPreferencesState } from "../../../features/user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../features/user-preferences/common/state.injectable";
export interface LocaleDateProps { export interface LocaleDateProps {
date: string; date: string;
} }
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
} }
const NonInjectedLocaleDate = observer(({ date, userStore }: LocaleDateProps & Dependencies) => ( const NonInjectedLocaleDate = observer(({ date, state }: LocaleDateProps & Dependencies) => (
<> <>
{`${moment.tz(date, userStore.localeTimezone).format()}`} {`${moment.tz(date, state.localeTimezone).format()}`}
</> </>
)); ));
export const LocaleDate = withInjectables<Dependencies, LocaleDateProps>(NonInjectedLocaleDate, { export const LocaleDate = withInjectables<Dependencies, LocaleDateProps>(NonInjectedLocaleDate, {
getProps: (di, props) => ({ getProps: (di, props) => ({
...props, ...props,
userStore: di.inject(userStoreInjectable), state: di.inject(userPreferencesStateInjectable),
}), }),
}); });

View File

@ -13,15 +13,15 @@ import type { MonacoTheme } from "./monaco-themes";
import { type MonacoValidator, monacoValidators } from "./monaco-validators"; import { type MonacoValidator, monacoValidators } from "./monaco-validators";
import { debounce, merge } from "lodash"; import { debounce, merge } from "lodash";
import { cssNames, disposer } from "@k8slens/utilities"; import { cssNames, disposer } from "@k8slens/utilities";
import type { UserStore } from "../../../common/user-store";
import type { LensTheme } from "../../themes/lens-theme"; import type { LensTheme } from "../../themes/lens-theme";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";
import getEditorHeightFromLinesCountInjectable from "./get-editor-height-from-lines-number.injectable"; import getEditorHeightFromLinesCountInjectable from "./get-editor-height-from-lines-number.injectable";
import type { Logger } from "../../../common/logger"; import type { Logger } from "../../../common/logger";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import autoBindReact from "auto-bind/react"; import autoBindReact from "auto-bind/react";
import type { UserPreferencesState } from "../../../features/user-preferences/common/state.injectable";
import userPreferencesStateInjectable from "../../../features/user-preferences/common/state.injectable";
export type MonacoEditorId = string; export type MonacoEditorId = string;
@ -45,7 +45,7 @@ export interface MonacoEditorProps {
} }
interface Dependencies { interface Dependencies {
userStore: UserStore; state: UserPreferencesState;
activeTheme: IComputedValue<LensTheme>; activeTheme: IComputedValue<LensTheme>;
getEditorHeightFromLinesCount: (linesCount: number) => number; getEditorHeightFromLinesCount: (linesCount: number) => number;
logger: Logger; logger: Logger;
@ -116,7 +116,7 @@ class NonInjectedMonacoEditor extends React.Component<MonacoEditorProps & Depend
@computed get options(): editor.IStandaloneEditorConstructionOptions { @computed get options(): editor.IStandaloneEditorConstructionOptions {
return merge({}, return merge({},
this.props.userStore.editorConfiguration, this.props.state.editorConfiguration,
this.props.options, this.props.options,
); );
} }
@ -325,15 +325,16 @@ class NonInjectedMonacoEditor extends React.Component<MonacoEditorProps & Depend
} }
} }
export const MonacoEditor = withInjectables<Dependencies, MonacoEditorProps, MonacoEditorRef>( const ForwardedRefMonacoEditor = React.forwardRef<MonacoEditorRef, MonacoEditorProps & Dependencies>((
React.forwardRef<MonacoEditorRef, MonacoEditorProps & Dependencies>((props, ref) => <NonInjectedMonacoEditor innerRef={ref} {...props} />), (props, ref) => <NonInjectedMonacoEditor innerRef={ref} {...props} />
{ ));
getProps: (di, props) => ({
...props, export const MonacoEditor = withInjectables<Dependencies, MonacoEditorProps, MonacoEditorRef>(ForwardedRefMonacoEditor, {
userStore: di.inject(userStoreInjectable), getProps: (di, props) => ({
activeTheme: di.inject(activeThemeInjectable), ...props,
getEditorHeightFromLinesCount: di.inject(getEditorHeightFromLinesCountInjectable), state: di.inject(userPreferencesStateInjectable),
logger: di.inject(loggerInjectable), activeTheme: di.inject(activeThemeInjectable),
}), getEditorHeightFromLinesCount: di.inject(getEditorHeightFromLinesCountInjectable),
}, logger: di.inject(loggerInjectable),
); }),
});

View File

@ -3,24 +3,24 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import React from "react"; import React from "react";
import navigateToKubernetesPreferencesInjectable from "../../features/preferences/common/navigate-to-kubernetes-preferences.injectable"; import navigateToKubernetesPreferencesInjectable from "../../features/preferences/common/navigate-to-kubernetes-preferences.injectable";
import { runInAction } from "mobx"; import { runInAction } from "mobx";
import showSuccessNotificationInjectable from "../components/notifications/show-success-notification.injectable"; import showSuccessNotificationInjectable from "../components/notifications/show-success-notification.injectable";
import userPreferencesStateInjectable from "../../features/user-preferences/common/state.injectable";
const addSyncEntriesInjectable = getInjectable({ const addSyncEntriesInjectable = getInjectable({
id: "add-sync-entries", id: "add-sync-entries",
instantiate: (di) => { instantiate: (di) => {
const userStore = di.inject(userStoreInjectable); const state = di.inject(userPreferencesStateInjectable);
const navigateToKubernetesPreferences = di.inject(navigateToKubernetesPreferencesInjectable); const navigateToKubernetesPreferences = di.inject(navigateToKubernetesPreferencesInjectable);
const showSuccessNotification = di.inject(showSuccessNotificationInjectable); const showSuccessNotification = di.inject(showSuccessNotificationInjectable);
return async (paths: string[]) => { return async (paths: string[]) => {
runInAction(() => { runInAction(() => {
for (const path of paths) { for (const path of paths) {
userStore.syncKubeconfigEntries.set(path, {}); state.syncKubeconfigEntries.set(path, {});
} }
}); });

View File

@ -1,23 +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 userStoreInjectable from "../../common/user-store/user-store.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../before-frame-starts/tokens";
import initDefaultUpdateChannelInjectable from "../vars/default-update-channel/init.injectable";
const initUserStoreInjectable = getInjectable({
id: "init-user-store",
instantiate: (di) => ({
run: () => {
const userStore = di.inject(userStoreInjectable);
return userStore.load();
},
runAfter: initDefaultUpdateChannelInjectable,
}),
injectionToken: beforeFrameStartsSecondInjectionToken,
});
export default initUserStoreInjectable;

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { computed } from "mobx"; import { computed } from "mobx";
import lensColorThemePreferenceInjectable from "../../common/user-store/lens-color-theme.injectable"; import lensColorThemePreferenceInjectable from "../../features/user-preferences/common/lens-color-theme.injectable";
import { lensThemeDeclarationInjectionToken } from "./declaration"; import { lensThemeDeclarationInjectionToken } from "./declaration";
import defaultLensThemeInjectable from "./default-theme.injectable"; import defaultLensThemeInjectable from "./default-theme.injectable";
import systemThemeConfigurationInjectable from "./system-theme.injectable"; import systemThemeConfigurationInjectable from "./system-theme.injectable";

View File

@ -4,9 +4,9 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../../common/logger.injectable"; import loggerInjectable from "../../common/logger.injectable";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import { object } from "@k8slens/utilities"; import { object } from "@k8slens/utilities";
import type { LensTheme } from "./lens-theme"; import type { LensTheme } from "./lens-theme";
import resetThemeInjectable from "../../features/user-preferences/common/reset-theme.injectable";
export type ApplyLensTheme = (theme: LensTheme) => void; export type ApplyLensTheme = (theme: LensTheme) => void;
@ -14,7 +14,7 @@ const applyLensThemeInjectable = getInjectable({
id: "apply-lens-theme", id: "apply-lens-theme",
instantiate: (di): ApplyLensTheme => { instantiate: (di): ApplyLensTheme => {
const logger = di.inject(loggerInjectable); const logger = di.inject(loggerInjectable);
const userStore = di.inject(userStoreInjectable); const resetTheme = di.inject(resetThemeInjectable);
return (theme) => { return (theme) => {
try { try {
@ -28,7 +28,7 @@ const applyLensThemeInjectable = getInjectable({
document.body.classList.toggle("theme-light", theme.type === "light"); document.body.classList.toggle("theme-light", theme.type === "light");
} catch (error) { } catch (error) {
logger.error("[THEME]: Failed to apply active theme", error); logger.error("[THEME]: Failed to apply active theme", error);
userStore.resetTheme(); resetTheme();
} }
}; };
}, },

View File

@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import { reaction } from "mobx"; import { reaction } from "mobx";
import initializeSystemThemeTypeInjectable from "../../features/theme/system-type/renderer/initialize.injectable"; import initializeSystemThemeTypeInjectable from "../../features/theme/system-type/renderer/initialize.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../before-frame-starts/tokens"; import { beforeFrameStartsSecondInjectionToken } from "../before-frame-starts/tokens";
import initUserStoreInjectable from "../stores/init-user-store.injectable"; import initUserStoreInjectable from "../../features/user-preferences/renderer/load-storage.injectable";
import activeThemeInjectable from "./active.injectable"; import activeThemeInjectable from "./active.injectable";
import applyLensThemeInjectable from "./apply-lens-theme.injectable"; import applyLensThemeInjectable from "./apply-lens-theme.injectable";

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import terminalThemePreferenceInjectable from "../../common/user-store/terminal-theme.injectable"; import terminalThemePreferenceInjectable from "../../features/user-preferences/common/terminal-theme.injectable";
import activeThemeInjectable from "./active.injectable"; import activeThemeInjectable from "./active.injectable";
import lensThemesInjectable from "./themes.injectable"; import lensThemesInjectable from "./themes.injectable";

View File

@ -63,6 +63,7 @@ export const getOverrideFsWithFakes = () => {
createReadStream: root.createReadStream as any, createReadStream: root.createReadStream as any,
stat: root.promises.stat as any, stat: root.promises.stat as any,
unlink: root.promises.unlink, unlink: root.promises.unlink,
rename: root.promises.rename,
})); }));
}; };
}; };