Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/common/enablement.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Disposable } from '../../../../base/common/lifecycle.js';
7
import { IReader, ITransaction } from '../../../../base/common/observable.js';
8
import { ObservableMemento, observableMemento } from '../../../../platform/observable/common/observableMemento.js';
9
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
10
11
export const enum ContributionEnablementState {
12
DisabledProfile,
13
DisabledWorkspace,
14
EnabledProfile,
15
EnabledWorkspace,
16
}
17
18
export function isContributionEnabled(state: ContributionEnablementState): boolean {
19
return state === ContributionEnablementState.EnabledProfile || state === ContributionEnablementState.EnabledWorkspace;
20
}
21
22
export function isContributionDisabled(state: ContributionEnablementState): boolean {
23
return !isContributionEnabled(state);
24
}
25
26
export interface IEnablementModel {
27
readEnabled(key: string, reader?: IReader): ContributionEnablementState;
28
setEnabled(key: string, state: ContributionEnablementState, tx?: ITransaction): void;
29
remove(key: string): void;
30
}
31
32
type EnablementMap = ReadonlyMap<string, boolean>;
33
34
function mapToStorage(value: EnablementMap): string {
35
return JSON.stringify([...value]);
36
}
37
38
function mapFromStorage(value: string): EnablementMap {
39
const parsed = JSON.parse(value);
40
return new Map(Array.isArray(parsed) ? parsed : []);
41
}
42
43
/**
44
* A reusable enablement model for string-keyed contributions. Uses
45
* `observableMemento` to persist enable/disable state in both profile-scoped
46
* and workspace-scoped storage.
47
*
48
* Resolution order: if a workspace-scoped entry exists for a key, it wins.
49
* Otherwise, the profile-scoped entry is used. The default (absence of any
50
* entry) is {@link ContributionEnablementState.EnabledProfile}.
51
*/
52
export class EnablementModel extends Disposable implements IEnablementModel {
53
private readonly _profileState: ObservableMemento<EnablementMap>;
54
private readonly _workspaceState: ObservableMemento<EnablementMap>;
55
56
constructor(
57
storageKey: string,
58
@IStorageService storageService: IStorageService,
59
) {
60
super();
61
62
const mapMemento = observableMemento<EnablementMap>({
63
key: storageKey,
64
defaultValue: new Map(),
65
toStorage: mapToStorage,
66
fromStorage: mapFromStorage,
67
});
68
69
this._profileState = this._register(
70
mapMemento(StorageScope.PROFILE, StorageTarget.MACHINE, storageService)
71
);
72
73
this._workspaceState = this._register(
74
mapMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE, storageService)
75
);
76
}
77
78
readEnabled(key: string, reader?: IReader): ContributionEnablementState {
79
const wsMap = this._workspaceState.read(reader);
80
if (wsMap.has(key)) {
81
return wsMap.get(key)!
82
? ContributionEnablementState.EnabledWorkspace
83
: ContributionEnablementState.DisabledWorkspace;
84
}
85
86
const profileMap = this._profileState.read(reader);
87
if (profileMap.has(key)) {
88
return profileMap.get(key)!
89
? ContributionEnablementState.EnabledProfile
90
: ContributionEnablementState.DisabledProfile;
91
}
92
93
return ContributionEnablementState.EnabledProfile;
94
}
95
96
setEnabled(key: string, state: ContributionEnablementState, tx?: ITransaction): void {
97
switch (state) {
98
case ContributionEnablementState.EnabledProfile: {
99
// Enabled-profile is the default: remove key from profile state,
100
// and also remove any workspace override.
101
this._deleteFromMap(this._profileState, key, tx);
102
this._deleteFromMap(this._workspaceState, key, tx);
103
break;
104
}
105
case ContributionEnablementState.DisabledProfile: {
106
// Store disabled in profile, remove workspace override.
107
this._setInMap(this._profileState, key, false, tx);
108
this._deleteFromMap(this._workspaceState, key, tx);
109
break;
110
}
111
case ContributionEnablementState.EnabledWorkspace: {
112
// Workspace override: always store explicitly.
113
this._setInMap(this._workspaceState, key, true, tx);
114
break;
115
}
116
case ContributionEnablementState.DisabledWorkspace: {
117
// Workspace override: always store explicitly.
118
this._setInMap(this._workspaceState, key, false, tx);
119
break;
120
}
121
}
122
}
123
124
remove(key: string): void {
125
this._deleteFromMap(this._profileState, key);
126
this._deleteFromMap(this._workspaceState, key);
127
}
128
129
private _setInMap(memento: ObservableMemento<EnablementMap>, key: string, value: boolean, tx?: ITransaction): void {
130
const current = memento.get();
131
if (current.get(key) === value) {
132
return;
133
}
134
const next = new Map(current);
135
next.set(key, value);
136
memento.set(next, tx);
137
}
138
139
private _deleteFromMap(memento: ObservableMemento<EnablementMap>, key: string, tx?: ITransaction): void {
140
const current = memento.get();
141
if (!current.has(key)) {
142
return;
143
}
144
const next = new Map(current);
145
next.delete(key);
146
memento.set(next, tx);
147
}
148
}
149
150