diff --git a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts index 0de614759e0fce5d3df8c61da8179dcca83f2203..29e92583235c98da738e9b49412b3839f093bfdc 100644 --- a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts @@ -26,6 +26,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { setImmediate } from 'vs/base/common/platform'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IExtensionRecommendationNotificationService, RecommendationsNotificationResult, RecommendationSource } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; +import { distinct } from 'vs/base/common/arrays'; type FileExtensionSuggestionClassification = { userReaction: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; @@ -33,6 +34,7 @@ type FileExtensionSuggestionClassification = { }; const promptedRecommendationsStorageKey = 'fileBasedRecommendations/promptedRecommendations'; +const promptedFileExtensionsStorageKey = 'fileBasedRecommendations/promptedFileExtensions'; const recommendationsStorageKey = 'extensionsAssistant/recommendations'; const searchMarketplace = localize('searchMarketplace', "Search Marketplace"); const milliSecondsInADay = 1000 * 60 * 60 * 24; @@ -164,7 +166,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations { } const language = model.getLanguageIdentifier().language; - const fileExtension = extname(uri); + const fileExtension = extname(uri).toLowerCase(); if (this.processedLanguages.includes(language) && this.processedFileExtensions.includes(fileExtension)) { return; } @@ -272,12 +274,27 @@ export class FileBasedRecommendations extends ExtensionRecommendations { this.storageService.store(promptedRecommendationsStorageKey, JSON.stringify(promptedRecommendations), StorageScope.GLOBAL); } + private getPromptedFileExtensions(): string[] { + return JSON.parse(this.storageService.get(promptedFileExtensionsStorageKey, StorageScope.GLOBAL, '[]')); + } + + private addToPromptedFileExtensions(fileExtension: string) { + const promptedFileExtensions = this.getPromptedFileExtensions(); + promptedFileExtensions.push(fileExtension); + this.storageService.store(promptedFileExtensionsStorageKey, JSON.stringify(distinct(promptedFileExtensions)), StorageScope.GLOBAL); + } + private async promptRecommendedExtensionForFileExtension(fileExtension: string, installed: IExtension[]): Promise { const fileExtensionSuggestionIgnoreList = JSON.parse(this.storageService.get('extensionsAssistant/fileExtensionsSuggestionIgnore', StorageScope.GLOBAL, '[]')); if (fileExtensionSuggestionIgnoreList.indexOf(fileExtension) > -1) { return; } + const promptedFileExtensions = this.getPromptedFileExtensions(); + if (promptedFileExtensions.includes(fileExtension)) { + return; + } + const text = `ext:${fileExtension}`; const pager = await this.extensionsWorkbenchService.queryGallery({ text, pageSize: 100 }, CancellationToken.None); if (pager.firstPage.length === 0) { @@ -295,6 +312,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations { [{ label: searchMarketplace, run: () => { + this.addToPromptedFileExtensions(fileExtension); this.telemetryService.publicLog2<{ userReaction: string, fileExtension: string }, FileExtensionSuggestionClassification>('fileExtensionSuggestion:popup', { userReaction: 'ok', fileExtension }); this.viewletService.openViewlet('workbench.view.extensions', true) .then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer)