From d20a7229bf426b0820c1434ce14f638bc82e675b Mon Sep 17 00:00:00 2001 From: Peter van Gulik Date: Mon, 18 Dec 2023 15:41:12 +0100 Subject: [PATCH] feat: expose context to commands and introduce new recent items store --- .../datapacks/deployDatapackCommand.ts | 3 +- .../developerLogs/setTraceFlagsCommand.ts | 7 +-- .../vscode-extension/src/lib/commandBase.ts | 6 +- .../src/lib/vlocodeContext.ts | 61 ++++++++++++++++++- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/packages/vscode-extension/src/commands/datapacks/deployDatapackCommand.ts b/packages/vscode-extension/src/commands/datapacks/deployDatapackCommand.ts index b892de19..53aa0044 100644 --- a/packages/vscode-extension/src/commands/datapacks/deployDatapackCommand.ts +++ b/packages/vscode-extension/src/commands/datapacks/deployDatapackCommand.ts @@ -10,7 +10,6 @@ import { DatapackCommand } from './datapackCommand'; import { vscodeCommand } from '../../lib/commandRouter'; import { VlocodeCommand } from '../../constants'; import { VlocityDeploy } from '../../lib/vlocity/vlocityDeploy'; -import { getContext } from '../../lib/vlocodeContext'; import { VlocodeDirectDeployment } from '../../lib/vlocity/vlocodeDirectDeploy'; import { VlocityToolsDeployment } from '../../lib/vlocity/vlocityToolsDeploy'; @@ -140,7 +139,7 @@ export class DeployDatapackCommand extends DatapackCommand { * If the users closes the question without anwsering it it will re-popup on the next deployment. */ private async suggestDeploymentModeChange() { - const suggestionState = getContext().globalState; + const suggestionState = this.context.globalState; const usingDirectMode = this.vlocode.config.deploymentMode === 'direct'; const currentSuggestionState = suggestionState.get(deployModeSuggestionKey); const allowSuggest = !currentSuggestionState || (currentSuggestionState + suggestionInterval < Date.now()); diff --git a/packages/vscode-extension/src/commands/developerLogs/setTraceFlagsCommand.ts b/packages/vscode-extension/src/commands/developerLogs/setTraceFlagsCommand.ts index 13110de2..2daae479 100644 --- a/packages/vscode-extension/src/commands/developerLogs/setTraceFlagsCommand.ts +++ b/packages/vscode-extension/src/commands/developerLogs/setTraceFlagsCommand.ts @@ -3,7 +3,6 @@ import { vscodeCommand } from '../../lib/commandRouter'; import { SalesforceDebugLevel } from '@vlocode/salesforce'; import { DateTime } from 'luxon'; import * as vscode from 'vscode'; -import { getContext } from '../../lib/vlocodeContext'; import MetadataCommand from '../metadata/metadataCommand'; @vscodeCommand(VlocodeCommand.setTraceFlags) @@ -198,17 +197,17 @@ export default class SetTraceFlagsCommand extends MetadataCommand { const customDebugLevels = this.getCustomDebugLevels(); const customDebugLevel = Object.assign(debugLevel, { name, created: Date.now() }); const updatedDebugLevels = [ ...(customDebugLevels?.slice(0, this.customDebugLevelMax - 1) ?? []), customDebugLevel ]; - getContext().globalState.update(this.customDebugLevelKey, updatedDebugLevels); + this.context.globalState.update(this.customDebugLevelKey, updatedDebugLevels); return customDebugLevel; } private getCustomDebugLevels() { - const customLevels = getContext().globalState.get>(this.customDebugLevelKey); + const customLevels = this.context.globalState.get>(this.customDebugLevelKey); return customLevels?.sort((a,b) => b.created - a.created); } private deleteAllCustomDebugLevels() { - getContext().globalState.update(this.customDebugLevelKey, undefined); + this.context.globalState.update(this.customDebugLevelKey, undefined); } public async traceFlagsWatcher() { diff --git a/packages/vscode-extension/src/lib/commandBase.ts b/packages/vscode-extension/src/lib/commandBase.ts index b6c15dd7..1839081a 100644 --- a/packages/vscode-extension/src/lib/commandBase.ts +++ b/packages/vscode-extension/src/lib/commandBase.ts @@ -3,7 +3,7 @@ import * as vscode from 'vscode'; import VlocodeService from '../lib/vlocodeService'; import { container, LogManager } from '@vlocode/core'; import { Command } from '../lib/command'; -import { getContext } from '../lib/vlocodeContext'; +import { getContext, VlocodeContext } from '../lib/vlocodeContext'; import { lazy } from '@vlocode/util'; export abstract class CommandBase implements Command { @@ -15,6 +15,10 @@ export abstract class CommandBase implements Command { public validate?(...args: any[]): any | Promise; + public get context(): VlocodeContext { + return getContext(); + } + protected get currentOpenDocument() : vscode.Uri | undefined { return vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : undefined; } diff --git a/packages/vscode-extension/src/lib/vlocodeContext.ts b/packages/vscode-extension/src/lib/vlocodeContext.ts index 96d0e297..54fd4b9d 100644 --- a/packages/vscode-extension/src/lib/vlocodeContext.ts +++ b/packages/vscode-extension/src/lib/vlocodeContext.ts @@ -6,7 +6,9 @@ import type VlocodeService from './vlocodeService'; /** * Minimal version of VScodes extension context. */ -class VlocodeContext { +export class VlocodeContext { + + readonly recent: RecentItems = new RecentItems(this.globalState); constructor( /** @@ -45,6 +47,63 @@ class VlocodeContext { } } +class RecentItems { + + private readonly recentsPrefix = 'recent:'; + + constructor(private readonly globalState: Memento) { + } + + /** + * Get recent items for for the specified key. Recent items are stored in the global + * state and are sorted by most recent first. The maximum number of recent items is 10. + * @param key Key to get recent items for + * @returns List of recent items + * @template T Type of the recent items + * + * @example + * ```typescript + * const recentItems = context.getRecent('myKey'); + * ``` + */ + public get(key: string): T[] { + return this.globalState.get(`${this.recentsPrefix}:${key}`, []); + } + + /** + * Add an item to the recent items list for the specified key. Recent items are stored in the global + * state and are sorted by most recent first. The maximum number of recent items is 10. + * @param key Key to add the recent item to + * @param item Item to add to the recent items list + * @param options.maxItems Maximum number of recent items to store, defaults to 10 when not specified + * @param options.equals Function to compare two items, when not specified the default matcher is used + * @returns + */ + public add(key: string, item: T, options?: { maxItems?: number, equals?: (item: T, other: T) => boolean }) { + const currentValues = this.globalState.get(`${this.recentsPrefix}:${key}`, []); + const equals = options?.equals ?? ((a, b) => a === b); + const newValues = [item, ...currentValues.filter(v => !equals(item, v))].slice(0, options?.maxItems ?? 10); + this.globalState.update(`${this.recentsPrefix}:${key}`, newValues); + } + + /** + * Clear the recent items list for the specified key. When no key is specified all recent items + * are cleared. + * @param key Key to clear the recent items for + */ + public clear(key?: string) { + if (key) { + this.globalState.update(`${this.recentsPrefix}:${key}`, undefined); + } else { + for (const stateKey of this.globalState.keys()) { + if (stateKey.startsWith(`${this.recentsPrefix}:`)) { + this.globalState.update(stateKey, undefined); + } + } + } + } +} + /** * Get the currently initialized Vlocode context object */