mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Flatten user preferences in user store (#2587)
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
119d584bcb
commit
afa5379ba9
16 files changed
+212
-116
No files matched your search
@@ -60,13 +60,13 @@ describe("user store tests", () => {
|
||||
it("allows setting and getting preferences", () => {
|
||||
const us = UserStore.getInstance();
|
||||
|
||||
us.preferences.httpsProxy = "abcd://defg";
|
||||
us.httpsProxy = "abcd://defg";
|
||||
|
||||
expect(us.preferences.httpsProxy).toBe("abcd://defg");
|
||||
expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme);
|
||||
expect(us.httpsProxy).toBe("abcd://defg");
|
||||
expect(us.colorTheme).toBe(UserStore.defaultTheme);
|
||||
|
||||
us.preferences.colorTheme = "light";
|
||||
expect(us.preferences.colorTheme).toBe("light");
|
||||
us.colorTheme = "light";
|
||||
expect(us.colorTheme).toBe("light");
|
||||
});
|
||||
|
||||
it("correctly resets theme to default value", async () => {
|
||||
@@ -74,9 +74,9 @@ describe("user store tests", () => {
|
||||
|
||||
us.isLoaded = true;
|
||||
|
||||
us.preferences.colorTheme = "some other theme";
|
||||
us.colorTheme = "some other theme";
|
||||
await us.resetTheme();
|
||||
expect(us.preferences.colorTheme).toBe(UserStore.defaultTheme);
|
||||
expect(us.colorTheme).toBe(UserStore.defaultTheme);
|
||||
});
|
||||
|
||||
it("correctly calculates if the last seen version is an old release", () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { UserStore } from "./user-store";
|
||||
// https://github.com/lensapp/lens/issues/459
|
||||
|
||||
function getDefaultRequestOpts(): Partial<request.Options> {
|
||||
const { httpsProxy, allowUntrustedCAs } = UserStore.getInstance().preferences;
|
||||
const { httpsProxy, allowUntrustedCAs } = UserStore.getInstance();
|
||||
|
||||
return {
|
||||
proxy: httpsProxy || undefined,
|
||||
|
||||
+99
-26
@@ -12,15 +12,16 @@ import { appEventBus } from "./event-bus";
|
||||
import logger from "../main/logger";
|
||||
import path from "path";
|
||||
import { fileNameMigration } from "../migrations/user-store";
|
||||
import { ObservableToggleSet } from "../renderer/utils";
|
||||
|
||||
export interface UserStoreModel {
|
||||
kubeConfigPath: string;
|
||||
lastSeenAppVersion: string;
|
||||
seenContexts: string[];
|
||||
preferences: UserPreferences;
|
||||
preferences: UserPreferencesModel;
|
||||
}
|
||||
|
||||
export interface UserPreferences {
|
||||
export interface UserPreferencesModel {
|
||||
httpsProxy?: string;
|
||||
shell?: string;
|
||||
colorTheme?: string;
|
||||
@@ -32,7 +33,7 @@ export interface UserPreferences {
|
||||
downloadBinariesPath?: string;
|
||||
kubectlBinariesPath?: string;
|
||||
openAtLogin?: boolean;
|
||||
hiddenTableColumns?: Record<string, string[]>;
|
||||
hiddenTableColumns?: [string, string[]][];
|
||||
}
|
||||
|
||||
export class UserStore extends BaseStore<UserStoreModel> {
|
||||
@@ -48,20 +49,29 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
}
|
||||
|
||||
@observable lastSeenAppVersion = "0.0.0";
|
||||
@observable kubeConfigPath = kubeConfigDefaultPath; // used in add-cluster page for providing context
|
||||
|
||||
/**
|
||||
* used in add-cluster page for providing context
|
||||
*/
|
||||
@observable kubeConfigPath = kubeConfigDefaultPath;
|
||||
@observable seenContexts = observable.set<string>();
|
||||
@observable newContexts = observable.set<string>();
|
||||
@observable allowTelemetry = true;
|
||||
@observable allowUntrustedCAs = false;
|
||||
@observable colorTheme = UserStore.defaultTheme;
|
||||
@observable localeTimezone = moment.tz.guess(true) || "UTC";
|
||||
@observable downloadMirror = "default";
|
||||
@observable httpsProxy?: string;
|
||||
@observable shell?: string;
|
||||
@observable downloadBinariesPath?: string;
|
||||
@observable kubectlBinariesPath?: string;
|
||||
|
||||
@observable preferences: UserPreferences = {
|
||||
allowTelemetry: true,
|
||||
allowUntrustedCAs: false,
|
||||
colorTheme: UserStore.defaultTheme,
|
||||
localeTimezone: moment.tz.guess(true) || "UTC",
|
||||
downloadMirror: "default",
|
||||
downloadKubectlBinaries: true, // Download kubectl binaries matching cluster version
|
||||
openAtLogin: false,
|
||||
hiddenTableColumns: {},
|
||||
};
|
||||
/**
|
||||
* Download kubectl binaries matching cluster version
|
||||
*/
|
||||
@observable downloadKubectlBinaries = true;
|
||||
@observable openAtLogin = false;
|
||||
hiddenTableColumns = observable.map<string, ObservableToggleSet<string>>();
|
||||
|
||||
protected async handleOnLoad() {
|
||||
await this.whenLoaded;
|
||||
@@ -72,12 +82,12 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
|
||||
if (app) {
|
||||
// track telemetry availability
|
||||
reaction(() => this.preferences.allowTelemetry, allowed => {
|
||||
reaction(() => this.allowTelemetry, allowed => {
|
||||
appEventBus.emit({ name: "telemetry", action: allowed ? "enabled" : "disabled" });
|
||||
});
|
||||
|
||||
// open at system start-up
|
||||
reaction(() => this.preferences.openAtLogin, openAtLogin => {
|
||||
reaction(() => this.openAtLogin, openAtLogin => {
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin,
|
||||
openAsHidden: true,
|
||||
@@ -99,17 +109,40 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
return super.load();
|
||||
}
|
||||
|
||||
get isNewVersion() {
|
||||
@computed get isNewVersion() {
|
||||
return semver.gt(getAppVersion(), this.lastSeenAppVersion);
|
||||
}
|
||||
|
||||
@action
|
||||
setHiddenTableColumns(tableId: string, names: Set<string> | string[]) {
|
||||
this.preferences.hiddenTableColumns[tableId] = Array.from(names);
|
||||
@computed get resolvedShell(): string | undefined {
|
||||
return this.shell || process.env.SHELL || process.env.PTYSHELL;
|
||||
}
|
||||
|
||||
getHiddenTableColumns(tableId: string): Set<string> {
|
||||
return new Set(this.preferences.hiddenTableColumns[tableId]);
|
||||
/**
|
||||
* 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[]): boolean {
|
||||
if (columnIds.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const config = this.hiddenTableColumns.get(tableId);
|
||||
|
||||
if (!config) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return columnIds.some(columnId => config.has(columnId));
|
||||
}
|
||||
|
||||
@action
|
||||
/**
|
||||
* Toggles the hidden configuration of a table's column
|
||||
*/
|
||||
toggleTableColumnVisibility(tableId: string, columnId: string) {
|
||||
this.hiddenTableColumns.get(tableId)?.toggle(columnId);
|
||||
}
|
||||
|
||||
@action
|
||||
@@ -124,7 +157,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
@action
|
||||
async resetTheme() {
|
||||
await this.whenLoaded;
|
||||
this.preferences.colorTheme = UserStore.defaultTheme;
|
||||
this.colorTheme = UserStore.defaultTheme;
|
||||
}
|
||||
|
||||
@action
|
||||
@@ -135,7 +168,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
|
||||
@action
|
||||
setLocaleTimezone(tz: string) {
|
||||
this.preferences.localeTimezone = tz;
|
||||
this.localeTimezone = tz;
|
||||
}
|
||||
|
||||
protected refreshNewContexts = async () => {
|
||||
@@ -175,15 +208,55 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
this.kubeConfigPath = kubeConfigPath;
|
||||
}
|
||||
this.seenContexts.replace(seenContexts);
|
||||
Object.assign(this.preferences, preferences);
|
||||
|
||||
if (!preferences) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.httpsProxy = preferences.httpsProxy;
|
||||
this.shell = preferences.shell;
|
||||
this.colorTheme = preferences.colorTheme;
|
||||
this.localeTimezone = preferences.localeTimezone;
|
||||
this.allowUntrustedCAs = preferences.allowUntrustedCAs;
|
||||
this.allowTelemetry = preferences.allowTelemetry;
|
||||
this.downloadMirror = preferences.downloadMirror;
|
||||
this.downloadKubectlBinaries = preferences.downloadKubectlBinaries;
|
||||
this.downloadBinariesPath = preferences.downloadBinariesPath;
|
||||
this.kubectlBinariesPath = preferences.kubectlBinariesPath;
|
||||
this.openAtLogin = preferences.openAtLogin;
|
||||
|
||||
this.hiddenTableColumns.clear();
|
||||
|
||||
for (const [tableId, columnIds] of preferences.hiddenTableColumns ?? []) {
|
||||
this.hiddenTableColumns.set(tableId, new ObservableToggleSet(columnIds));
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(): UserStoreModel {
|
||||
const hiddenTableColumns: [string, string[]][] = [];
|
||||
|
||||
for (const [key, values] of this.hiddenTableColumns.entries()) {
|
||||
hiddenTableColumns.push([key, Array.from(values)]);
|
||||
}
|
||||
|
||||
const model: UserStoreModel = {
|
||||
kubeConfigPath: this.kubeConfigPath,
|
||||
lastSeenAppVersion: this.lastSeenAppVersion,
|
||||
seenContexts: Array.from(this.seenContexts),
|
||||
preferences: this.preferences,
|
||||
preferences: {
|
||||
httpsProxy: this.httpsProxy,
|
||||
shell: this.shell,
|
||||
colorTheme: this.colorTheme,
|
||||
localeTimezone: this.localeTimezone,
|
||||
allowUntrustedCAs: this.allowUntrustedCAs,
|
||||
allowTelemetry: this.allowTelemetry,
|
||||
downloadMirror: this.downloadMirror,
|
||||
downloadKubectlBinaries: this.downloadKubectlBinaries,
|
||||
downloadBinariesPath: this.downloadBinariesPath,
|
||||
kubectlBinariesPath: this.kubectlBinariesPath,
|
||||
openAtLogin: this.openAtLogin,
|
||||
hiddenTableColumns,
|
||||
},
|
||||
};
|
||||
|
||||
return toJS(model, {
|
||||
|
||||
@@ -7,19 +7,20 @@ export * from "./autobind";
|
||||
export * from "./base64";
|
||||
export * from "./camelCase";
|
||||
export * from "./cloneJson";
|
||||
export * from "./delay";
|
||||
export * from "./debouncePromise";
|
||||
export * from "./defineGlobal";
|
||||
export * from "./getRandId";
|
||||
export * from "./splitArray";
|
||||
export * from "./saveToAppFiles";
|
||||
export * from "./singleton";
|
||||
export * from "./openExternal";
|
||||
export * from "./delay";
|
||||
export * from "./disposer";
|
||||
export * from "./downloadFile";
|
||||
export * from "./escapeRegExp";
|
||||
export * from "./getRandId";
|
||||
export * from "./openExternal";
|
||||
export * from "./saveToAppFiles";
|
||||
export * from "./singleton";
|
||||
export * from "./splitArray";
|
||||
export * from "./tar";
|
||||
export * from "./toggle-set";
|
||||
export * from "./type-narrowing";
|
||||
export * from "./disposer";
|
||||
|
||||
import * as iter from "./iter";
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { action, ObservableSet } from "mobx";
|
||||
|
||||
export class ToggleSet<T> extends Set<T> {
|
||||
public toggle(value: T): void {
|
||||
if (!this.delete(value)) {
|
||||
// Set.prototype.delete returns false if `value` was not in the set
|
||||
this.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ObservableToggleSet<T> extends ObservableSet<T> {
|
||||
@action
|
||||
public toggle(value: T): void {
|
||||
if (!this.delete(value)) {
|
||||
// Set.prototype.delete returns false if `value` was not in the set
|
||||
this.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user