From b00945fc8c79f6db74b280ef53eba060ed9a1388 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Thu, 18 May 2017 12:33:48 -0700 Subject: [PATCH] Quick link for tools and languages (fixes #22098) --- product.json | 5 + .../extensions/browser/extensionsActions.ts | 28 +++ .../extensions.contribution.ts | 7 +- ...keymapExtensions.ts => extensionsUtils.ts} | 24 +-- .../electron-browser/vs_code_welcome_page.ts | 14 +- .../page/electron-browser/welcomePage.css | 6 +- .../page/electron-browser/welcomePage.ts | 190 ++++++++++++------ 7 files changed, 191 insertions(+), 83 deletions(-) rename src/vs/workbench/parts/extensions/electron-browser/{keymapExtensions.ts => extensionsUtils.ts} (81%) diff --git a/product.json b/product.json index 49f852e2928..b4c35813f4e 100644 --- a/product.json +++ b/product.json @@ -14,5 +14,10 @@ "win32ShellNameShort": "C&ode - OSS", "darwinBundleIdentifier": "com.visualstudio.code.oss", "reportIssueUrl": "https://github.com/Microsoft/vscode/issues/new", + "extensionsGallery": { + "serviceUrl": "https://marketplace.visualstudio.com/_apis/public/gallery", + "cacheUrl": "https://vscode.blob.core.windows.net/gallery/index", + "itemUrl": "https://marketplace.visualstudio.com/items" + }, "urlProtocol": "code-oss" } \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index 748b574f248..6b29b621d0f 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -1048,6 +1048,34 @@ export class ShowRecommendedKeymapExtensionsAction extends Action { } } +export class ShowExtensionPacksAction extends Action { + + static ID = 'workbench.extensions.action.showExtensionPacks'; + static LABEL = localize('showExtensionPacks', "Show Extension Packs"); + static SHORT_LABEL = localize('showExtensionPacksShort', "Extension Packs"); + + constructor( + id: string, + label: string, + @IViewletService private viewletService: IViewletService + ) { + super(id, label, null, true); + } + + run(): TPromise { + return this.viewletService.openViewlet(VIEWLET_ID, true) + .then(viewlet => viewlet as IExtensionsViewlet) + .then(viewlet => { + viewlet.search('@sort:installs @category:"extension packs" '); + viewlet.focus(); + }); + } + + protected isEnabled(): boolean { + return true; + } +} + export class ChangeSortAction extends Action { private query: Query; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts index 827ae6984e1..c46c015065d 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts @@ -24,7 +24,7 @@ import { ExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/node/e import { OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowWorkspaceRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, UpdateAllAction, ConfigureWorkspaceRecommendedExtensionsAction, - EnableAllAction, EnableAllWorkpsaceAction, DisableAllAction, DisableAllWorkpsaceAction, CheckForUpdatesAction + EnableAllAction, EnableAllWorkpsaceAction, DisableAllAction, DisableAllWorkpsaceAction, CheckForUpdatesAction, ShowExtensionPacksAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import { OpenExtensionsFolderAction, InstallVSIXAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; @@ -37,7 +37,7 @@ import jsonContributionRegistry = require('vs/platform/jsonschemas/common/jsonCo import { ExtensionsConfigurationSchema, ExtensionsConfigurationSchemaId } from 'vs/workbench/parts/extensions/common/extensionsFileTemplate'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { KeymapExtensions } from 'vs/workbench/parts/extensions/electron-browser/keymapExtensions'; +import { KeymapExtensions } from 'vs/workbench/parts/extensions/electron-browser/extensionsUtils'; import { adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; // Singletons @@ -115,6 +115,9 @@ actionRegistry.registerWorkbenchAction(recommendationsActionDescriptor, 'Extensi const keymapRecommendationsActionDescriptor = new SyncActionDescriptor(ShowRecommendedKeymapExtensionsAction, ShowRecommendedKeymapExtensionsAction.ID, ShowRecommendedKeymapExtensionsAction.SHORT_LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_M) }); actionRegistry.registerWorkbenchAction(keymapRecommendationsActionDescriptor, 'Preferences: Keymaps', PreferencesLabel); +const extensionPacksActionDescriptor = new SyncActionDescriptor(ShowExtensionPacksAction, ShowExtensionPacksAction.ID, ShowExtensionPacksAction.SHORT_LABEL); +actionRegistry.registerWorkbenchAction(extensionPacksActionDescriptor, 'Extensions: Extension Packs', PreferencesLabel); + const workspaceRecommendationsActionDescriptor = new SyncActionDescriptor(ShowWorkspaceRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction.ID, ShowWorkspaceRecommendedExtensionsAction.LABEL); actionRegistry.registerWorkbenchAction(workspaceRecommendationsActionDescriptor, 'Extensions: Show Workspace Recommended Extensions', ExtensionsLabel); diff --git a/src/vs/workbench/parts/extensions/electron-browser/keymapExtensions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts similarity index 81% rename from src/vs/workbench/parts/extensions/electron-browser/keymapExtensions.ts rename to src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts index 5c30ad7c0be..e8802bef6f1 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/keymapExtensions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts @@ -19,7 +19,7 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -export interface IKeymapExtension { +export interface IExtensionStatus { identifier: string; local: ILocalExtension; globallyEnabled: boolean; @@ -32,13 +32,14 @@ export class KeymapExtensions implements IWorkbenchContribution { constructor( @IInstantiationService private instantiationService: IInstantiationService, @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, + @IExtensionTipsService private tipsService: IExtensionTipsService, @IChoiceService private choiceService: IChoiceService, @ILifecycleService lifecycleService: ILifecycleService, @ITelemetryService private telemetryService: ITelemetryService, ) { this.disposables.push( lifecycleService.onShutdown(() => this.dispose()), - instantiationService.invokeFunction(onKeymapExtensionChanged)((ids => { + instantiationService.invokeFunction(onExtensionChanged)((ids => { TPromise.join(ids.map(id => this.checkForOtherKeymaps(id))) .then(null, onUnexpectedError); })) @@ -50,10 +51,11 @@ export class KeymapExtensions implements IWorkbenchContribution { } private checkForOtherKeymaps(extensionId: string): TPromise { - return this.instantiationService.invokeFunction(getInstalledKeymaps).then(extensions => { - const extension = arrays.first(extensions, extension => extension.identifier === extensionId); + return this.instantiationService.invokeFunction(getInstalledExtensions).then(extensions => { + const keymaps = extensions.filter(extension => isKeymapExtension(this.tipsService, extension)); + const extension = arrays.first(keymaps, extension => extension.identifier === extensionId); if (extension && extension.globallyEnabled) { - const otherKeymaps = extensions.filter(extension => extension.identifier !== extensionId && extension.globallyEnabled); + const otherKeymaps = keymaps.filter(extension => extension.identifier !== extensionId && extension.globallyEnabled); if (otherKeymaps.length) { return this.promptForDisablingOtherKeymaps(extension, otherKeymaps); } @@ -62,7 +64,7 @@ export class KeymapExtensions implements IWorkbenchContribution { }); } - private promptForDisablingOtherKeymaps(newKeymap: IKeymapExtension, oldKeymaps: IKeymapExtension[]): TPromise { + private promptForDisablingOtherKeymaps(newKeymap: IExtensionStatus, oldKeymaps: IExtensionStatus[]): TPromise { const telemetryData: { [key: string]: any; } = { newKeymap: newKeymap.identifier, oldKeymaps: oldKeymaps.map(k => k.identifier) @@ -92,7 +94,7 @@ export class KeymapExtensions implements IWorkbenchContribution { } } -export function onKeymapExtensionChanged(accessor: ServicesAccessor): Event { +export function onExtensionChanged(accessor: ServicesAccessor): Event { const extensionService = accessor.get(IExtensionManagementService); const extensionEnablementService = accessor.get(IExtensionEnablementService); return debounceEvent(any( @@ -110,13 +112,12 @@ export function onKeymapExtensionChanged(accessor: ServicesAccessor): Event { +export function getInstalledExtensions(accessor: ServicesAccessor): TPromise { const extensionService = accessor.get(IExtensionManagementService); const extensionEnablementService = accessor.get(IExtensionEnablementService); - const tipsService = accessor.get(IExtensionTipsService); return extensionService.getInstalled().then(extensions => { const globallyDisabled = extensionEnablementService.getGloballyDisabledExtensions(); - const installedExtensions = extensions.map(extension => { + return extensions.map(extension => { const identifier = stripVersion(extension.id); return { identifier, @@ -124,11 +125,10 @@ export function getInstalledKeymaps(accessor: ServicesAccessor): TPromise isKeymapExtension(tipsService, extension)); }); } -function isKeymapExtension(tipsService: IExtensionTipsService, extension: IKeymapExtension): boolean { +export function isKeymapExtension(tipsService: IExtensionTipsService, extension: IExtensionStatus): boolean { const cats = extension.local.manifest.categories; return cats && cats.indexOf('Keymaps') !== -1 || tipsService.getKeymapRecommendations().indexOf(extension.identifier) !== -1; } diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts b/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts index 6f52d129c86..041c4026aa7 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts @@ -52,14 +52,15 @@ export default () => `

${escape(localize('welcomePage.customize', "Customize"))}

    -
  • +
  • -
@@ -74,6 +75,7 @@ export default () => `

${escape(localize('welcomePage.quickLinks', "Quick links"))}

  • +
diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css index 78cee53838d..982a72d9d1b 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.css @@ -245,13 +245,13 @@ outline-offset: -5px; } -.monaco-workbench > .part.editor > .content .welcomePage .commands li button .currentKeymap { +.monaco-workbench > .part.editor > .content .welcomePage .commands li button .enabledExtension { display: none; } -.monaco-workbench > .part.editor > .content .welcomePage .commands li button .installKeymap.installed { +.monaco-workbench > .part.editor > .content .welcomePage .commands li button .installExtension.installed { display: none; } -.monaco-workbench > .part.editor > .content .welcomePage .commands li button .currentKeymap.installed { +.monaco-workbench > .part.editor > .content .welcomePage .commands li button .enabledExtension.installed { display: inline; } diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index cb7607b1648..874bc17d8dd 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -27,8 +27,8 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { Schemas } from 'vs/base/common/network'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IMessageService, Severity, CloseAction } from 'vs/platform/message/common/message'; -import { getInstalledKeymaps, IKeymapExtension, onKeymapExtensionChanged } from 'vs/workbench/parts/extensions/electron-browser/keymapExtensions'; -import { IExtensionEnablementService, IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { getInstalledExtensions, IExtensionStatus, onExtensionChanged, isKeymapExtension } from 'vs/workbench/parts/extensions/electron-browser/extensionsUtils'; +import { IExtensionEnablementService, IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { used } from 'vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -101,6 +101,57 @@ const reorderedQuickLinks = [ 'showInteractivePlayground', ]; +interface ExtensionSuggestion { + name: string; + id: string; + isKeymap?: boolean; +} + +const extensionPacks: ExtensionSuggestion[] = [ + { name: localize('welcomePage.javaScript', "JavaScript"), id: 'dbaeumer.vscode-eslint' }, + { name: localize('welcomePage.typeScript', "TypeScript"), id: 'eg2.tslint' }, + { name: localize('welcomePage.python', "Python"), id: 'donjayamanne.python' }, + // { name: localize('welcomePage.go', "Go"), id: 'lukehoban.go' }, + { name: localize('welcomePage.php', "PHP"), id: 'felixfbecker.php-pack' }, + { name: localize('welcomePage.docker', "Docker"), id: 'PeterJausovec.vscode-docker' }, +]; + +const keymapExtensions: ExtensionSuggestion[] = [ + { name: localize('welcomePage.vim', "Vim"), id: 'vscodevim.vim', isKeymap: true }, + { name: localize('welcomePage.sublime', "Sublime"), id: 'ms-vscode.sublime-keybindings', isKeymap: true }, + { name: localize('welcomePage.atom', "Atom"), id: 'ms-vscode.atom-keybindings', isKeymap: true }, +]; + +interface Strings { + installEvent: string; + installedEvent: string; + + alreadyInstalled: string; + reloadAfterInstall: string; + installing: string; + extensionNotFound: string; +} + +const extensionPackStrings: Strings = { + installEvent: 'installExtension', + installedEvent: 'installedExtension', + + alreadyInstalled: localize('welcomePage.extensionPackAlreadyInstalled', "Support for {0} is already installed."), + reloadAfterInstall: localize('welcomePage.willReloadAfterInstallingExtensionPack', "The window will reload after installing support for {0}."), + installing: localize('welcomePage.installingExtensionPack', "Installing support for {0}..."), + extensionNotFound: localize('welcomePage.extensionPackNotFound', "Support for {0} with id {1} could not be found."), +}; + +const keymapStrings: Strings = { + installEvent: 'installKeymap', + installedEvent: 'installedKeymap', + + alreadyInstalled: localize('welcomePage.keymapAlreadyInstalled', "The {0} keyboard shortcuts are already installed."), + reloadAfterInstall: localize('welcomePage.willReloadAfterInstallingKeymap', "The window will reload after installing the {0} keyboard shortcuts."), + installing: localize('welcomePage.installingKeymap', "Installing the {0} keyboard shortcuts..."), + extensionNotFound: localize('welcomePage.keymapNotFound', "The {0} keyboard shortcuts with id {1} could not be found."), +}; + class WelcomePage { private disposables: IDisposable[] = []; @@ -118,6 +169,7 @@ class WelcomePage { @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, @IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService, @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionTipsService private tipsService: IExtensionTipsService, @ILifecycleService lifecycleService: ILifecycleService, @IThemeService private themeService: IThemeService, @ITelemetryService private telemetryService: ITelemetryService @@ -128,18 +180,18 @@ class WelcomePage { private create() { const recentlyOpened = this.windowService.getRecentlyOpen(); - const installedKeymaps = this.instantiationService.invokeFunction(getInstalledKeymaps); + const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions); const uri = URI.parse(require.toUrl('./vs_code_welcome_page')) .with({ scheme: Schemas.walkThrough, query: JSON.stringify({ moduleId: 'vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page' }) }); - const input = this.instantiationService.createInstance(WalkThroughInput, localize('welcome.title', "Welcome"), '', uri, telemetryFrom, container => this.onReady(container, recentlyOpened, installedKeymaps)); + const input = this.instantiationService.createInstance(WalkThroughInput, localize('welcome.title', "Welcome"), '', uri, telemetryFrom, container => this.onReady(container, recentlyOpened, installedExtensions)); this.editorService.openEditor(input, { pinned: true }, Position.ONE) .then(null, onUnexpectedError); } - private onReady(container: HTMLElement, recentlyOpened: TPromise<{ files: string[]; folders: string[]; }>, installedKeymaps: TPromise): void { + private onReady(container: HTMLElement, recentlyOpened: TPromise<{ files: string[]; folders: string[]; }>, installedExtensions: TPromise): void { const enabled = this.configurationService.lookup(enabledKey).value; const showOnStartup = container.querySelector('#showOnStartup'); if (enabled) { @@ -214,32 +266,50 @@ class WelcomePage { quickLinks.remove(); } - container.addEventListener('click', event => { - for (let node = event.target as HTMLElement; node; node = node.parentNode as HTMLElement) { - if (node instanceof HTMLAnchorElement && node.classList.contains('installKeymap')) { - const keymapName = node.getAttribute('data-keymap-name'); - const keymapIdentifier = node.getAttribute('data-keymap'); - if (keymapName && keymapIdentifier) { - this.installKeymap(keymapName, keymapIdentifier); - event.preventDefault(); - event.stopPropagation(); - } - } - } - }); + this.addExtensionList(container, '.extensionPackList', extensionPacks, extensionPackStrings); + this.addExtensionList(container, '.keymapList', keymapExtensions, keymapStrings); - this.updateInstalledKeymaps(container, installedKeymaps); - this.disposables.push(this.instantiationService.invokeFunction(onKeymapExtensionChanged)(ids => { + this.updateInstalledExtensions(container, installedExtensions); + this.disposables.push(this.instantiationService.invokeFunction(onExtensionChanged)(ids => { for (const id of ids) { - if (container.querySelector(`.installKeymap[data-keymap="${id}"], .currentKeymap[data-keymap="${id}"]`)) { - const installedKeymaps = this.instantiationService.invokeFunction(getInstalledKeymaps); - this.updateInstalledKeymaps(container, installedKeymaps); + if (container.querySelector(`.installExtension[data-extension="${id}"], .enabledExtension[data-extension="${id}"]`)) { + const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions); + this.updateInstalledExtensions(container, installedExtensions); break; } }; })); } + private addExtensionList(container: HTMLElement, listSelector: string, suggestions: ExtensionSuggestion[], strings: Strings) { + const list = container.querySelector(listSelector); + if (list) { + suggestions.forEach((extension, i) => { + if (i) { + list.appendChild(document.createTextNode(localize('welcomePage.extensionListSeparator', ", "))); + } + + const a = document.createElement('a'); + a.innerText = extension.name; + a.classList.add('installExtension'); + a.setAttribute('data-extension', extension.id); + a.href = 'javascript:void(0)'; + a.addEventListener('click', e => { + this.installExtension(extension, strings); + e.preventDefault(); + e.stopPropagation(); + }); + list.appendChild(a); + + const span = document.createElement('span'); + span.innerText = localize('welcomePage.installedExtension', "{0} (installed)", extension.name); + span.classList.add('enabledExtension'); + span.setAttribute('data-extension', extension.id); + list.appendChild(span); + }); + } + } + private pathEquals(path1: string, path2: string): boolean { if (!isLinux) { path1 = path1.toLowerCase(); @@ -249,23 +319,23 @@ class WelcomePage { return path1 === path2; } - private installKeymap(keymapName: string, keymapIdentifier: string): void { - this.telemetryService.publicLog('installKeymap', { + private installExtension(extensionSuggestion: ExtensionSuggestion, strings: Strings): void { + this.telemetryService.publicLog(strings.installEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, + extensionId: extensionSuggestion.id, }); - this.instantiationService.invokeFunction(getInstalledKeymaps).then(extensions => { - const keymap = arrays.first(extensions, extension => extension.identifier === keymapIdentifier); - if (keymap && keymap.globallyEnabled) { - this.telemetryService.publicLog('installedKeymap', { + this.instantiationService.invokeFunction(getInstalledExtensions).then(extensions => { + const installedExtension = arrays.first(extensions, extension => extension.identifier === extensionSuggestion.id); + if (installedExtension && installedExtension.globallyEnabled) { + this.telemetryService.publicLog(strings.installedEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, + extensionId: extensionSuggestion.id, outcome: 'already_enabled', }); - this.messageService.show(Severity.Info, localize('welcomePage.keymapAlreadyInstalled', "The {0} keyboard shortcuts are already installed.", keymapName)); + this.messageService.show(Severity.Info, strings.alreadyInstalled.replace('{0}', extensionSuggestion.name)); return; } - const foundAndInstalled = keymap ? TPromise.as(true) : this.extensionGalleryService.query({ names: [keymapIdentifier] }) + const foundAndInstalled = installedExtension ? TPromise.as(true) : this.extensionGalleryService.query({ names: [extensionSuggestion.id] }) .then(result => { const [extension] = result.firstPage; if (!extension) { @@ -274,52 +344,52 @@ class WelcomePage { return this.extensionManagementService.installFromGallery(extension) .then(() => { // TODO: Do this as part of the install to avoid multiple events. - return this.extensionEnablementService.setEnablement(keymapIdentifier, false); + return this.extensionEnablementService.setEnablement(extensionSuggestion.id, false); }).then(() => { return true; }); }); this.messageService.show(Severity.Info, { - message: localize('welcomePage.willReloadAfterInstallingKeymap', "The window will reload after installing the {0} keyboard shortcuts.", keymapName), + message: strings.reloadAfterInstall.replace('{0}', extensionSuggestion.name), actions: [ new Action('ok', localize('ok', "OK"), null, true, () => { const messageDelay = TPromise.timeout(300); messageDelay.then(() => { this.messageService.show(Severity.Info, { - message: localize('welcomePage.installingKeymap', "Installing the {0} keyboard shortcuts...", keymapName), + message: strings.installing.replace('{0}', extensionSuggestion.name), actions: [CloseAction] }); }); - TPromise.join(extensions.filter(extension => extension.globallyEnabled) + TPromise.join(extensionSuggestion.isKeymap ? extensions.filter(extension => isKeymapExtension(this.tipsService, extension) && extension.globallyEnabled) .map(extension => { return this.extensionEnablementService.setEnablement(extension.identifier, false); - })).then(() => { + }) : []).then(() => { return foundAndInstalled.then(found => { messageDelay.cancel(); if (found) { - return this.extensionEnablementService.setEnablement(keymapIdentifier, true) + return this.extensionEnablementService.setEnablement(extensionSuggestion.id, true) .then(() => { - this.telemetryService.publicLog('installedKeymap', { + this.telemetryService.publicLog(strings.installedEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, - outcome: keymap ? 'enabled' : 'installed', + extensionId: extensionSuggestion.id, + outcome: installedExtension ? 'enabled' : 'installed', }); return this.windowService.reloadWindow(); }); } else { - this.telemetryService.publicLog('installedKeymap', { + this.telemetryService.publicLog(strings.installedEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, + extensionId: extensionSuggestion.id, outcome: 'not_found', }); - this.messageService.show(Severity.Error, localize('welcomePage.keymapNotFound', "The {0} keyboard shortcuts with id {1} could not be found.", keymapName, keymapIdentifier)); + this.messageService.show(Severity.Error, strings.extensionNotFound.replace('{0}', extensionSuggestion.name).replace('{1}', extensionSuggestion.id)); return undefined; } }); }).then(null, err => { - this.telemetryService.publicLog('installedKeymap', { + this.telemetryService.publicLog(strings.installedEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, + extensionId: extensionSuggestion.id, outcome: isPromiseCanceledError(err) ? 'canceled' : 'error', error: String(err), }); @@ -328,9 +398,9 @@ class WelcomePage { return TPromise.as(true); }), new Action('cancel', localize('cancel', "Cancel"), null, true, () => { - this.telemetryService.publicLog('installedKeymap', { + this.telemetryService.publicLog(strings.installedEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, + extensionId: extensionSuggestion.id, outcome: 'user_canceled', }); return TPromise.as(true); @@ -338,9 +408,9 @@ class WelcomePage { ] }); }).then(null, err => { - this.telemetryService.publicLog('installedKeymap', { + this.telemetryService.publicLog(strings.installedEvent, { from: telemetryFrom, - extensionId: keymapIdentifier, + extensionId: extensionSuggestion.id, outcome: isPromiseCanceledError(err) ? 'canceled' : 'error', error: String(err), }); @@ -348,22 +418,22 @@ class WelcomePage { }); } - private updateInstalledKeymaps(container: HTMLElement, installedKeymaps: TPromise) { - installedKeymaps.then(extensions => { - const elements = container.querySelectorAll('.installKeymap, .currentKeymap'); + private updateInstalledExtensions(container: HTMLElement, installedExtensions: TPromise) { + installedExtensions.then(extensions => { + const elements = container.querySelectorAll('.installExtension, .enabledExtension'); for (let i = 0; i < elements.length; i++) { elements[i].classList.remove('installed'); } extensions.filter(ext => ext.globallyEnabled) .map(ext => ext.identifier) .forEach(id => { - const install = container.querySelector(`.installKeymap[data-keymap="${id}"]`); - if (install) { - install.classList.add('installed'); + const install = container.querySelectorAll(`.installExtension[data-extension="${id}"]`); + for (let i = 0; i < install.length; i++) { + install[i].classList.add('installed'); } - const current = container.querySelector(`.currentKeymap[data-keymap="${id}"]`); - if (current) { - current.classList.add('installed'); + const enabled = container.querySelectorAll(`.enabledExtension[data-extension="${id}"]`); + for (let i = 0; i < enabled.length; i++) { + enabled[i].classList.add('installed'); } }); }).then(null, onUnexpectedError);