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

fix: apply theme on the fly in preferences, theme-store refactoring

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-07-23 18:26:16 +03:00
parent 6fd9b7cf76
commit 407c4fb4d0
15 changed files with 322 additions and 315 deletions

View File

@ -116,11 +116,11 @@ msgstr "Add field"
#~ msgid "Added repos"
#~ msgstr "Added repos"
#: src/renderer/components/+preferences/preferences.tsx:149
#: src/renderer/components/+preferences/preferences.tsx:147
msgid "Added repos:"
msgstr "Added repos:"
#: src/renderer/components/+preferences/preferences.tsx:108
#: src/renderer/components/+preferences/preferences.tsx:106
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
msgstr "Adding helm branch <0>{0}</0> has failed: {1}"
@ -202,11 +202,11 @@ msgstr "Allocatable"
msgid "Allow Privilege Escalation"
msgstr "Allow Privilege Escalation"
#: src/renderer/components/+preferences/preferences.tsx:177
#: src/renderer/components/+preferences/preferences.tsx:175
msgid "Allow telemetry & usage tracking"
msgstr "Allow telemetry & usage tracking"
#: src/renderer/components/+preferences/preferences.tsx:169
#: src/renderer/components/+preferences/preferences.tsx:167
msgid "Allow untrusted Certificate Authorities"
msgstr "Allow untrusted Certificate Authorities"
@ -401,7 +401,7 @@ msgstr "Cancel"
msgid "Capacity"
msgstr "Capacity"
#: src/renderer/components/+preferences/preferences.tsx:168
#: src/renderer/components/+preferences/preferences.tsx:166
msgid "Certificate Trust"
msgstr "Certificate Trust"
@ -468,7 +468,7 @@ msgstr "Cluster IP"
msgid "Cluster Issuers"
msgstr "Cluster Issuers"
#: src/renderer/components/+preferences/preferences.tsx:139
#: src/renderer/components/+preferences/preferences.tsx:137
msgid "Color Theme"
msgstr "Color Theme"
@ -717,7 +717,7 @@ msgstr "Daemon Sets"
msgid "DaemonSets"
msgstr "DaemonSets"
#: src/renderer/components/+preferences/preferences.tsx:40
#: src/renderer/theme.store.ts:32
msgid "Dark"
msgstr "Dark"
@ -780,7 +780,7 @@ msgstr "Disk"
msgid "Disk:"
msgstr "Disk:"
#: src/renderer/components/+preferences/preferences.tsx:173
#: src/renderer/components/+preferences/preferences.tsx:171
msgid "Does not affect cluster communications!"
msgstr "Does not affect cluster communications!"
@ -788,7 +788,7 @@ msgstr "Does not affect cluster communications!"
msgid "Domains"
msgstr "Domains"
#: src/renderer/components/+preferences/preferences.tsx:142
#: src/renderer/components/+preferences/preferences.tsx:140
msgid "Download Mirror"
msgstr "Download Mirror"
@ -796,7 +796,7 @@ msgstr "Download Mirror"
msgid "Download file"
msgstr "Download file"
#: src/renderer/components/+preferences/preferences.tsx:143
#: src/renderer/components/+preferences/preferences.tsx:141
msgid "Download mirror for kubectl"
msgstr "Download mirror for kubectl"
@ -967,7 +967,7 @@ msgstr "Groups"
msgid "HPA"
msgstr "HPA"
#: src/renderer/components/+preferences/preferences.tsx:162
#: src/renderer/components/+preferences/preferences.tsx:160
msgid "HTTP Proxy"
msgstr "HTTP Proxy"
@ -975,7 +975,7 @@ msgstr "HTTP Proxy"
msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
msgstr "HTTP Proxy server. Used for communicating with Kubernetes API."
#: src/renderer/components/+preferences/preferences.tsx:145
#: src/renderer/components/+preferences/preferences.tsx:143
msgid "Helm"
msgstr "Helm"
@ -995,7 +995,7 @@ msgstr "Helm Install: {repo}/{name}"
msgid "Helm Upgrade: {0}"
msgstr "Helm Upgrade: {0}"
#: src/renderer/components/+preferences/preferences.tsx:61
#: src/renderer/components/+preferences/preferences.tsx:50
msgid "Helm branch <0>{0}</0> already in use"
msgstr "Helm branch <0>{0}</0> already in use"
@ -1209,7 +1209,7 @@ msgstr "Last seen"
msgid "Last transition time: {lastTransitionTime}"
msgstr "Last transition time: {lastTransitionTime}"
#: src/renderer/components/+preferences/preferences.tsx:131
#: src/renderer/components/+preferences/preferences.tsx:129
msgid "Lens Global Settings"
msgstr "Lens Global Settings"
@ -1217,7 +1217,7 @@ msgstr "Lens Global Settings"
msgid "Level"
msgstr "Level"
#: src/renderer/components/+preferences/preferences.tsx:41
#: src/renderer/theme.store.ts:33
msgid "Light"
msgstr "Light"
@ -1485,7 +1485,7 @@ msgstr "Namespaces"
msgid "Namespaces: {0}"
msgstr "Namespaces: {0}"
#: src/renderer/components/+preferences/preferences.tsx:172
#: src/renderer/components/+preferences/preferences.tsx:170
msgid "Needed with some corporate proxies that do certificate re-writing."
msgstr "Needed with some corporate proxies that do certificate re-writing."
@ -1755,7 +1755,7 @@ msgstr "Port"
msgid "Ports"
msgstr "Ports"
#: src/renderer/components/+preferences/preferences.tsx:126
#: src/renderer/components/+preferences/preferences.tsx:124
msgid "Preferences"
msgstr "Preferences"
@ -1777,7 +1777,7 @@ msgstr "Privileged"
msgid "Provisioner"
msgstr "Provisioner"
#: src/renderer/components/+preferences/preferences.tsx:165
#: src/renderer/components/+preferences/preferences.tsx:163
msgid "Proxy is used only for non-cluster communication."
msgstr "Proxy is used only for non-cluster communication."
@ -1861,7 +1861,7 @@ msgstr "Release: {0}"
msgid "Releases"
msgstr "Releases"
#: src/renderer/components/+preferences/preferences.tsx:156
#: src/renderer/components/+preferences/preferences.tsx:154
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64
@ -1903,7 +1903,7 @@ msgstr "Remove selected items ({0})"
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
msgstr "Remove {resourceKind} <0>{resourceName}</0>?"
#: src/renderer/components/+preferences/preferences.tsx:119
#: src/renderer/components/+preferences/preferences.tsx:117
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
msgstr "Removing helm branch <0>{0}</0> has failed: {1}"
@ -1927,7 +1927,7 @@ msgstr "Replicas"
msgid "Repo/Name"
msgstr "Repo/Name"
#: src/renderer/components/+preferences/preferences.tsx:146
#: src/renderer/components/+preferences/preferences.tsx:144
msgid "Repositories"
msgstr "Repositories"
@ -2378,11 +2378,11 @@ msgstr "TLS"
msgid "Taints"
msgstr "Taints"
#: src/renderer/components/+preferences/preferences.tsx:176
#: src/renderer/components/+preferences/preferences.tsx:174
msgid "Telemetry & Usage Tracking"
msgstr "Telemetry & Usage Tracking"
#: src/renderer/components/+preferences/preferences.tsx:179
#: src/renderer/components/+preferences/preferences.tsx:177
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
msgstr "Telemetry & usage data is collected to continuously improve the Lens experience."
@ -2414,7 +2414,7 @@ msgstr "This field must contain only lowercase latin characters, numbers and das
msgid "This is the quick launch menu."
msgstr "This is the quick launch menu."
#: src/renderer/components/+preferences/preferences.tsx:171
#: src/renderer/components/+preferences/preferences.tsx:169
msgid "This will make Lens to trust ANY certificate authority without any validations."
msgstr "This will make Lens to trust ANY certificate authority without any validations."
@ -2457,7 +2457,7 @@ msgstr "Transmit"
msgid "Type"
msgstr "Type"
#: src/renderer/components/+preferences/preferences.tsx:163
#: src/renderer/components/+preferences/preferences.tsx:161
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
msgstr "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
@ -2650,7 +2650,7 @@ msgstr "ago"
msgid "and <0>{tailCount}</0> more"
msgstr "and <0>{tailCount}</0> more"
#: src/renderer/components/+preferences/preferences.tsx:131
#: src/renderer/components/+preferences/preferences.tsx:129
msgid "applicable to all clusters"
msgstr "applicable to all clusters"

View File

@ -116,11 +116,11 @@ msgstr ""
#~ msgid "Added repos"
#~ msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:149
#: src/renderer/components/+preferences/preferences.tsx:147
msgid "Added repos:"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:108
#: src/renderer/components/+preferences/preferences.tsx:106
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
msgstr ""
@ -202,11 +202,11 @@ msgstr ""
msgid "Allow Privilege Escalation"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:177
#: src/renderer/components/+preferences/preferences.tsx:175
msgid "Allow telemetry & usage tracking"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:169
#: src/renderer/components/+preferences/preferences.tsx:167
msgid "Allow untrusted Certificate Authorities"
msgstr ""
@ -401,7 +401,7 @@ msgstr ""
msgid "Capacity"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:168
#: src/renderer/components/+preferences/preferences.tsx:166
msgid "Certificate Trust"
msgstr ""
@ -464,7 +464,7 @@ msgstr ""
msgid "Cluster Issuers"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:139
#: src/renderer/components/+preferences/preferences.tsx:137
msgid "Color Theme"
msgstr ""
@ -713,7 +713,7 @@ msgstr ""
msgid "DaemonSets"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:40
#: src/renderer/theme.store.ts:32
msgid "Dark"
msgstr ""
@ -776,7 +776,7 @@ msgstr ""
msgid "Disk:"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:173
#: src/renderer/components/+preferences/preferences.tsx:171
msgid "Does not affect cluster communications!"
msgstr ""
@ -784,7 +784,7 @@ msgstr ""
msgid "Domains"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:142
#: src/renderer/components/+preferences/preferences.tsx:140
msgid "Download Mirror"
msgstr ""
@ -792,7 +792,7 @@ msgstr ""
msgid "Download file"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:143
#: src/renderer/components/+preferences/preferences.tsx:141
msgid "Download mirror for kubectl"
msgstr ""
@ -958,7 +958,7 @@ msgstr ""
msgid "HPA"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:162
#: src/renderer/components/+preferences/preferences.tsx:160
msgid "HTTP Proxy"
msgstr ""
@ -966,7 +966,7 @@ msgstr ""
msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:145
#: src/renderer/components/+preferences/preferences.tsx:143
msgid "Helm"
msgstr ""
@ -986,7 +986,7 @@ msgstr ""
msgid "Helm Upgrade: {0}"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:61
#: src/renderer/components/+preferences/preferences.tsx:50
msgid "Helm branch <0>{0}</0> already in use"
msgstr ""
@ -1200,7 +1200,7 @@ msgstr ""
msgid "Last transition time: {lastTransitionTime}"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:131
#: src/renderer/components/+preferences/preferences.tsx:129
msgid "Lens Global Settings"
msgstr ""
@ -1208,7 +1208,7 @@ msgstr ""
msgid "Level"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:41
#: src/renderer/theme.store.ts:33
msgid "Light"
msgstr ""
@ -1476,7 +1476,7 @@ msgstr ""
msgid "Namespaces: {0}"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:172
#: src/renderer/components/+preferences/preferences.tsx:170
msgid "Needed with some corporate proxies that do certificate re-writing."
msgstr ""
@ -1738,7 +1738,7 @@ msgstr ""
msgid "Ports"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:126
#: src/renderer/components/+preferences/preferences.tsx:124
msgid "Preferences"
msgstr ""
@ -1760,7 +1760,7 @@ msgstr ""
msgid "Provisioner"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:165
#: src/renderer/components/+preferences/preferences.tsx:163
msgid "Proxy is used only for non-cluster communication."
msgstr ""
@ -1844,7 +1844,7 @@ msgstr ""
msgid "Releases"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:156
#: src/renderer/components/+preferences/preferences.tsx:154
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64
@ -1886,7 +1886,7 @@ msgstr ""
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:119
#: src/renderer/components/+preferences/preferences.tsx:117
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
msgstr ""
@ -1910,7 +1910,7 @@ msgstr ""
msgid "Repo/Name"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:146
#: src/renderer/components/+preferences/preferences.tsx:144
msgid "Repositories"
msgstr ""
@ -2361,11 +2361,11 @@ msgstr ""
msgid "Taints"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:176
#: src/renderer/components/+preferences/preferences.tsx:174
msgid "Telemetry & Usage Tracking"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:179
#: src/renderer/components/+preferences/preferences.tsx:177
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
msgstr ""
@ -2397,7 +2397,7 @@ msgstr ""
msgid "This is the quick launch menu."
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:171
#: src/renderer/components/+preferences/preferences.tsx:169
msgid "This will make Lens to trust ANY certificate authority without any validations."
msgstr ""
@ -2440,7 +2440,7 @@ msgstr ""
msgid "Type"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:163
#: src/renderer/components/+preferences/preferences.tsx:161
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
msgstr ""
@ -2633,7 +2633,7 @@ msgstr ""
msgid "and <0>{tailCount}</0> more"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:131
#: src/renderer/components/+preferences/preferences.tsx:129
msgid "applicable to all clusters"
msgstr ""

View File

@ -117,11 +117,11 @@ msgstr "Добавить поле"
#~ msgid "Added repos"
#~ msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:149
#: src/renderer/components/+preferences/preferences.tsx:147
msgid "Added repos:"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:108
#: src/renderer/components/+preferences/preferences.tsx:106
msgid "Adding helm branch <0>{0}</0> has failed: {1}"
msgstr ""
@ -203,11 +203,11 @@ msgstr ""
msgid "Allow Privilege Escalation"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:177
#: src/renderer/components/+preferences/preferences.tsx:175
msgid "Allow telemetry & usage tracking"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:169
#: src/renderer/components/+preferences/preferences.tsx:167
msgid "Allow untrusted Certificate Authorities"
msgstr ""
@ -402,7 +402,7 @@ msgstr "Отмена"
msgid "Capacity"
msgstr "Емкость"
#: src/renderer/components/+preferences/preferences.tsx:168
#: src/renderer/components/+preferences/preferences.tsx:166
msgid "Certificate Trust"
msgstr ""
@ -469,7 +469,7 @@ msgstr "IP-адрес кластера"
msgid "Cluster Issuers"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:139
#: src/renderer/components/+preferences/preferences.tsx:137
msgid "Color Theme"
msgstr ""
@ -718,7 +718,7 @@ msgstr ""
msgid "DaemonSets"
msgstr "DaemonSets"
#: src/renderer/components/+preferences/preferences.tsx:40
#: src/renderer/theme.store.ts:32
msgid "Dark"
msgstr ""
@ -781,7 +781,7 @@ msgstr "Диск"
msgid "Disk:"
msgstr "Диск:"
#: src/renderer/components/+preferences/preferences.tsx:173
#: src/renderer/components/+preferences/preferences.tsx:171
msgid "Does not affect cluster communications!"
msgstr ""
@ -789,7 +789,7 @@ msgstr ""
msgid "Domains"
msgstr "Домены"
#: src/renderer/components/+preferences/preferences.tsx:142
#: src/renderer/components/+preferences/preferences.tsx:140
msgid "Download Mirror"
msgstr ""
@ -797,7 +797,7 @@ msgstr ""
msgid "Download file"
msgstr "Скачать файл"
#: src/renderer/components/+preferences/preferences.tsx:143
#: src/renderer/components/+preferences/preferences.tsx:141
msgid "Download mirror for kubectl"
msgstr ""
@ -968,7 +968,7 @@ msgstr "Группы"
msgid "HPA"
msgstr "HPA"
#: src/renderer/components/+preferences/preferences.tsx:162
#: src/renderer/components/+preferences/preferences.tsx:160
msgid "HTTP Proxy"
msgstr ""
@ -976,7 +976,7 @@ msgstr ""
msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:145
#: src/renderer/components/+preferences/preferences.tsx:143
msgid "Helm"
msgstr ""
@ -996,7 +996,7 @@ msgstr "Helm установка: {repo}/{name}"
msgid "Helm Upgrade: {0}"
msgstr "Helm обновление: {0}"
#: src/renderer/components/+preferences/preferences.tsx:61
#: src/renderer/components/+preferences/preferences.tsx:50
msgid "Helm branch <0>{0}</0> already in use"
msgstr ""
@ -1210,7 +1210,7 @@ msgstr "Увиденно в последний раз"
msgid "Last transition time: {lastTransitionTime}"
msgstr "Последнее изменение: {lastTransitionTime}"
#: src/renderer/components/+preferences/preferences.tsx:131
#: src/renderer/components/+preferences/preferences.tsx:129
msgid "Lens Global Settings"
msgstr ""
@ -1218,7 +1218,7 @@ msgstr ""
msgid "Level"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:41
#: src/renderer/theme.store.ts:33
msgid "Light"
msgstr ""
@ -1486,7 +1486,7 @@ msgstr "Namespaces"
msgid "Namespaces: {0}"
msgstr "Namespaces: {0}"
#: src/renderer/components/+preferences/preferences.tsx:172
#: src/renderer/components/+preferences/preferences.tsx:170
msgid "Needed with some corporate proxies that do certificate re-writing."
msgstr ""
@ -1756,7 +1756,7 @@ msgstr ""
msgid "Ports"
msgstr "Порты"
#: src/renderer/components/+preferences/preferences.tsx:126
#: src/renderer/components/+preferences/preferences.tsx:124
msgid "Preferences"
msgstr ""
@ -1778,7 +1778,7 @@ msgstr ""
msgid "Provisioner"
msgstr "Комиссия"
#: src/renderer/components/+preferences/preferences.tsx:165
#: src/renderer/components/+preferences/preferences.tsx:163
msgid "Proxy is used only for non-cluster communication."
msgstr ""
@ -1862,7 +1862,7 @@ msgstr "Установка: {0}"
msgid "Releases"
msgstr "Релизы"
#: src/renderer/components/+preferences/preferences.tsx:156
#: src/renderer/components/+preferences/preferences.tsx:154
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64
@ -1904,7 +1904,7 @@ msgstr "Удалить выбранные элементы ({0})"
msgid "Remove {resourceKind} <0>{resourceName}</0>?"
msgstr "Удалить {resourceKind} <0>{resourceName}</0>?"
#: src/renderer/components/+preferences/preferences.tsx:119
#: src/renderer/components/+preferences/preferences.tsx:117
msgid "Removing helm branch <0>{0}</0> has failed: {1}"
msgstr ""
@ -1928,7 +1928,7 @@ msgstr "Реплики"
msgid "Repo/Name"
msgstr "Репозиторий/Имя"
#: src/renderer/components/+preferences/preferences.tsx:146
#: src/renderer/components/+preferences/preferences.tsx:144
msgid "Repositories"
msgstr ""
@ -2379,11 +2379,11 @@ msgstr "TLS"
msgid "Taints"
msgstr "Метки блокировки"
#: src/renderer/components/+preferences/preferences.tsx:176
#: src/renderer/components/+preferences/preferences.tsx:174
msgid "Telemetry & Usage Tracking"
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:179
#: src/renderer/components/+preferences/preferences.tsx:177
msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
msgstr ""
@ -2415,7 +2415,7 @@ msgstr "Это поле может содержать только латинс
msgid "This is the quick launch menu."
msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:171
#: src/renderer/components/+preferences/preferences.tsx:169
msgid "This will make Lens to trust ANY certificate authority without any validations."
msgstr ""
@ -2458,7 +2458,7 @@ msgstr "Транзит"
msgid "Type"
msgstr "Тип"
#: src/renderer/components/+preferences/preferences.tsx:163
#: src/renderer/components/+preferences/preferences.tsx:161
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
msgstr ""
@ -2651,7 +2651,7 @@ msgstr "тому назад"
msgid "and <0>{tailCount}</0> more"
msgstr "и <0>{tailCount}</0> ещё"
#: src/renderer/components/+preferences/preferences.tsx:131
#: src/renderer/components/+preferences/preferences.tsx:129
msgid "applicable to all clusters"
msgstr ""

View File

@ -1,3 +1,4 @@
import type { ThemeId } from "../renderer/theme.store";
import semver from "semver"
import { action, observable, reaction, toJS } from "mobx";
import { BaseStore } from "./base-store";
@ -5,20 +6,8 @@ import migrations from "../migrations/user-store"
import { getAppVersion } from "./utils/app-version";
import { tracker } from "./tracker";
// todo: merge with config.store.ts + theme.store.ts
// fixme: detect new contexts from .kube/config since last open
export enum ThemeType {
LIGHT = "light",
DARK = "dark",
}
export interface Theme {
name: string;
type: ThemeType;
colors?: Record<string, string>;
}
export interface UserStoreModel {
lastSeenAppVersion: string;
seenContexts: string[];
@ -27,13 +16,15 @@ export interface UserStoreModel {
export interface UserPreferences {
httpsProxy?: string;
colorTheme?: string | "dark" | "light";
colorTheme?: string;
allowUntrustedCAs?: boolean;
allowTelemetry?: boolean;
downloadMirror?: string | "default";
}
export class UserStore extends BaseStore<UserStoreModel> {
static readonly defaultTheme: ThemeId = "kontena-dark"
private constructor() {
super({
// configName: "lens-user-store", // todo: migrate from default filename
@ -53,7 +44,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
@observable preferences: UserPreferences = {
allowTelemetry: true,
allowUntrustedCAs: false,
colorTheme: "dark",
colorTheme: UserStore.defaultTheme,
downloadMirror: "default",
httpsProxy: "",
};
@ -62,6 +53,11 @@ export class UserStore extends BaseStore<UserStoreModel> {
return semver.gt(getAppVersion(), this.lastSeenAppVersion);
}
@action
resetTheme() {
this.preferences.colorTheme = UserStore.defaultTheme;
}
@action
saveLastSeenAppVersion() {
tracker.event("app", "whats-new-seen")

View File

@ -2,14 +2,12 @@ import { app } from "electron"
import { CoreV1Api } from "@kubernetes/client-node"
import { LensApiRequest } from "../router"
import { LensApi } from "../lens-api"
import { userStore } from "../../common/user-store"
import { Cluster } from "../cluster"
export interface IConfigRoutePayload {
kubeVersion?: string;
clusterName?: string;
lensVersion?: string;
lensTheme?: string;
username?: string;
token?: string;
allowedNamespaces?: string[];
@ -58,12 +56,11 @@ async function getAllowedNamespaces(cluster: Cluster) {
return namespaceList.body.items
.filter((ns, i) => nsAccessStatuses[i])
.map(ns => ns.metadata.name)
} catch(error) {
} catch (error) {
const ctx = cluster.getProxyKubeconfig().getContextObject(cluster.contextName)
if (ctx.namespace) {
return [ctx.namespace]
}
else {
} else {
return []
}
}
@ -94,7 +91,6 @@ class ConfigRoute extends LensApi {
const data: IConfigRoutePayload = {
clusterName: cluster.contextName,
lensVersion: app.getVersion(),
lensTheme: userStore.preferences.colorTheme,
kubeVersion: cluster.version,
chartsEnabled: true,
isClusterAdmin: cluster.isAdmin,

View File

@ -14,6 +14,7 @@ import { Checkbox } from "../checkbox";
import { Notifications } from "../notifications";
import { Badge } from "../badge";
import { Spinner } from "../spinner";
import { themeStore } from "../../theme.store";
@observer
export class Preferences extends React.Component {
@ -22,20 +23,22 @@ export class Preferences extends React.Component {
@observable helmRepos: HelmRepo[] = [];
@observable helmAddedRepos = observable.map<string, HelmRepo>();
@observable themeOptions: SelectOption<string>[] = [
{ value: "kontena-dark", label: <Trans>Dark</Trans> },
{ value: "kontena-light", label: <Trans>Light</Trans> },
]
@observable downloadMirrorOptions: SelectOption<string>[] = [
{ value: "default", label: "Default (Google)" },
{ value: "china", label: "China (Azure)" },
]
@computed get themeOptions(): SelectOption<string>[] {
return themeStore.themes.map(theme => ({
label: theme.name,
value: theme.id,
}))
}
@computed get helmOptions(): SelectOption<HelmRepo>[] {
return this.helmRepos.map(repo => ({
value: repo,
label: repo.name,
value: repo,
}))
}
@ -80,7 +83,6 @@ export class Preferences extends React.Component {
}
onThemeChange = ({ value }: SelectOption<string>) => {
// themeStore.setTheme(value); // fixme: apply theme on the fly for current view
userStore.preferences.colorTheme = value;
}
@ -129,7 +131,7 @@ export class Preferences extends React.Component {
<Select
options={this.themeOptions}
value={preferences.colorTheme}
onChange={this.onThemeChange}
onChange={({ value }: SelectOption) => preferences.colorTheme = value}
/>
<h2><Trans>Download Mirror</Trans></h2>
@ -158,7 +160,7 @@ export class Preferences extends React.Component {
{this.helmLoading && <Spinner/>}
{Array.from(this.helmAddedRepos).map(([name, repo]) => {
return (
<Badge key={name} className="added-repo flex gaps align-center">
<Badge key={name} className="added-repo flex gaps align-center" title={repo.url}>
<span className="repo">{name}</span>
<Icon
material="remove_circle_outline"

View File

@ -1,5 +1,6 @@
import React, { useContext } from "react";
import { t } from "@lingui/macro";
import { observer } from "mobx-react";
import { IPodMetrics } from "../../api/endpoints";
import { BarChart, cpuOptions, memoryOptions } from "../chart";
import { isMetricsEmpty, normalizeMetrics } from "../../api/endpoints/metrics.api";
@ -10,7 +11,7 @@ import { themeStore } from "../../theme.store";
type IContext = IResourceMetricsValue<any, { metrics: IPodMetrics }>;
export const ContainerCharts = () => {
export const ContainerCharts = observer(() => {
const { params: { metrics }, tabId } = useContext<IContext>(ResourceMetricsContext);
const { chartCapacityColor } = themeStore.activeTheme.colors;
@ -100,4 +101,4 @@ export const ContainerCharts = () => {
data={{ datasets: datasets[tabId] }}
/>
);
}
})

View File

@ -1,7 +1,8 @@
import React, { useEffect, useRef } from "react";
import React from "react";
import merge from "lodash/merge";
import moment from "moment";
import Color from "color";
import { observer } from "mobx-react";
import { ChartData, ChartOptions, ChartPoint, Scriptable } from "chart.js";
import { Chart, ChartKind, ChartProps } from "./chart";
import { bytesToUnits, cssNames } from "../../utils";
@ -19,139 +20,136 @@ const defaultProps: Partial<Props> = {
plugins: [ZebraStripes]
};
BarChart.defaultProps = defaultProps;
@observer
export class BarChart extends React.Component<Props> {
static defaultProps = defaultProps as object;
export function BarChart(props: Props) {
const { name, data, className, timeLabelStep, plugins, options: customOptions, ...settings } = props;
const { textColorPrimary, borderFaintColor, chartStripesColor } = themeStore.activeTheme.colors;
render() {
const { name, data, className, timeLabelStep, plugins, options: customOptions, ...settings } = this.props;
const { textColorPrimary, borderFaintColor, chartStripesColor } = themeStore.activeTheme.colors;
const savedName = useRef<string>();
const getBarColor: Scriptable<string> = ({ dataset }) => {
const color = dataset.borderColor;
return Color(color).alpha(0.2).string();
}
useEffect(() => {
savedName.current = props.name;
});
const getBarColor: Scriptable<string> = ({ dataset }) => {
const color = dataset.borderColor;
return Color(color).alpha(0.2).string();
}
// Remove empty sets and insert default data
const chartData: ChartData = {
...data,
datasets: data.datasets
.filter(set => set.data.length)
.map(item => {
return {
type: ChartKind.BAR,
borderWidth: { top: 3 },
barPercentage: 1,
categoryPercentage: 1,
...item
}
})
};
const formatTimeLabels = (timestamp: string, index: number) => {
const label = moment(parseInt(timestamp)).format("HH:mm");
const offset = " ";
if (index == 0) return offset + label;
if (index == 60) return label + offset;
return index % timeLabelStep == 0 ? label : "";
};
const barOptions: ChartOptions = {
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: [{
type: "time",
offset: true,
gridLines: {
display: false,
},
stacked: true,
ticks: {
callback: formatTimeLabels,
autoSkip: false,
source: "data",
backdropColor: "white",
fontColor: textColorPrimary,
fontSize: 11,
maxRotation: 0,
minRotation: 0
},
bounds: "data",
time: {
unit: "minute",
displayFormats: {
minute: "x"
},
parser: timestamp => moment.unix(parseInt(timestamp))
}
}],
yAxes: [{
position: "right",
gridLines: {
color: borderFaintColor,
drawBorder: false,
tickMarkLength: 0,
zeroLineWidth: 0
},
ticks: {
maxTicksLimit: 6,
fontColor: textColorPrimary,
fontSize: 11,
padding: 8,
min: 0
}
}]
},
tooltips: {
mode: "index",
position: "cursor",
callbacks: {
title: tooltipItems => {
const now = new Date().getTime()
if (new Date(tooltipItems[0].xLabel).getTime() > now) return "";
return `${tooltipItems[0].xLabel}`
},
labelColor: ({ datasetIndex }) => {
// Remove empty sets and insert default data
const chartData: ChartData = {
...data,
datasets: data.datasets
.filter(set => set.data.length)
.map(item => {
return {
borderColor: "darkgray",
backgroundColor: chartData.datasets[datasetIndex].borderColor as string
type: ChartKind.BAR,
borderWidth: { top: 3 },
barPercentage: 1,
categoryPercentage: 1,
...item
}
})
};
const formatTimeLabels = (timestamp: string, index: number) => {
const label = moment(parseInt(timestamp)).format("HH:mm");
const offset = " ";
if (index == 0) return offset + label;
if (index == 60) return label + offset;
return index % timeLabelStep == 0 ? label : "";
};
const barOptions: ChartOptions = {
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: [{
type: "time",
offset: true,
gridLines: {
display: false,
},
stacked: true,
ticks: {
callback: formatTimeLabels,
autoSkip: false,
source: "data",
backdropColor: "white",
fontColor: textColorPrimary,
fontSize: 11,
maxRotation: 0,
minRotation: 0
},
bounds: "data",
time: {
unit: "minute",
displayFormats: {
minute: "x"
},
parser: timestamp => moment.unix(parseInt(timestamp))
}
}],
yAxes: [{
position: "right",
gridLines: {
color: borderFaintColor,
drawBorder: false,
tickMarkLength: 0,
zeroLineWidth: 0
},
ticks: {
maxTicksLimit: 6,
fontColor: textColorPrimary,
fontSize: 11,
padding: 8,
min: 0
}
}]
},
tooltips: {
mode: "index",
position: "cursor",
callbacks: {
title: tooltipItems => {
const now = new Date().getTime()
if (new Date(tooltipItems[0].xLabel).getTime() > now) return "";
return `${tooltipItems[0].xLabel}`
},
labelColor: ({ datasetIndex }) => {
return {
borderColor: "darkgray",
backgroundColor: chartData.datasets[datasetIndex].borderColor as string
}
}
}
},
animation: {
duration: 0
},
elements: {
rectangle: {
backgroundColor: getBarColor.bind(null)
}
},
plugins: {
ZebraStripes: {
stripeColor: chartStripesColor
}
}
},
animation: {
duration: 0
},
elements: {
rectangle: {
backgroundColor: getBarColor.bind(null)
}
},
plugins: {
ZebraStripes: {
stripeColor: chartStripesColor
}
};
const options = merge(barOptions, customOptions);
if (chartData.datasets.length == 0) {
return <NoMetrics/>
}
};
const options = merge(barOptions, customOptions);
if (chartData.datasets.length == 0) {
return <NoMetrics/>
return (
<Chart
className={cssNames("BarChart flex box grow column", className)}
type={ChartKind.BAR}
data={chartData}
options={options}
plugins={plugins}
{...settings}
/>
)
}
return (
<Chart
className={cssNames("BarChart flex box grow column", className)}
type={ChartKind.BAR}
data={chartData}
options={options}
plugins={plugins}
{...settings}
/>
)
}
// Default options for all charts containing memory units (network, disk, memory, etc)

View File

@ -1,5 +1,6 @@
import "./pie-chart.scss";
import React from "react";
import { observer } from "mobx-react";
import ChartJS, { ChartOptions } from "chart.js";
import { Chart, ChartProps } from "./chart";
import { cssNames } from "../../utils";
@ -8,6 +9,7 @@ import { themeStore } from "../../theme.store";
interface Props extends ChartProps {
}
@observer
export class PieChart extends React.Component<Props> {
render() {
const { data, className, options, ...chartProps } = this.props

View File

@ -6,6 +6,7 @@ import { BottomBar } from "./bottom-bar";
import { cssNames, IClassName } from "../../utils";
import { Terminal } from "../dock/terminal";
import { i18nStore } from "../../i18n";
import { themeStore } from "../../theme.store";
interface Props {
className?: IClassName;
@ -14,8 +15,11 @@ interface Props {
export class ClusterManager extends React.Component<Props> {
static async init() {
await i18nStore.init()
await Terminal.preloadFonts()
await Promise.all([
i18nStore.init(),
themeStore.init(),
Terminal.preloadFonts(),
])
}
render() {

View File

@ -1,5 +1,5 @@
import debounce from "lodash/debounce";
import { autorun } from "mobx";
import { reaction, toJS } from "mobx";
import { Terminal as XTerm } from "xterm";
import { FitAddon } from "xterm-addon-fit";
import { dockStore, TabId } from "./dock.store";
@ -20,7 +20,7 @@ export class Terminal {
Terminal.spawningPool = pool;
}
static async preloadFonts(){
static async preloadFonts() {
const fontPath = require("../fonts/roboto-mono-nerd.ttf").default; // eslint-disable-line @typescript-eslint/no-var-requires
const fontFace = new FontFace("RobotoMono", `url(${fontPath})`);
await fontFace.load();
@ -33,7 +33,7 @@ export class Terminal {
public disposers: Function[] = [];
@autobind()
protected setTheme(colors = themeStore.activeTheme.colors) {
protected setTheme(colors: Record<string, string>) {
// Replacing keys stored in styles to format accepted by terminal
// E.g. terminalBrightBlack -> brightBlack
const colorPrefix = "terminal"
@ -94,19 +94,18 @@ export class Terminal {
this.xterm.attachCustomKeyEventHandler(this.keyHandler);
// bind events
const onResizeDisposer = dockStore.onResize(this.onResize);
const onData = this.xterm.onData(this.onData);
const onThemeChangeDisposer = autorun(() => this.setTheme(themeStore.activeTheme.colors));
const onDataHandler = this.xterm.onData(this.onData);
this.viewport.addEventListener("scroll", this.onScroll);
this.api.onReady.addListener(this.onClear, { once: true }); // clear status logs (connecting..)
this.api.onData.addListener(this.onApiData);
window.addEventListener("resize", this.onResize);
// add clean-up handlers to be called on destroy
this.disposers.push(
onResizeDisposer,
onThemeChangeDisposer,
() => onData.dispose(),
reaction(() => toJS(themeStore.activeTheme.colors), this.setTheme, {
fireImmediately: true
}),
dockStore.onResize(this.onResize),
() => onDataHandler.dispose(),
() => this.fitAddon.dispose(),
() => this.api.removeAllListeners(),
() => window.removeEventListener("resize", this.onResize),
@ -171,7 +170,7 @@ export class Terminal {
// Handle custom hotkey bindings
if (ctrlKey) {
switch (code) {
// Ctrl+C: prevent terminal exit on windows / linux (?)
// Ctrl+C: prevent terminal exit on windows / linux (?)
case "KeyC":
if (this.xterm.hasSelection()) return false;
break;

View File

@ -8,7 +8,7 @@
grid-template-columns: 1fr 40%;
> * {
@include hidden-scrollbar;
@include custom-scrollbar;
--flex-gap: #{$spacing};
padding: $spacing;
}

View File

@ -1,91 +1,98 @@
import { action, autorun, computed, observable, reaction } from "mobx";
import { autobind, createStorage } from "./utils";
import { Notifications } from "./components/notifications";
import { Theme, ThemeType } from "../common/user-store";
import { computed, observable, reaction } from "mobx";
import { autobind } from "./utils";
import { userStore } from "../common/user-store";
import logger from "../main/logger";
export type ThemeId = string;
export enum ThemeType {
DARK = "dark",
LIGHT = "light",
}
export interface Theme {
id: ThemeId; // filename without .json-extension
type: ThemeType;
name?: string;
colors?: Record<string, string>;
description?: string;
author?: string;
}
@autobind()
export class ThemeStore {
protected style = document.createElement("style");
protected styles: HTMLStyleElement;
readonly defaultTheme: Theme = {
name: "kontena-dark",
type: ThemeType.DARK,
colors: {},
};
// bundled themes from `themes/${themeId}.json`
@observable themes: Theme[] = [
{ id: "kontena-dark", type: ThemeType.DARK },
{ id: "kontena-light", type: ThemeType.LIGHT },
];
@observable activeThemeId = this.defaultTheme.name; // theme's filename without extension
@observable themes = observable.map<string, Theme>([], { deep: false });
@computed get activeThemeId() {
return userStore.preferences.colorTheme;
}
@computed get activeTheme() {
return this.themes.get(this.activeThemeId) || this.defaultTheme;
@computed get activeTheme(): Theme {
const activeTheme = this.themes.find(theme => theme.id === this.activeThemeId) || this.themes[0];
return {
colors: {},
...activeTheme,
}
}
constructor() {
const storage = createStorage("theme", this.activeThemeId);
this.activeThemeId = storage.get();
// init
this.style.id = "lens-theme"
document.head.prepend(this.style);
this.setTheme(this.activeThemeId);
// save active theme-id in local storage
reaction(() => this.activeThemeId, themeId => storage.set(themeId), {
fireImmediately: true
});
// auto-apply colors to dom from active theme
reaction(() => this.activeTheme, this.onChange, {
// auto-apply active theme
reaction(() => this.activeThemeId, async themeId => {
try {
await this.loadTheme(themeId);
this.applyTheme();
} catch (err) {
userStore.resetTheme();
}
}, {
fireImmediately: true,
delay: 150,
});
// apply theme from configuration
import("./config.store").then(({ configStore }) => {
autorun(() => {
const themeId = configStore.config.lensTheme;
if (themeId && themeId !== this.activeThemeId) {
this.setTheme(themeId);
}
});
})
}
protected onChange = (theme: Theme) => {
let cssText = "\n"
Object.entries(theme.colors).forEach(([propName, color]) => {
cssText += `--${propName}: ${color} !important;\n`
});
this.style.textContent = `:root {${cssText}} `;
async init() {
// preload all themes
await Promise.all(
this.themes.map(theme => this.loadTheme(theme.id))
);
}
async load(themeId: string, { showErrorNotification = true } = {}): Promise<Theme> {
if (this.themes.has(themeId)) {
return this.themes.get(themeId);
}
getThemeById(themeId: ThemeId): Theme {
return this.themes.find(theme => theme.id === themeId)
}
protected async loadTheme(themeId: ThemeId): Promise<Theme> {
try {
const theme: Theme = require( // eslint-disable-line @typescript-eslint/no-var-requires
/* webpackMode: "lazy", webpackChunkName: "theme/[request]" */
// todo: figure out why await import() doesn't work
const theme = require( // eslint-disable-line @typescript-eslint/no-var-requires
/* webpackChunkName: "themes/[name]" */
`./themes/${themeId}.json`
);
this.themes.set(themeId, theme);
return theme;
const existingTheme = this.getThemeById(themeId);
if (existingTheme) {
Object.assign(existingTheme, theme); // merge
}
return existingTheme;
} catch (err) {
if (showErrorNotification) Notifications.error(err.toString());
throw err;
logger.error(`Can't load theme "${themeId}": ${err}`);
}
}
@action
async setTheme(themeId = this.defaultTheme.name) {
try {
await this.load(themeId);
this.activeThemeId = themeId;
} catch (err) {
if (themeId !== this.defaultTheme.name) {
this.setTheme(); // fallback to default theme
}
protected applyTheme(theme = this.activeTheme) {
if (!this.styles) {
this.styles = document.createElement("style");
this.styles.id = "lens-theme"
document.head.prepend(this.styles);
}
const cssVars = Object.entries(theme.colors).map(([cssName, color]) => {
return `--${cssName}: ${color} !important;`
});
this.styles.textContent = `:root {\n${cssVars.join("\n")}}`;
}
}

View File

@ -1,6 +1,7 @@
{
"name": "Lens Dark Theme",
"name": "Dark (Lens)",
"type": "dark",
"description": "Original Lens dark theme",
"author": "Lakend Labs",
"colors": {
"blue": "#3d90ce",

View File

@ -1,6 +1,7 @@
{
"name": "Lens Light Theme",
"name": "Light (Lens)",
"type": "light",
"description": "Original Lens light theme",
"author": "Lakend Labs",
"colors": {
"blue": "#3d90ce",