Code improvements.
This commit is contained in:
120
extension/src/utils/VsCodeSettings.ts
Normal file
120
extension/src/utils/VsCodeSettings.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { Uri, workspace, ConfigurationTarget, Disposable } from "vscode";
|
||||
import { fromResource } from "mobx-utils";
|
||||
import { computed, runInAction } from "mobx";
|
||||
import { EventEmitter } from "@hediet/std/events";
|
||||
|
||||
export interface Serializer<T> {
|
||||
deserialize: (val: any) => T;
|
||||
serializer: (val: T) => any;
|
||||
}
|
||||
|
||||
export function serializerWithDefault<T>(defaultValue: T): Serializer<T> {
|
||||
return {
|
||||
deserialize: val => (val === undefined ? defaultValue : val),
|
||||
serializer: val => val,
|
||||
};
|
||||
}
|
||||
|
||||
export class VsCodeSetting<T> {
|
||||
public get T(): T {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
public readonly serializer: Serializer<T>;
|
||||
public readonly scope: Uri | undefined;
|
||||
private readonly settingResource: VsCodeSettingResource;
|
||||
|
||||
public constructor(
|
||||
public readonly id: string,
|
||||
options: {
|
||||
serializer?: Serializer<T>;
|
||||
scope?: Uri;
|
||||
} = {}
|
||||
) {
|
||||
this.scope = options.scope;
|
||||
this.serializer = options.serializer || {
|
||||
deserialize: val => val,
|
||||
serializer: val => val,
|
||||
};
|
||||
this.settingResource = new VsCodeSettingResource(this.id, this.scope);
|
||||
}
|
||||
|
||||
public get(): T {
|
||||
const result = this.settingResource.value;
|
||||
return this.serializer.deserialize(result);
|
||||
}
|
||||
|
||||
public async set(value: T): Promise<void> {
|
||||
const value2 = this.serializer.serializer(value);
|
||||
const c = workspace.getConfiguration(undefined, this.scope);
|
||||
const result = c.inspect(this.id);
|
||||
let target: ConfigurationTarget;
|
||||
|
||||
if (
|
||||
result &&
|
||||
[result.workspaceFolderValue].some(i => i !== undefined)
|
||||
) {
|
||||
target = ConfigurationTarget.WorkspaceFolder;
|
||||
}
|
||||
if (result && [result.workspaceValue].some(i => i !== undefined)) {
|
||||
target = ConfigurationTarget.Workspace;
|
||||
} else {
|
||||
target = ConfigurationTarget.Global;
|
||||
}
|
||||
|
||||
await c.update(this.id, value2, target);
|
||||
}
|
||||
}
|
||||
|
||||
class VsCodeSettingResource {
|
||||
public static onConfigChange = new EventEmitter();
|
||||
|
||||
private subscription: Disposable | undefined;
|
||||
private readonly resource = fromResource<any>(
|
||||
update => {
|
||||
update(this.readValue());
|
||||
this.subscription = VsCodeSettingResource.onConfigChange.sub(() => {
|
||||
update(this.readValue());
|
||||
});
|
||||
},
|
||||
() => this.subscription!.dispose(),
|
||||
this.readValue()
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly id: string,
|
||||
private readonly scope: Uri | undefined
|
||||
) {}
|
||||
|
||||
private readValue(): any {
|
||||
const val = workspace
|
||||
.getConfiguration(undefined, this.scope)
|
||||
.get(this.id);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* This improves change detection.
|
||||
*/
|
||||
private readonly stringifiedSettingValue = computed(
|
||||
() => JSON.stringify(this.resource.current()),
|
||||
{
|
||||
name: `VsCodeSettingResource[${this.id}].value`,
|
||||
context: this,
|
||||
}
|
||||
);
|
||||
|
||||
public get value() {
|
||||
const v = this.stringifiedSettingValue.get();
|
||||
if (v === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(v);
|
||||
}
|
||||
}
|
||||
|
||||
workspace.onDidChangeConfiguration(() => {
|
||||
runInAction("Update Configuration", () => {
|
||||
VsCodeSettingResource.onConfigChange.emit();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user