Extract keymaps code from ExtensionsWorkbenchService (fixes #16493)
This commit is contained in:
parent
38fbba35ff
commit
b46834dd50
|
@ -37,14 +37,16 @@ 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';
|
||||
|
||||
// Singletons
|
||||
registerSingleton(IExtensionGalleryService, ExtensionGalleryService);
|
||||
registerSingleton(IExtensionTipsService, ExtensionTipsService);
|
||||
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
|
||||
.registerWorkbenchContribution(StatusUpdater);
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchRegistry.registerWorkbenchContribution(StatusUpdater);
|
||||
workbenchRegistry.registerWorkbenchContribution(KeymapExtensions);
|
||||
|
||||
Registry.as<IOutputChannelRegistry>(OutputExtensions.OutputChannels)
|
||||
.registerChannel(ExtensionsChannelId, ExtensionsLabel);
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
import nls = require('vs/nls');
|
||||
import { chain, any } from 'vs/base/common/event';
|
||||
import { onUnexpectedError, canceled } from 'vs/base/common/errors';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IExtensionManagementService, ILocalExtension, IExtensionEnablementService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IChoiceService } from 'vs/platform/message/common/message';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
|
||||
interface IExtension {
|
||||
identifier: string;
|
||||
local: ILocalExtension;
|
||||
}
|
||||
|
||||
export class KeymapExtensions implements IWorkbenchContribution {
|
||||
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementService private extensionService: IExtensionManagementService,
|
||||
@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()),
|
||||
any(
|
||||
chain(extensionService.onDidInstallExtension)
|
||||
.map(e => stripVersion(e.id))
|
||||
.event,
|
||||
extensionEnablementService.onEnablementChanged
|
||||
)((id => {
|
||||
this.checkForOtherKeymaps(id)
|
||||
.then(null, onUnexpectedError);
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return 'vs.extensions.keymapExtensions';
|
||||
}
|
||||
|
||||
private checkForOtherKeymaps(extensionId: string): TPromise<void> {
|
||||
return this.extensionService.getInstalled().then(extensions => {
|
||||
const installedExtensions = extensions.map(ext => ({ identifier: stripVersion(ext.id), local: ext }));
|
||||
const extension = arrays.first(installedExtensions, ext => ext.identifier === extensionId);
|
||||
const globallyDisabled = this.extensionEnablementService.getGloballyDisabledExtensions();
|
||||
if (extension && this.isKeymapExtension(extension) && globallyDisabled.indexOf(extensionId) === -1) {
|
||||
const otherKeymaps = installedExtensions.filter(ext => ext.identifier !== extensionId &&
|
||||
this.isKeymapExtension(ext) &&
|
||||
globallyDisabled.indexOf(ext.identifier) === -1);
|
||||
if (otherKeymaps.length) {
|
||||
return this.promptForDisablingOtherKeymaps(extension, otherKeymaps);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
private isKeymapExtension(extension: IExtension): boolean {
|
||||
const cats = extension.local.manifest.categories;
|
||||
return cats && cats.indexOf('Keymaps') !== -1 || this.tipsService.getKeymapRecommendations().indexOf(extension.identifier) !== -1;
|
||||
}
|
||||
|
||||
private promptForDisablingOtherKeymaps(newKeymap: IExtension, oldKeymaps: IExtension[]): TPromise<void> {
|
||||
const telemetryData: { [key: string]: any; } = {
|
||||
newKeymap: newKeymap.identifier,
|
||||
oldKeymaps: oldKeymaps.map(k => k.identifier)
|
||||
};
|
||||
this.telemetryService.publicLog('disableOtherKeymapsConfirmation', telemetryData);
|
||||
const message = nls.localize('disableOtherKeymapsConfirmation', "Disable other keymaps to avoid conflicts between keybindings?");
|
||||
const options = [
|
||||
nls.localize('yes', "Yes"),
|
||||
nls.localize('no', "No")
|
||||
];
|
||||
return this.choiceService.choose(Severity.Info, message, options, false)
|
||||
.then<void>(value => {
|
||||
const confirmed = value === 0;
|
||||
telemetryData['confirmed'] = confirmed;
|
||||
this.telemetryService.publicLog('disableOtherKeymaps', telemetryData);
|
||||
if (confirmed) {
|
||||
return TPromise.join(oldKeymaps.map(keymap => {
|
||||
return this.extensionEnablementService.setEnablement(keymap.identifier, false);
|
||||
}));
|
||||
}
|
||||
return undefined;
|
||||
}, error => TPromise.wrapError(canceled()));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
||||
|
||||
function stripVersion(id: string): string {
|
||||
return id.replace(/-\d+\.\d+\.\d+$/, '');
|
||||
}
|
|
@ -15,7 +15,7 @@ import { LinkedMap as Map } from 'vs/base/common/map';
|
|||
import { assign } from 'vs/base/common/objects';
|
||||
import { isUUID } from 'vs/base/common/uuid';
|
||||
import { ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { isPromiseCanceledError, onUnexpectedError, canceled } from 'vs/base/common/errors';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IPager, mapPager, singlePagePager } from 'vs/base/common/paging';
|
||||
|
@ -689,8 +689,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
|
|||
installed.local = local;
|
||||
} else {
|
||||
this.installed.push(extension);
|
||||
this.checkForOtherKeymaps(extension)
|
||||
.then(null, onUnexpectedError);
|
||||
}
|
||||
}
|
||||
if (extension.gallery) {
|
||||
|
@ -701,48 +699,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
|
|||
this._onChange.fire();
|
||||
}
|
||||
|
||||
private checkForOtherKeymaps(extension: Extension): TPromise<void> {
|
||||
if (!extension.disabledGlobally && this.isKeymapExtension(extension)) {
|
||||
const otherKeymaps = this.installed.filter(ext => ext.identifier !== extension.identifier &&
|
||||
!ext.disabledGlobally &&
|
||||
this.isKeymapExtension(ext));
|
||||
if (otherKeymaps.length) {
|
||||
return this.promptForDisablingOtherKeymaps(extension, otherKeymaps);
|
||||
}
|
||||
}
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
private isKeymapExtension(extension: Extension): boolean {
|
||||
const cats = extension.local.manifest.categories;
|
||||
return cats && cats.indexOf('Keymaps') !== -1 || this.tipsService.getKeymapRecommendations().indexOf(extension.identifier) !== -1;
|
||||
}
|
||||
|
||||
private promptForDisablingOtherKeymaps(newKeymap: Extension, oldKeymaps: Extension[]): TPromise<void> {
|
||||
const telemetryData: { [key: string]: any; } = {
|
||||
newKeymap: newKeymap.identifier,
|
||||
oldKeymaps: oldKeymaps.map(k => k.identifier)
|
||||
};
|
||||
this.telemetryService.publicLog('disableOtherKeymapsConfirmation', telemetryData);
|
||||
const message = nls.localize('disableOtherKeymapsConfirmation', "Disable other keymaps to avoid conflicts between keybindings?");
|
||||
const options = [
|
||||
nls.localize('yes', "Yes"),
|
||||
nls.localize('no', "No")
|
||||
];
|
||||
return this.choiceService.choose(Severity.Info, message, options, false)
|
||||
.then<void>(value => {
|
||||
const confirmed = value === 0;
|
||||
telemetryData['confirmed'] = confirmed;
|
||||
this.telemetryService.publicLog('disableOtherKeymaps', telemetryData);
|
||||
if (confirmed) {
|
||||
return TPromise.join(oldKeymaps.map(keymap => {
|
||||
return this.setEnablement(keymap, false);
|
||||
}));
|
||||
}
|
||||
return undefined;
|
||||
}, error => TPromise.wrapError(canceled()));
|
||||
}
|
||||
|
||||
private onUninstallExtension(id: string): void {
|
||||
const extension = this.installed.filter(e => e.local.id === id)[0];
|
||||
const newLength = this.installed.filter(e => e.local.id !== id).length;
|
||||
|
@ -785,8 +741,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
|
|||
extension.disabledGlobally = globallyDisabledExtensions.indexOf(extension.identifier) !== -1;
|
||||
extension.disabledForWorkspace = workspaceDisabledExtensions.indexOf(extension.identifier) !== -1;
|
||||
this._onChange.fire();
|
||||
this.checkForOtherKeymaps(<Extension>extension)
|
||||
.then(null, onUnexpectedError);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue