-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to ignore recommendations both globally and at a per-workspace level #51941
Add ability to ignore recommendations both globally and at a per-workspace level #51941
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Phase 1 is done. I'll get back to this in an hr.
@@ -74,6 +74,7 @@ export const IExtensionsWorkbenchService = createDecorator<IExtensionsWorkbenchS | |||
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.
@@ -16,7 +16,16 @@ export const ExtensionsConfigurationSchema: IJSONSchema = { | |||
properties: { | |||
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.
@@ -544,6 +544,37 @@ export class EnableGloballyAction extends Action implements IExtensionAction { | |||
} | |||
} | |||
|
|||
export class IgnoreAction extends Action { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
@@ -369,6 +392,22 @@ export class ExtensionEditor extends BaseEditor { | |||
this.extensionActionBar.push([disabledStatusAction, reloadAction, updateAction, enableAction, disableAction, installAction, maliciousStatusAction], { icon: true, label: true }); | |||
this.transientDisposables.push(enableAction, updateAction, reloadAction, disableAction, installAction, maliciousStatusAction, disabledStatusAction); | |||
|
|||
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.
@@ -374,6 +384,8 @@ export interface IExtensionTipsService { | |||
getKeymapRecommendations(): string[]; | |||
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.
*/ | ||
this.telemetryService.publicLog('extensionGallery:openExtension', assign(extension.telemetryData, recommendationsData)); | ||
|
||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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...
?
@@ -295,24 +306,25 @@ export class ExtensionEditor extends BaseEditor { | |||
this.publisher.textContent = extension.publisherDisplayName; | |||
this.description.textContent = extension.description; | |||
|
|||
removeClass(this.header, 'ignored'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like now, this is the only place from where we call mergeExtensionRecommendationConfigs
, in which case, how about merging its code into processConfigContent
?
@@ -555,86 +636,84 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe | |||
}); | |||
} | |||
|
|||
private _suggestWorkspaceRecommendations(): TPromise<any> { | |||
private _suggestWorkspaceRecommendations(allRecommendations: string[]): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this parameter need to be passed in? Can we not use this._allWorkspaceRecommendedExtensions
directly?
…arl/vscode into feature/un-recomend-extensions
Resolves #48743.