Add ability to ignore recommendations both globally and at a per-workspace level#51941
Conversation
ramya-rao-a
left a comment
There was a problem hiding this comment.
Review Phase 1 is done. I'll get back to this in an hr.
| export interface IExtensionsWorkbenchService { | ||
| _serviceBrand: any; | ||
| onChange: Event<void>; | ||
| onRecommendationChange: Event<void>; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| data.root.setAttribute('aria-label', extension.displayName + '. ' + extRecommendations[extension.id]); | ||
| data.root.title = extRecommendations[extension.id.toLowerCase()].reasonText; | ||
| addClass(data.root, 'recommended'); | ||
| } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| recommendations: { | ||
| type: 'array', | ||
| description: localize('app.extensions.json.recommendations', "List of extensions recommendations. The identifier of an extension is always '${publisher}.${name}'. For example: 'vscode.csharp'."), | ||
| description: localize('app.extensions.json.recommendations', "List of extensions which should be recommended for users of this repository. The identifier of an extension is always '${publisher}.${name}'. For example: 'vscode.csharp'."), |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| }, | ||
| unwantedRecommendations: { | ||
| type: 'array', | ||
| description: localize('app.extensions.json.unwantedRecommendations', "List of extensions which are irrelevant, redundant, or otherwise unwanted, and should not be recommended for users of this repository. The identifier of an extension is always '${publisher}.${name}'. For example: 'vscode.csharp'."), |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| } | ||
| } | ||
|
|
||
| export class IgnoreAction extends Action { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
|
||
| const ignoreAction = this.instantiationService.createInstance(IgnoreAction); | ||
| ignoreAction.extension = extension; | ||
| ignoreAction.onIgnored = () => { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| this.recommendationText.textContent = localize('recommendationHasBeenIgnoredGlobal', "You have chosen not to receive recommendations for this extension."); | ||
| } | ||
| if (ignoredRecommendations.workspace.indexOf(extension.id.toLowerCase()) !== -1) { | ||
| this.recommendationText.textContent = localize('recommendationHasBeenIgnoredWorkspace', "This extension has been marked as redundant or irrelevant by users of the current workspace."); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| recommendations: string[]; | ||
| unwantedRecommendations: string[]; | ||
| } | ||
|
|
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| getKeywordsForExtension(extension: string): string[]; | ||
| getRecommendationsForExtension(extension: string): string[]; | ||
| refreshAllIgnoredRecommendations(): TPromise<void>; | ||
| getAllIgnoredRecommendations(): IIgnoredRecommendations; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| const ignoredRecommendations = this.extensionTipsService.getAllIgnoredRecommendations(); | ||
|
|
||
| toggleClass(this.header, 'ignored', this.recentlyIgnored.indexOf(extension.id.toLowerCase()) !== -1 || ignoredRecommendations.workspace.indexOf(extension.id.toLowerCase()) !== -1); | ||
| if (this.recentlyIgnored.indexOf(extension.id.toLowerCase()) !== -1) { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
|
||
| const ignoredRecommendations = this.extensionTipsService.getAllIgnoredRecommendations(); | ||
|
|
||
| toggleClass(this.header, 'ignored', this.recentlyIgnored.indexOf(extension.id.toLowerCase()) !== -1 || ignoredRecommendations.workspace.indexOf(extension.id.toLowerCase()) !== -1); |
There was a problem hiding this comment.
Do we really need to add the ignored class?
From what I can see in the css file, its used in the same situation where the recommended label is used.
There was a problem hiding this comment.
It stylizes the text differently and removes the ignore button
| return cleansedIDs; | ||
| } | ||
|
|
||
| refreshAllIgnoredRecommendations(): TPromise<void> { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| }); | ||
|
|
||
| this._exeBasedRecommendations = filteredExeBased; | ||
| this._fileBasedRecommendations = filteredFileBased; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
…arl/vscode into feature/un-recomend-extensions
| '\t\t', | ||
| '\t],', | ||
| '\t"unwantedRecommendations": [', | ||
| '\t\t// List of extensions which should not be recommended for users of this workspace. These extensions may be irrelevant, redundant, or otherwise unwanted.', |
There was a problem hiding this comment.
A literal translation of this would mean that we are asking users to list ALL the extensions that they would consider irrelevant/redundant etc.
How about..
List of extensions that will be skipped from the recommendations that VS Code makes for the users of this workspace... ?
| this.publisher.textContent = extension.publisherDisplayName; | ||
| this.description.textContent = extension.description; | ||
|
|
||
| removeClass(this.header, 'ignored'); |
There was a problem hiding this comment.
ignored can be recommendationIgnored?
| .then(contents => this.processConfigContent(this.mergeExtensionRecommendationConfigs(flatten(contents)))); | ||
| } | ||
|
|
||
| private resolveWorkspaceExtensionConfig(workspace: IWorkspace): TPromise<IExtensionsConfigContent[]> { |
There was a problem hiding this comment.
Why are both resolveWorkspaceExtensionConfig and resolveWorkspaceFolderExtensionConfig returning array of IExtensionsConfigContent? They both work on individual files... and so wouldn't the output be just `TPromise< IExtensionsConfigContent>?
There was a problem hiding this comment.
I moved it back to maybe being represented by empty array or array of one rather than merging all over the place. what do you think?
| private fetchCombinedExtensionRecommendationConfig(): TPromise<IExtensionsConfigContent> { | ||
| const workspace = this.contextService.getWorkspace(); | ||
| return TPromise.join([this.resolveWorkspaceExtensionConfig(workspace), ...workspace.folders.map(workspaceFolder => this.resolveWorkspaceFolderExtensionConfig(workspaceFolder))]) | ||
| .then(contents => this.processConfigContent(this.mergeExtensionRecommendationConfigs(flatten(contents)))); |
There was a problem hiding this comment.
Looks like now, this is the only place from where we call mergeExtensionRecommendationConfigs, in which case, how about merging its code into processConfigContent?
| } | ||
|
|
||
| private _suggestWorkspaceRecommendations(): TPromise<any> { | ||
| private _suggestWorkspaceRecommendations(allRecommendations: string[]): void { |
There was a problem hiding this comment.
Does this parameter need to be passed in? Can we not use this._allWorkspaceRecommendedExtensions directly?
…arl/vscode into feature/un-recomend-extensions
Resolves #48743.