From afa5379ba9d74bba6ad5091197ceb221533716a1 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 27 Apr 2021 09:44:02 -0400 Subject: [PATCH] Flatten user preferences in user store (#2587) Signed-off-by: Sebastian Malton --- src/common/__tests__/user-store.test.ts | 14 +- src/common/request.ts | 2 +- src/common/user-store.ts | 125 ++++++++++++++---- src/common/utils/index.ts | 15 ++- src/common/utils/toggle-set.ts | 20 +++ src/main/kubectl.ts | 14 +- src/main/shell-session/local-shell-session.ts | 4 +- src/main/shell-session/shell-session.ts | 2 +- src/migrations/user-store/5.0.0-alpha.3.ts | 18 +++ src/migrations/user-store/index.ts | 2 + .../+preferences/kubectl-binaries.tsx | 29 ++-- .../components/+preferences/preferences.tsx | 25 ++-- src/renderer/components/dock/log-list.tsx | 3 +- .../item-object-list/item-list-layout.tsx | 50 +++---- .../components/locale-date/locale-date.tsx | 3 +- src/renderer/theme.store.ts | 2 +- 16 files changed, 212 insertions(+), 116 deletions(-) create mode 100644 src/common/utils/toggle-set.ts create mode 100644 src/migrations/user-store/5.0.0-alpha.3.ts diff --git a/src/common/__tests__/user-store.test.ts b/src/common/__tests__/user-store.test.ts index e4622ffa64..7e007efb0d 100644 --- a/src/common/__tests__/user-store.test.ts +++ b/src/common/__tests__/user-store.test.ts @@ -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", () => { diff --git a/src/common/request.ts b/src/common/request.ts index 8c78c865fa..e2b9062916 100644 --- a/src/common/request.ts +++ b/src/common/request.ts @@ -6,7 +6,7 @@ import { UserStore } from "./user-store"; // https://github.com/lensapp/lens/issues/459 function getDefaultRequestOpts(): Partial { - const { httpsProxy, allowUntrustedCAs } = UserStore.getInstance().preferences; + const { httpsProxy, allowUntrustedCAs } = UserStore.getInstance(); return { proxy: httpsProxy || undefined, diff --git a/src/common/user-store.ts b/src/common/user-store.ts index 0532cc59bc..1118344d02 100644 --- a/src/common/user-store.ts +++ b/src/common/user-store.ts @@ -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; + hiddenTableColumns?: [string, string[]][]; } export class UserStore extends BaseStore { @@ -48,20 +49,29 @@ export class UserStore extends BaseStore { } @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(); @observable newContexts = observable.set(); + @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>(); protected async handleOnLoad() { await this.whenLoaded; @@ -72,12 +82,12 @@ export class UserStore extends BaseStore { 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 { return super.load(); } - get isNewVersion() { + @computed get isNewVersion() { return semver.gt(getAppVersion(), this.lastSeenAppVersion); } - @action - setHiddenTableColumns(tableId: string, names: Set | 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 { - 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 { @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 { @action setLocaleTimezone(tz: string) { - this.preferences.localeTimezone = tz; + this.localeTimezone = tz; } protected refreshNewContexts = async () => { @@ -175,15 +208,55 @@ export class UserStore extends BaseStore { 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, { diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 7ed9fc9d05..edb2b44d96 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -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"; diff --git a/src/common/utils/toggle-set.ts b/src/common/utils/toggle-set.ts new file mode 100644 index 0000000000..1a8b22f186 --- /dev/null +++ b/src/common/utils/toggle-set.ts @@ -0,0 +1,20 @@ +import { action, ObservableSet } from "mobx"; + +export class ToggleSet extends Set { + 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 extends ObservableSet { + @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); + } + } +} diff --git a/src/main/kubectl.ts b/src/main/kubectl.ts index 903f54ff07..104f44f0d7 100644 --- a/src/main/kubectl.ts +++ b/src/main/kubectl.ts @@ -113,12 +113,12 @@ export class Kubectl { } public getPathFromPreferences() { - return UserStore.getInstance().preferences?.kubectlBinariesPath || this.getBundledPath(); + return UserStore.getInstance().kubectlBinariesPath || this.getBundledPath(); } protected getDownloadDir() { - if (UserStore.getInstance().preferences?.downloadBinariesPath) { - return path.join(UserStore.getInstance().preferences.downloadBinariesPath, "kubectl"); + if (UserStore.getInstance().downloadBinariesPath) { + return path.join(UserStore.getInstance().downloadBinariesPath, "kubectl"); } return Kubectl.kubectlDir; @@ -129,7 +129,7 @@ export class Kubectl { return this.getBundledPath(); } - if (UserStore.getInstance().preferences?.downloadKubectlBinaries === false) { + if (UserStore.getInstance().downloadKubectlBinaries === false) { return this.getPathFromPreferences(); } @@ -223,7 +223,7 @@ export class Kubectl { } public async ensureKubectl(): Promise { - if (UserStore.getInstance().preferences?.downloadKubectlBinaries === false) { + if (UserStore.getInstance().downloadKubectlBinaries === false) { return true; } @@ -303,7 +303,7 @@ export class Kubectl { } protected async writeInitScripts() { - const kubectlPath = UserStore.getInstance().preferences?.downloadKubectlBinaries ? this.dirname : path.dirname(this.getPathFromPreferences()); + const kubectlPath = UserStore.getInstance().downloadKubectlBinaries ? this.dirname : path.dirname(this.getPathFromPreferences()); const helmPath = helmCli.getBinaryDir(); const fsPromises = fs.promises; const bashScriptPath = path.join(this.dirname, ".bash_set_path"); @@ -361,7 +361,7 @@ export class Kubectl { } protected getDownloadMirror() { - const mirror = packageMirrors.get(UserStore.getInstance().preferences?.downloadMirror); + const mirror = packageMirrors.get(UserStore.getInstance().downloadMirror); if (mirror) { return mirror; diff --git a/src/main/shell-session/local-shell-session.ts b/src/main/shell-session/local-shell-session.ts index c500ff169f..6bfc9441cf 100644 --- a/src/main/shell-session/local-shell-session.ts +++ b/src/main/shell-session/local-shell-session.ts @@ -21,8 +21,8 @@ export class LocalShellSession extends ShellSession { protected async getShellArgs(shell: string): Promise { const helmpath = helmCli.getBinaryDir(); - const pathFromPreferences = UserStore.getInstance().preferences.kubectlBinariesPath || this.kubectl.getBundledPath(); - const kubectlPathDir = UserStore.getInstance().preferences.downloadKubectlBinaries ? await this.kubectlBinDirP : path.dirname(pathFromPreferences); + const pathFromPreferences = UserStore.getInstance().kubectlBinariesPath || this.kubectl.getBundledPath(); + const kubectlPathDir = UserStore.getInstance().downloadKubectlBinaries ? await this.kubectlBinDirP : path.dirname(pathFromPreferences); switch(path.basename(shell)) { case "powershell.exe": diff --git a/src/main/shell-session/shell-session.ts b/src/main/shell-session/shell-session.ts index 37c948f6f6..599f84e42b 100644 --- a/src/main/shell-session/shell-session.ts +++ b/src/main/shell-session/shell-session.ts @@ -119,7 +119,7 @@ export abstract class ShellSession { protected async getShellEnv() { const env = clearKubeconfigEnvVars(JSON.parse(JSON.stringify(await shellEnv()))); const pathStr = [...this.getPathEntries(), await this.kubectlBinDirP, process.env.PATH].join(path.delimiter); - const shell = UserStore.getInstance().preferences.shell || process.env.SHELL || process.env.PTYSHELL; + const shell = UserStore.getInstance().resolvedShell; delete env.DEBUG; // don't pass DEBUG into shells diff --git a/src/migrations/user-store/5.0.0-alpha.3.ts b/src/migrations/user-store/5.0.0-alpha.3.ts new file mode 100644 index 0000000000..ae90b85525 --- /dev/null +++ b/src/migrations/user-store/5.0.0-alpha.3.ts @@ -0,0 +1,18 @@ +// Switch representation of hiddenTableColumns in store +import { migration } from "../migration-wrapper"; + +export default migration({ + version: "5.0.0-alpha.3", + run(store) { + const preferences = store.get("preferences"); + const oldHiddenTableColumns: Record = preferences?.hiddenTableColumns; + + if (!oldHiddenTableColumns) { + return; + } + + preferences.hiddenTableColumns = Object.entries(oldHiddenTableColumns); + + store.set("preferences", preferences); + } +}); diff --git a/src/migrations/user-store/index.ts b/src/migrations/user-store/index.ts index 5f5085b475..c8733fdd8a 100644 --- a/src/migrations/user-store/index.ts +++ b/src/migrations/user-store/index.ts @@ -1,6 +1,7 @@ // User store migrations import version210Beta4 from "./2.1.0-beta.4"; +import version500Alpha3 from "./5.0.0-alpha.3"; import { fileNameMigration } from "./file-name-migration"; export { @@ -9,4 +10,5 @@ export { export default { ...version210Beta4, + ...version500Alpha3, }; diff --git a/src/renderer/components/+preferences/kubectl-binaries.tsx b/src/renderer/components/+preferences/kubectl-binaries.tsx index eb1dfca1c5..f9c3bfdacb 100644 --- a/src/renderer/components/+preferences/kubectl-binaries.tsx +++ b/src/renderer/components/+preferences/kubectl-binaries.tsx @@ -1,15 +1,16 @@ import React, { useState } from "react"; import { Input, InputValidators } from "../input"; import { SubTitle } from "../layout/sub-title"; -import { getDefaultKubectlPath, UserPreferences } from "../../../common/user-store"; +import { getDefaultKubectlPath, UserStore } from "../../../common/user-store"; import { observer } from "mobx-react"; import { bundledKubectlPath } from "../../../main/kubectl"; import { SelectOption, Select } from "../select"; import { FormSwitch, Switcher } from "../switch"; -export const KubectlBinaries = observer(({ preferences }: { preferences: UserPreferences }) => { - const [downloadPath, setDownloadPath] = useState(preferences.downloadBinariesPath || ""); - const [binariesPath, setBinariesPath] = useState(preferences.kubectlBinariesPath || ""); +export const KubectlBinaries = observer(() => { + const userStore = UserStore.getInstance(); + const [downloadPath, setDownloadPath] = useState(userStore.downloadBinariesPath || ""); + const [binariesPath, setBinariesPath] = useState(userStore.kubectlBinariesPath || ""); const pathValidator = downloadPath ? InputValidators.isPath : undefined; const downloadMirrorOptions: SelectOption[] = [ @@ -18,8 +19,8 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre ]; const save = () => { - preferences.downloadBinariesPath = downloadPath; - preferences.kubectlBinariesPath = binariesPath; + userStore.downloadBinariesPath = downloadPath; + userStore.kubectlBinariesPath = binariesPath; }; return ( @@ -29,8 +30,8 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre preferences.downloadKubectlBinaries = v.target.checked} + checked={userStore.downloadKubectlBinaries} + onChange={v => userStore.downloadKubectlBinaries = v.target.checked} name="kubectl-download" /> } @@ -45,9 +46,9 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre
The directory to download binaries into. @@ -81,7 +82,7 @@ export const KubectlBinaries = observer(({ preferences }: { preferences: UserPre validators={pathValidator} onChange={setBinariesPath} onBlur={save} - disabled={preferences.downloadKubectlBinaries} + disabled={userStore.downloadKubectlBinaries} /> diff --git a/src/renderer/components/+preferences/preferences.tsx b/src/renderer/components/+preferences/preferences.tsx index c5d1c92db0..d101d614ba 100644 --- a/src/renderer/components/+preferences/preferences.tsx +++ b/src/renderer/components/+preferences/preferences.tsx @@ -30,8 +30,8 @@ enum Pages { @observer export class Preferences extends React.Component { - @observable httpProxy = UserStore.getInstance().preferences.httpsProxy || ""; - @observable shell = UserStore.getInstance().preferences.shell || ""; + @observable httpProxy = UserStore.getInstance().httpsProxy || ""; + @observable shell = UserStore.getInstance().shell || ""; @observable activeTab = Pages.Application; @computed get themeOptions(): SelectOption[] { @@ -100,7 +100,6 @@ export class Preferences extends React.Component { render() { const extensions = appPreferenceRegistry.getItems(); const telemetryExtensions = extensions.filter(e => e.showInPreferencesTab == Pages.Telemetry); - const { preferences } = UserStore.getInstance(); const defaultShell = process.env.SHELL || process.env.PTYSHELL || ( @@ -123,8 +122,8 @@ export class Preferences extends React.Component { UserStore.getInstance().setLocaleTimezone(value)} themeName="lens" /> @@ -181,7 +180,7 @@ export class Preferences extends React.Component { placeholder="Type HTTP proxy url (example: http://proxy.acme.org:8080)" value={this.httpProxy} onChange={v => this.httpProxy = v} - onBlur={() => preferences.httpsProxy = this.httpProxy} + onBlur={() => UserStore.getInstance().httpsProxy = this.httpProxy} /> Proxy is used only for non-cluster communication. @@ -195,8 +194,8 @@ export class Preferences extends React.Component { preferences.allowUntrustedCAs = v.target.checked} + checked={UserStore.getInstance().allowUntrustedCAs} + onChange={v => UserStore.getInstance().allowUntrustedCAs = v.target.checked} name="startup" /> } @@ -215,7 +214,7 @@ export class Preferences extends React.Component {

Kubernetes

- +

diff --git a/src/renderer/components/dock/log-list.tsx b/src/renderer/components/dock/log-list.tsx index 9c5accf1ef..1eafe0f15a 100644 --- a/src/renderer/components/dock/log-list.tsx +++ b/src/renderer/components/dock/log-list.tsx @@ -81,7 +81,6 @@ export class LogList extends React.Component { @computed get logs() { const showTimestamps = logTabStore.getData(this.props.id).showTimestamps; - const { preferences } = UserStore.getInstance(); if (!showTimestamps) { return logStore.logsWithoutTimestamps; @@ -89,7 +88,7 @@ export class LogList extends React.Component { return this.props.logs .map(log => logStore.splitOutTimestamp(log)) - .map(([logTimestamp, log]) => (`${moment.tz(logTimestamp, preferences.localeTimezone).format()}${log}`)); + .map(([logTimestamp, log]) => (`${moment.tz(logTimestamp, UserStore.getInstance().localeTimezone).format()}${log}`)); } /** diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index 95d9667a56..d3424f2c0a 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -6,7 +6,7 @@ import { computed } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { ConfirmDialog, ConfirmDialogParams } from "../confirm-dialog"; import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRow, TableRowProps, TableSortCallback } from "../table"; -import { autobind, createStorage, cssNames, IClassName, isReactNode, noop, prevDefault, stopPropagation } from "../../utils"; +import { autobind, createStorage, cssNames, IClassName, isReactNode, noop, ObservableToggleSet, prevDefault, stopPropagation } from "../../utils"; import { AddRemoveButtons, AddRemoveButtonsProps } from "../add-remove-buttons"; import { NoItems } from "../no-items"; import { Spinner } from "../spinner"; @@ -117,6 +117,10 @@ export class ItemListLayout extends React.Component { throw new Error("[ItemListLayout]: configurable list require props.tableId to be specified"); } + if (isConfigurable && !UserStore.getInstance().hiddenTableColumns.has(tableId)) { + UserStore.getInstance().hiddenTableColumns.set(tableId, new ObservableToggleSet()); + } + if (preloadStores) { this.loadStores(); @@ -251,7 +255,7 @@ export class ItemListLayout extends React.Component { cellProps.className = cssNames(cellProps.className, headCell.className); } - if (!headCell || !this.isHiddenColumn(headCell)) { + if (!headCell || this.showColumn(headCell)) { return ; } }) @@ -420,11 +424,11 @@ export class ItemListLayout extends React.Component { onClick={prevDefault(() => store.toggleSelectionAll(enabledItems))} /> )} - {renderTableHeader.map((cellProps, index) => { - if (!this.isHiddenColumn(cellProps)) { - return ; - } - })} + {renderTableHeader.map((cellProps, index) => ( + this.showColumn(cellProps) && ( + + ) + ))} {isConfigurable && this.renderColumnVisibilityMenu()} @@ -468,34 +472,14 @@ export class ItemListLayout extends React.Component { ); } - @computed get hiddenColumns() { - return UserStore.getInstance().getHiddenTableColumns(this.props.tableId); - } + showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean { + const { tableId, isConfigurable } = this.props; - isHiddenColumn({ id: columnId, showWithColumn }: TableCellProps): boolean { - if (!this.props.isConfigurable) { - return false; - } - - return this.hiddenColumns.has(columnId) || ( - showWithColumn && this.hiddenColumns.has(showWithColumn) - ); - } - - updateColumnVisibility({ id: columnId }: TableCellProps, isVisible: boolean) { - const hiddenColumns = new Set(this.hiddenColumns); - - if (!isVisible) { - hiddenColumns.add(columnId); - } else { - hiddenColumns.delete(columnId); - } - - UserStore.getInstance().setHiddenTableColumns(this.props.tableId, hiddenColumns); + return !isConfigurable || !UserStore.getInstance().isTableColumnHidden(tableId, columnId, showWithColumn); } renderColumnVisibilityMenu() { - const { renderTableHeader } = this.props; + const { renderTableHeader, tableId } = this.props; return ( @@ -504,8 +488,8 @@ export class ItemListLayout extends React.Component { `} - value={!this.isHiddenColumn(cellProps)} - onChange={isVisible => this.updateColumnVisibility(cellProps, isVisible)} + value={this.showColumn(cellProps)} + onChange={() => UserStore.getInstance().toggleTableColumnVisibility(tableId, cellProps.id)} /> ) diff --git a/src/renderer/components/locale-date/locale-date.tsx b/src/renderer/components/locale-date/locale-date.tsx index 42223bbf69..f8dcd19ef8 100644 --- a/src/renderer/components/locale-date/locale-date.tsx +++ b/src/renderer/components/locale-date/locale-date.tsx @@ -10,9 +10,8 @@ interface Props { @observer export class LocaleDate extends React.Component { render() { - const { preferences } = UserStore.getInstance(); const { date } = this.props; - return <>{moment.tz(date, preferences.localeTimezone).format()}; + return moment.tz(date, UserStore.getInstance().localeTimezone).format(); } } diff --git a/src/renderer/theme.store.ts b/src/renderer/theme.store.ts index 8e517341f3..07b663a5cc 100644 --- a/src/renderer/theme.store.ts +++ b/src/renderer/theme.store.ts @@ -38,7 +38,7 @@ export class ThemeStore extends Singleton { } @computed get activeThemeId(): string { - return UserStore.getInstance().preferences.colorTheme; + return UserStore.getInstance().colorTheme; } @computed get activeTheme(): Theme {