-
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
Changes from 44 commits
d30415f
76472b7
58e1eed
6803fc1
e9669f4
42e9a32
828fe0a
7c6c8fa
0202014
138f45a
eb876ac
a711169
f287d7f
08df8e0
d9748db
019f2ac
75fddb9
7033d13
a9863f1
328eca4
3073051
8d3b34b
e80b831
07af902
bf04418
6dc8862
976978f
3fa9b65
8052abd
cf92a80
f33abfe
d9a018b
cc2fe62
bf1eea8
0ddd992
1421677
f520130
3e6310f
956c8ab
68ee832
3e8a0e1
374e49d
01a4913
312cf84
c217a29
2fc3625
ba26860
b8438bf
ab52be6
0a60392
b77ba77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,20 @@ export const ExtensionsConfigurationSchema: IJSONSchema = { | |
allowComments: true, | ||
type: 'object', | ||
title: localize('app.extensions.json.title', "Extensions"), | ||
additionalProperties: false, | ||
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 workspace. The identifier of an extension is always '${publisher}.${name}'. For example: 'vscode.csharp'."), | ||
items: { | ||
type: 'string', | ||
pattern: EXTENSION_IDENTIFIER_PATTERN, | ||
errorMessage: localize('app.extension.identifier.errorMessage', "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.") | ||
}, | ||
}, | ||
unwantedRecommendations: { | ||
type: 'array', | ||
description: localize('app.extensions.json.unwantedRecommendations', "List of extensions which should not be recommended for users of this workspace. These extensions may be irrelevant, redundant, or otherwise unwanted. The identifier of an extension is always '${publisher}.${name}'. For example: 'vscode.csharp'."), | ||
items: { | ||
type: 'string', | ||
pattern: EXTENSION_IDENTIFIER_PATTERN, | ||
|
@@ -31,6 +41,12 @@ export const ExtensionsConfigurationInitialContent: string = [ | |
'\t// See http://go.microsoft.com/fwlink/?LinkId=827846', | ||
'\t// for the documentation about the extensions.json format', | ||
'\t"recommendations": [', | ||
'\t\t// List of extensions which should be recommended for users of this workspace.', | ||
'\t\t// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp', | ||
'\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 commentThe 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..
|
||
'\t\t// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp', | ||
'\t\t', | ||
'\t]', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ import { Renderer, DataSource, Controller } from 'vs/workbench/parts/extensions/ | |
import { RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; | ||
import { EditorOptions } from 'vs/workbench/common/editor'; | ||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; | ||
import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, ReloadAction, MaliciousStatusLabelAction, DisabledStatusLabelAction, MultiServerInstallAction, MultiServerUpdateAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions'; | ||
import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, ReloadAction, MaliciousStatusLabelAction, DisabledStatusLabelAction, MultiServerInstallAction, MultiServerUpdateAction, IgnoreExtensionRecommendationAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions'; | ||
import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement'; | ||
import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; | ||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; | ||
|
@@ -164,6 +164,8 @@ export class ExtensionEditor extends BaseEditor { | |
private navbar: NavBar; | ||
private content: HTMLElement; | ||
private recommendation: HTMLElement; | ||
private recommendationText: any; | ||
private ignoreActionbar: ActionBar; | ||
private header: HTMLElement; | ||
|
||
private extensionReadme: Cache<string>; | ||
|
@@ -256,15 +258,24 @@ export class ExtensionEditor extends BaseEditor { | |
return null; | ||
} | ||
}); | ||
this.disposables.push(this.extensionActionBar); | ||
|
||
this.recommendation = append(details, $('.recommendation')); | ||
this.recommendationText = append(this.recommendation, $('.recommendation-text')); | ||
this.ignoreActionbar = new ActionBar(this.recommendation, { animated: false }); | ||
|
||
this.disposables.push(this.extensionActionBar); | ||
this.disposables.push(this.ignoreActionbar); | ||
|
||
chain(this.extensionActionBar.onDidRun) | ||
.map(({ error }) => error) | ||
.filter(error => !!error) | ||
.on(this.onError, this, this.disposables); | ||
|
||
chain(this.ignoreActionbar.onDidRun) | ||
.map(({ error }) => error) | ||
.filter(error => !!error) | ||
.on(this.onError, this, this.disposables); | ||
|
||
const body = append(root, $('.body')); | ||
this.navbar = new NavBar(body); | ||
|
||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason(); | ||
let recommendationsData = {}; | ||
if (extRecommendations[extension.id.toLowerCase()]) { | ||
addClass(this.header, 'recommended'); | ||
this.recommendation.textContent = extRecommendations[extension.id.toLowerCase()].reasonText; | ||
this.recommendationText.textContent = extRecommendations[extension.id.toLowerCase()].reasonText; | ||
recommendationsData = { recommendationReason: extRecommendations[extension.id.toLowerCase()].reasonId }; | ||
} else { | ||
removeClass(this.header, 'recommended'); | ||
this.recommendation.textContent = ''; | ||
this.recommendationText.textContent = ''; | ||
} | ||
|
||
/* __GDPR__ | ||
"extensionGallery:openExtension" : { | ||
"recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, | ||
"${include}": [ | ||
"${GalleryExtensionTelemetryData}" | ||
] | ||
} | ||
"extensionGallery:openExtension" : { | ||
"recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, | ||
"${include}": [ | ||
"${GalleryExtensionTelemetryData}" | ||
] | ||
} | ||
*/ | ||
this.telemetryService.publicLog('extensionGallery:openExtension', assign(extension.telemetryData, recommendationsData)); | ||
|
||
|
@@ -376,6 +388,21 @@ 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(IgnoreExtensionRecommendationAction); | ||
ignoreAction.extension = extension; | ||
|
||
this.extensionTipsService.onRecommendationChange(change => { | ||
if (change.extensionId.toLowerCase() === extension.id.toLowerCase() && change.isRecommended === false) { | ||
addClass(this.header, 'ignored'); | ||
removeClass(this.header, 'recommended'); | ||
this.recommendationText.textContent = localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension."); | ||
} | ||
}); | ||
|
||
this.ignoreActionbar.clear(); | ||
this.ignoreActionbar.push([ignoreAction], { icon: true, label: true }); | ||
this.transientDisposables.push(ignoreAction); | ||
|
||
this.content.innerHTML = ''; // Clear content before setting navbar actions. | ||
|
||
this.navbar.clear(); | ||
|
This comment was marked as resolved.
Sorry, something went wrong.