Path: blob/main/src/vs/workbench/contrib/chat/common/enablement.ts
13401 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Disposable } from '../../../../base/common/lifecycle.js';6import { IReader, ITransaction } from '../../../../base/common/observable.js';7import { ObservableMemento, observableMemento } from '../../../../platform/observable/common/observableMemento.js';8import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';910export const enum ContributionEnablementState {11DisabledProfile,12DisabledWorkspace,13EnabledProfile,14EnabledWorkspace,15}1617export function isContributionEnabled(state: ContributionEnablementState): boolean {18return state === ContributionEnablementState.EnabledProfile || state === ContributionEnablementState.EnabledWorkspace;19}2021export function isContributionDisabled(state: ContributionEnablementState): boolean {22return !isContributionEnabled(state);23}2425export interface IEnablementModel {26readEnabled(key: string, reader?: IReader): ContributionEnablementState;27setEnabled(key: string, state: ContributionEnablementState, tx?: ITransaction): void;28remove(key: string): void;29}3031type EnablementMap = ReadonlyMap<string, boolean>;3233function mapToStorage(value: EnablementMap): string {34return JSON.stringify([...value]);35}3637function mapFromStorage(value: string): EnablementMap {38const parsed = JSON.parse(value);39return new Map(Array.isArray(parsed) ? parsed : []);40}4142/**43* A reusable enablement model for string-keyed contributions. Uses44* `observableMemento` to persist enable/disable state in both profile-scoped45* and workspace-scoped storage.46*47* Resolution order: if a workspace-scoped entry exists for a key, it wins.48* Otherwise, the profile-scoped entry is used. The default (absence of any49* entry) is {@link ContributionEnablementState.EnabledProfile}.50*/51export class EnablementModel extends Disposable implements IEnablementModel {52private readonly _profileState: ObservableMemento<EnablementMap>;53private readonly _workspaceState: ObservableMemento<EnablementMap>;5455constructor(56storageKey: string,57@IStorageService storageService: IStorageService,58) {59super();6061const mapMemento = observableMemento<EnablementMap>({62key: storageKey,63defaultValue: new Map(),64toStorage: mapToStorage,65fromStorage: mapFromStorage,66});6768this._profileState = this._register(69mapMemento(StorageScope.PROFILE, StorageTarget.MACHINE, storageService)70);7172this._workspaceState = this._register(73mapMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE, storageService)74);75}7677readEnabled(key: string, reader?: IReader): ContributionEnablementState {78const wsMap = this._workspaceState.read(reader);79if (wsMap.has(key)) {80return wsMap.get(key)!81? ContributionEnablementState.EnabledWorkspace82: ContributionEnablementState.DisabledWorkspace;83}8485const profileMap = this._profileState.read(reader);86if (profileMap.has(key)) {87return profileMap.get(key)!88? ContributionEnablementState.EnabledProfile89: ContributionEnablementState.DisabledProfile;90}9192return ContributionEnablementState.EnabledProfile;93}9495setEnabled(key: string, state: ContributionEnablementState, tx?: ITransaction): void {96switch (state) {97case ContributionEnablementState.EnabledProfile: {98// Enabled-profile is the default: remove key from profile state,99// and also remove any workspace override.100this._deleteFromMap(this._profileState, key, tx);101this._deleteFromMap(this._workspaceState, key, tx);102break;103}104case ContributionEnablementState.DisabledProfile: {105// Store disabled in profile, remove workspace override.106this._setInMap(this._profileState, key, false, tx);107this._deleteFromMap(this._workspaceState, key, tx);108break;109}110case ContributionEnablementState.EnabledWorkspace: {111// Workspace override: always store explicitly.112this._setInMap(this._workspaceState, key, true, tx);113break;114}115case ContributionEnablementState.DisabledWorkspace: {116// Workspace override: always store explicitly.117this._setInMap(this._workspaceState, key, false, tx);118break;119}120}121}122123remove(key: string): void {124this._deleteFromMap(this._profileState, key);125this._deleteFromMap(this._workspaceState, key);126}127128private _setInMap(memento: ObservableMemento<EnablementMap>, key: string, value: boolean, tx?: ITransaction): void {129const current = memento.get();130if (current.get(key) === value) {131return;132}133const next = new Map(current);134next.set(key, value);135memento.set(next, tx);136}137138private _deleteFromMap(memento: ObservableMemento<EnablementMap>, key: string, tx?: ITransaction): void {139const current = memento.get();140if (!current.has(key)) {141return;142}143const next = new Map(current);144next.delete(key);145memento.set(next, tx);146}147}148149150