mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
tracker / user-store refactoring, part 1
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
1 parent
c9fb015bcf
commit
4270ec4240
23 files changed
+247
-225
No files matched your search
@@ -1,32 +1,32 @@
|
||||
import ElectronStore from "electron-store"
|
||||
import { Singleton } from "./utils/singleton";
|
||||
import Config from "conf"
|
||||
import Singleton from "./utils/singleton";
|
||||
import migrations from "../migrations/cluster-store"
|
||||
import { Cluster, ClusterBaseInfo } from "../main/cluster";
|
||||
|
||||
export class ClusterStore extends Singleton {
|
||||
private store = new ElectronStore({
|
||||
name: "lens-cluster-store",
|
||||
private storeConfig = new Config({
|
||||
configName: "lens-cluster-store",
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
migrations: migrations,
|
||||
})
|
||||
|
||||
public getAllClusterObjects(): Cluster[] {
|
||||
return this.store.get("clusters", []).map((clusterInfo: ClusterBaseInfo) => {
|
||||
return this.storeConfig.get("clusters", []).map((clusterInfo: ClusterBaseInfo) => {
|
||||
return new Cluster(clusterInfo)
|
||||
})
|
||||
}
|
||||
|
||||
public getAllClusters(): ClusterBaseInfo[] {
|
||||
return this.store.get("clusters", [])
|
||||
return this.storeConfig.get("clusters", [])
|
||||
}
|
||||
|
||||
public removeCluster(id: string): void {
|
||||
this.store.delete(id);
|
||||
this.storeConfig.delete(id);
|
||||
const clusterBaseInfos = this.getAllClusters()
|
||||
const index = clusterBaseInfos.findIndex((cbi) => cbi.id === id)
|
||||
if (index !== -1) {
|
||||
clusterBaseInfos.splice(index, 1)
|
||||
this.store.set("clusters", clusterBaseInfos)
|
||||
this.storeConfig.set("clusters", clusterBaseInfos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export class ClusterStore extends Singleton {
|
||||
} else {
|
||||
clusters[index] = storable
|
||||
}
|
||||
this.store.set("clusters", clusters)
|
||||
this.storeConfig.set("clusters", clusters)
|
||||
}
|
||||
|
||||
public storeClusters(clusters: ClusterBaseInfo[]) {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import request from "request"
|
||||
import { userStore } from "./user-store"
|
||||
|
||||
export function globalRequestOpts(requestOpts: request.Options ) {
|
||||
const userPrefs = userStore.getPreferences()
|
||||
if (userPrefs.httpsProxy) {
|
||||
requestOpts.proxy = userPrefs.httpsProxy
|
||||
export function globalRequestOpts(requestOpts: request.Options) {
|
||||
const { httpsProxy, allowUntrustedCAs } = userStore.preferences
|
||||
if (httpsProxy) {
|
||||
requestOpts.proxy = httpsProxy
|
||||
}
|
||||
requestOpts.rejectUnauthorized = !userPrefs.allowUntrustedCAs;
|
||||
|
||||
requestOpts.rejectUnauthorized = !allowUntrustedCAs;
|
||||
return requestOpts
|
||||
}
|
||||
+24
-18
@@ -1,10 +1,12 @@
|
||||
import { app, App, remote } from "electron"
|
||||
import ua from "universal-analytics"
|
||||
import { machineIdSync } from "node-machine-id"
|
||||
import Singleton from "./utils/singleton";
|
||||
import { userStore } from "./user-store"
|
||||
|
||||
const GA_ID = "UA-159377374-1"
|
||||
export class Tracker extends Singleton {
|
||||
static readonly GA_ID = "UA-159377374-1"
|
||||
|
||||
export class Tracker {
|
||||
protected visitor: ua.Visitor
|
||||
protected machineId: string = null;
|
||||
protected ip: string = null;
|
||||
@@ -12,31 +14,35 @@ export class Tracker {
|
||||
protected locale: string;
|
||||
protected electronUA: string;
|
||||
|
||||
constructor(app: Electron.App) {
|
||||
private constructor(app: App) {
|
||||
super();
|
||||
try {
|
||||
this.visitor = ua(GA_ID, machineIdSync(), {strictCidFormat: false})
|
||||
this.visitor = ua(Tracker.GA_ID, machineIdSync(), { strictCidFormat: false })
|
||||
} catch (error) {
|
||||
this.visitor = ua(GA_ID)
|
||||
this.visitor = ua(Tracker.GA_ID)
|
||||
}
|
||||
this.visitor.set("dl", "https://lensapptelemetry.lakendlabs.com")
|
||||
}
|
||||
|
||||
public async event(eventCategory: string, eventAction: string) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (!this.telemetryAllowed()) {
|
||||
resolve()
|
||||
return
|
||||
protected async isTelemetryAllowed(): Promise<boolean> {
|
||||
return userStore.preferences.allowTelemetry;
|
||||
}
|
||||
|
||||
async event(eventCategory: string, eventAction: string, otherParams = {}) {
|
||||
try {
|
||||
const allowed = await this.isTelemetryAllowed();
|
||||
if (!allowed) {
|
||||
return;
|
||||
}
|
||||
this.visitor.event({
|
||||
ec: eventCategory,
|
||||
ea: eventAction
|
||||
ea: eventAction,
|
||||
...otherParams,
|
||||
}).send()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
protected telemetryAllowed() {
|
||||
const userPrefs = userStore.getPreferences()
|
||||
return !!userPrefs.allowTelemetry
|
||||
} catch (err) {
|
||||
console.error(`Failed to track "${eventCategory}:${eventAction}"`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const tracker: Tracker = Tracker.getInstance(app || remote.app);
|
||||
+78
-32
@@ -1,59 +1,105 @@
|
||||
import ElectronStore from "electron-store"
|
||||
import { app, remote } from "electron"
|
||||
import { computed, observable, reaction, toJS } from "mobx";
|
||||
import Config from "conf"
|
||||
import semver from "semver"
|
||||
import migrations from "../migrations/user-store"
|
||||
import { Singleton } from "./utils/singleton";
|
||||
import Singleton from "./utils/singleton";
|
||||
import { getAppVersion } from "./utils/app-version";
|
||||
import { tracker } from "./tracker";
|
||||
|
||||
export interface UserStoreModel {
|
||||
lastSeenAppVersion: string;
|
||||
seenContexts: string[];
|
||||
preferences: UserPreferences;
|
||||
}
|
||||
|
||||
export interface UserPreferences {
|
||||
httpsProxy?: string;
|
||||
colorTheme?: string;
|
||||
colorTheme?: string | "dark";
|
||||
allowUntrustedCAs?: boolean;
|
||||
allowTelemetry?: boolean;
|
||||
downloadMirror?: string;
|
||||
downloadMirror?: string | "default";
|
||||
}
|
||||
|
||||
export class UserStore extends Singleton {
|
||||
protected store = new ElectronStore({
|
||||
name: "lens-user-store",
|
||||
migrations: migrations,
|
||||
});
|
||||
private storeConfig: Config<UserStoreModel>;
|
||||
|
||||
public lastSeenAppVersion() {
|
||||
return this.store.get('lastSeenAppVersion', "0.0.0")
|
||||
@observable isReady = false;
|
||||
@observable lastSeenAppVersion = "0.0.0"
|
||||
@observable seenContexts = observable.set();
|
||||
|
||||
@observable preferences: UserPreferences = {
|
||||
allowTelemetry: true,
|
||||
colorTheme: "dark",
|
||||
downloadMirror: "default",
|
||||
};
|
||||
|
||||
@computed get hasNewAppVersion() {
|
||||
return semver.gt(getAppVersion(), this.lastSeenAppVersion);
|
||||
}
|
||||
|
||||
public setLastSeenAppVersion(version: string) {
|
||||
this.store.set('lastSeenAppVersion', version)
|
||||
private constructor() {
|
||||
super();
|
||||
this.init();
|
||||
}
|
||||
|
||||
public getSeenContexts(): Array<string> {
|
||||
return this.store.get("seenContexts", [])
|
||||
async init() {
|
||||
/*await*/ this.load();
|
||||
this.bindEvents();
|
||||
this.isReady = true;
|
||||
}
|
||||
|
||||
public storeSeenContext(newContexts: string[]) {
|
||||
const seenContexts = this.getSeenContexts().concat(newContexts)
|
||||
// store unique contexts by casting array to set first
|
||||
const newContextSet = new Set(seenContexts)
|
||||
const allContexts = [...newContextSet]
|
||||
this.store.set("seenContexts", allContexts)
|
||||
return allContexts
|
||||
saveLastSeenAppVersion() {
|
||||
this.lastSeenAppVersion = getAppVersion();
|
||||
}
|
||||
|
||||
public setPreferences(preferences: UserPreferences) {
|
||||
this.store.set('preferences', preferences)
|
||||
// todo: use "conf" as pseudo-async for more future-proof usages
|
||||
protected async load() {
|
||||
this.storeConfig = new Config<UserStoreModel>({
|
||||
configName: "lens-user-store",
|
||||
migrations: migrations,
|
||||
cwd: (app || remote.app).getPath("userData"),
|
||||
});
|
||||
this.fromStore(this.storeConfig.store);
|
||||
}
|
||||
|
||||
public getPreferences(): UserPreferences {
|
||||
const prefs = this.store.get("preferences", {})
|
||||
if (!prefs.colorTheme) {
|
||||
prefs.colorTheme = "dark"
|
||||
protected bindEvents() {
|
||||
// refresh from file-system updates
|
||||
this.storeConfig.onDidAnyChange((data, oldValue) => {
|
||||
this.fromStore(data);
|
||||
});
|
||||
|
||||
// refresh config file from runtime
|
||||
reaction(() => this.toJSON(), model => {
|
||||
this.storeConfig.store = model;
|
||||
});
|
||||
|
||||
// track telemetry availability
|
||||
reaction(() => this.preferences.allowTelemetry, allowed => {
|
||||
tracker.event("telemetry", allowed ? "enabled" : "disabled");
|
||||
});
|
||||
}
|
||||
|
||||
// todo: use "serializr" ?
|
||||
protected fromStore(data: Partial<UserStoreModel> = {}) {
|
||||
const { lastSeenAppVersion, seenContexts, preferences } = data
|
||||
if (lastSeenAppVersion) {
|
||||
this.lastSeenAppVersion = lastSeenAppVersion;
|
||||
}
|
||||
if (!prefs.downloadMirror) {
|
||||
prefs.downloadMirror = "default"
|
||||
if (seenContexts) {
|
||||
this.seenContexts = observable.set(seenContexts)
|
||||
}
|
||||
if (prefs.allowTelemetry === undefined) {
|
||||
prefs.allowTelemetry = true
|
||||
if (preferences) {
|
||||
Object.assign(this.preferences, preferences);
|
||||
}
|
||||
}
|
||||
|
||||
return prefs
|
||||
protected toJSON(): UserStoreModel {
|
||||
return toJS({
|
||||
lastSeenAppVersion: this.lastSeenAppVersion,
|
||||
seenContexts: Array.from(this.seenContexts),
|
||||
preferences: this.preferences,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
* const usersStore: UsersStore = UsersStore.getInstance();
|
||||
*/
|
||||
|
||||
export class Singleton {
|
||||
// todo: maybe convert to @decorator
|
||||
class Singleton {
|
||||
private static instances = new WeakMap<object, Singleton>();
|
||||
|
||||
// todo: figure out how to infer child class + arguments types
|
||||
@@ -21,3 +22,6 @@ export class Singleton {
|
||||
Singleton.instances.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
export { Singleton }
|
||||
export default Singleton;
|
||||
@@ -1,30 +1,26 @@
|
||||
import ElectronStore from "electron-store"
|
||||
import { Singleton } from "./utils/singleton";
|
||||
import Config from "conf"
|
||||
import Singleton from "./utils/singleton";
|
||||
import { clusterStore } from "./cluster-store"
|
||||
import { getAppVersion } from "./utils/app-version";
|
||||
|
||||
export type WorkspaceId = string;
|
||||
|
||||
export interface WorkspaceData {
|
||||
export interface WorkspaceStoreModel {
|
||||
workspaces: Workspace[]
|
||||
}
|
||||
|
||||
export interface Workspace {
|
||||
id: WorkspaceId;
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export class Workspace implements WorkspaceData {
|
||||
public id: string
|
||||
public name: string
|
||||
public description?: string
|
||||
|
||||
public constructor(data: WorkspaceData) {
|
||||
Object.assign(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceStore extends Singleton {
|
||||
static defaultId = "default"
|
||||
static readonly defaultId = "default"
|
||||
|
||||
private store = new ElectronStore({
|
||||
name: "lens-workspace-store"
|
||||
private storeConfig = new Config<WorkspaceStoreModel>({
|
||||
configName: "lens-workspace-store",
|
||||
projectVersion: getAppVersion(),
|
||||
});
|
||||
|
||||
private constructor() {
|
||||
@@ -46,11 +42,10 @@ export class WorkspaceStore extends Singleton {
|
||||
}
|
||||
|
||||
public getAllWorkspaces(): Workspace[] {
|
||||
const workspacesData: WorkspaceData[] = this.store.get("workspaces", [])
|
||||
return workspacesData.map((wsd) => new Workspace(wsd))
|
||||
return this.storeConfig.get("workspaces", [])
|
||||
}
|
||||
|
||||
public saveWorkspace(workspace: WorkspaceData) {
|
||||
public saveWorkspace(workspace: Workspace) {
|
||||
const workspaces = this.getAllWorkspaces()
|
||||
const index = workspaces.findIndex((w) => w.id === workspace.id)
|
||||
if (index !== -1) {
|
||||
@@ -58,7 +53,7 @@ export class WorkspaceStore extends Singleton {
|
||||
} else {
|
||||
workspaces.push(workspace)
|
||||
}
|
||||
this.store.set("workspaces", workspaces)
|
||||
this.storeConfig.set("workspaces", workspaces)
|
||||
}
|
||||
|
||||
public removeWorkspace(workspace: Workspace) {
|
||||
@@ -70,7 +65,7 @@ export class WorkspaceStore extends Singleton {
|
||||
if (index !== -1) {
|
||||
clusterStore.removeClustersByWorkspace(workspace.id)
|
||||
workspaces.splice(index, 1)
|
||||
this.store.set("workspaces", workspaces)
|
||||
this.storeConfig.set("workspaces", workspaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user