mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 09:35:41 -05:00
Merge from vscode 8b5ebbb1b8f6b2127bbbd551ac10cc080482d5b4 (#5041)
This commit is contained in:
@@ -72,8 +72,8 @@ export class FileDialogService implements IFileDialogService {
|
||||
}
|
||||
}
|
||||
|
||||
// ...then fallback to default folder path
|
||||
return this.defaultFolderPath(schemeFilter);
|
||||
// ...then fallback to default file path
|
||||
return this.defaultFilePath(schemeFilter);
|
||||
}
|
||||
|
||||
private toNativeOpenDialogOptions(options: IPickAndOpenOptions): INativeOpenDialogOptions {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-2 -2 16 16" enable-background="new -2 -2 16 16"><polygon fill="#C5C5C5" points="9,0 4.5,9 3,6 0,6 3,12 6,12 12,0"/></svg>
|
||||
|
Before Width: | Height: | Size: 194 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{opacity:0;fill:#F6F6F6;} .icon-vs-fg{fill:#F0EFF1;} .icon-folder{fill:#656565;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 2.5v10c0 .827-.673 1.5-1.5 1.5h-11.996c-.827 0-1.5-.673-1.5-1.5v-8c0-.827.673-1.5 1.5-1.5h2.886l1-2h8.11c.827 0 1.5.673 1.5 1.5z" id="outline"/><path class="icon-folder" d="M14.5 2h-7.492l-1 2h-3.504c-.277 0-.5.224-.5.5v8c0 .276.223.5.5.5h11.996c.275 0 .5-.224.5-.5v-10c0-.276-.225-.5-.5-.5zm-.496 2h-6.496l.5-1h5.996v1z" id="iconBg"/><path class="icon-vs-fg" d="M14 3v1h-6.5l.5-1h6z" id="iconFg"/></svg>
|
||||
|
Before Width: | Height: | Size: 750 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><polygon points="5.382,13 2.382,7 6.618,7 7,7.764 9.382,3 13.618,3 8.618,13" fill="#F6F6F6"/><path d="M12 4l-4 8h-2l-2-4h2l1 2 3-6h2z" fill="#424242"/></svg>
|
||||
|
Before Width: | Height: | Size: 221 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{opacity:0;fill:#F6F6F6;} .icon-vs-fg{opacity:0;fill:#F0EFF1;} .icon-folder{fill:#C5C5C5;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 2.5v10c0 .827-.673 1.5-1.5 1.5h-11.996c-.827 0-1.5-.673-1.5-1.5v-8c0-.827.673-1.5 1.5-1.5h2.886l1-2h8.11c.827 0 1.5.673 1.5 1.5z" id="outline"/><path class="icon-folder" d="M14.5 2h-7.492l-1 2h-3.504c-.277 0-.5.224-.5.5v8c0 .276.223.5.5.5h11.996c.275 0 .5-.224.5-.5v-10c0-.276-.225-.5-.5-.5zm-.496 2h-6.496l.5-1h5.996v1z" id="iconBg"/><path class="icon-vs-fg" d="M14 3v1h-6.5l.5-1h6z" id="iconFg"/></svg>
|
||||
|
Before Width: | Height: | Size: 760 B |
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { IFileService, IFileStat, FileKind } from 'vs/platform/files/common/files';
|
||||
import { IQuickInputService, IQuickPickItem, IQuickPick, IQuickInputButton } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IQuickInputService, IQuickPickItem, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { ISaveDialogOptions, IOpenDialogOptions, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
@@ -23,20 +23,26 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { RemoteFileDialogContext } from 'vs/workbench/common/contextkeys';
|
||||
import { equalsIgnoreCase } from 'vs/base/common/strings';
|
||||
import { equalsIgnoreCase, format } from 'vs/base/common/strings';
|
||||
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
|
||||
interface FileQuickPickItem extends IQuickPickItem {
|
||||
uri: URI;
|
||||
isFolder: boolean;
|
||||
}
|
||||
|
||||
enum UpdateResult {
|
||||
Updated,
|
||||
NotUpdated,
|
||||
InvalidPath
|
||||
}
|
||||
|
||||
// Reference: https://en.wikipedia.org/wiki/Filename
|
||||
const INVALID_FILE_CHARS = isWindows ? /[\\/:\*\?"<>\|]/g : /[\\/]/g;
|
||||
const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])$/i;
|
||||
|
||||
export class RemoteFileDialog {
|
||||
private acceptButton: IQuickInputButton;
|
||||
private fallbackListItem: FileQuickPickItem | undefined;
|
||||
private options: IOpenDialogOptions;
|
||||
private currentFolder: URI;
|
||||
private filePickBox: IQuickPick<FileQuickPickItem>;
|
||||
@@ -52,6 +58,7 @@ export class RemoteFileDialog {
|
||||
private autoCompletePathSegment: string;
|
||||
private activeItem: FileQuickPickItem;
|
||||
private userHome: URI;
|
||||
private badPath: string | undefined;
|
||||
|
||||
constructor(
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@@ -64,8 +71,8 @@ export class RemoteFileDialog {
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
) {
|
||||
this.remoteAuthority = this.environmentService.configuration.remoteAuthority;
|
||||
this.contextKey = RemoteFileDialogContext.bindTo(contextKeyService);
|
||||
@@ -79,13 +86,6 @@ export class RemoteFileDialog {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
this.options = newOptions;
|
||||
|
||||
const openFileString = nls.localize('remoteFileDialog.localFileFallback', '(Open Local File)');
|
||||
const openFolderString = nls.localize('remoteFileDialog.localFolderFallback', '(Open Local Folder)');
|
||||
const openFileFolderString = nls.localize('remoteFileDialog.localFileFolderFallback', '(Open Local File or Folder)');
|
||||
let fallbackLabel = options.canSelectFiles ? (options.canSelectFolders ? openFileFolderString : openFileString) : openFolderString;
|
||||
this.fallbackListItem = this.getFallbackFileSystem(fallbackLabel);
|
||||
|
||||
return this.pickResource();
|
||||
}
|
||||
|
||||
@@ -100,7 +100,6 @@ export class RemoteFileDialog {
|
||||
this.options = newOptions;
|
||||
this.options.canSelectFolders = true;
|
||||
this.options.canSelectFiles = true;
|
||||
this.fallbackListItem = this.getFallbackFileSystem(nls.localize('remoteFileDialog.localSaveFallback', '(Save Local File)'));
|
||||
|
||||
return new Promise<URI | undefined>((resolve) => {
|
||||
this.pickResource(true).then(folderUri => {
|
||||
@@ -129,20 +128,13 @@ export class RemoteFileDialog {
|
||||
|
||||
private remoteUriFrom(path: string): URI {
|
||||
path = path.replace(/\\/g, '/');
|
||||
return resources.toLocalResource(URI.from({ scheme: this.scheme, path }), this.remoteAuthority);
|
||||
return resources.toLocalResource(URI.from({ scheme: this.scheme, path }), this.scheme === Schemas.file ? undefined : this.remoteAuthority);
|
||||
}
|
||||
|
||||
private getScheme(defaultUri: URI | undefined, available: string[] | undefined): string {
|
||||
return defaultUri ? defaultUri.scheme : (available ? available[0] : Schemas.file);
|
||||
}
|
||||
|
||||
private getFallbackFileSystem(label: string): FileQuickPickItem | undefined {
|
||||
if (this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
|
||||
return { label: label, uri: URI.from({ scheme: this.options.availableFileSystems[1] }), isFolder: true };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async getUserHome(): Promise<URI> {
|
||||
if (this.scheme !== Schemas.file) {
|
||||
const env = await this.remoteAgentService.getEnvironment();
|
||||
@@ -182,33 +174,34 @@ export class RemoteFileDialog {
|
||||
}
|
||||
}
|
||||
}
|
||||
this.acceptButton = { iconPath: this.getDialogIcons('accept'), tooltip: this.options.title };
|
||||
|
||||
return new Promise<URI | undefined>(async (resolve) => {
|
||||
this.filePickBox = this.quickInputService.createQuickPick<FileQuickPickItem>();
|
||||
this.filePickBox.matchOnLabel = false;
|
||||
this.filePickBox.autoFocusOnList = false;
|
||||
this.filePickBox.ok = true;
|
||||
if (this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
|
||||
this.filePickBox.customButton = true;
|
||||
this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
|
||||
const action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderAction : OpenLocalFileAction) : OpenLocalFolderAction;
|
||||
const keybinding = this.keybindingService.lookupKeybinding(action.ID);
|
||||
if (keybinding) {
|
||||
const label = keybinding.getLabel();
|
||||
if (label) {
|
||||
this.filePickBox.customHover = format('{0} ({1})', action.LABEL, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let isResolving = false;
|
||||
let isAcceptHandled = false;
|
||||
this.currentFolder = homedir;
|
||||
this.userEnteredPathSegment = '';
|
||||
this.autoCompletePathSegment = '';
|
||||
this.filePickBox.buttons = [this.acceptButton];
|
||||
this.filePickBox.onDidTriggerButton(_ => {
|
||||
// accept button
|
||||
const resolveValue = this.addPostfix(this.remoteUriFrom(this.filePickBox.value));
|
||||
this.validate(resolveValue).then(validated => {
|
||||
if (validated) {
|
||||
isResolving = true;
|
||||
this.filePickBox.hide();
|
||||
doResolve(this, resolveValue);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.filePickBox.title = this.options.title;
|
||||
this.filePickBox.value = this.pathFromUri(this.currentFolder);
|
||||
this.filePickBox.value = this.pathFromUri(this.currentFolder, true);
|
||||
this.filePickBox.valueSelection = [this.filePickBox.value.length, this.filePickBox.value.length];
|
||||
this.filePickBox.items = [];
|
||||
|
||||
function doResolve(dialog: RemoteFileDialog, uri: URI | undefined) {
|
||||
@@ -217,6 +210,28 @@ export class RemoteFileDialog {
|
||||
dialog.filePickBox.dispose();
|
||||
}
|
||||
|
||||
this.filePickBox.onDidCustom(() => {
|
||||
if (isAcceptHandled || this.filePickBox.busy) {
|
||||
return undefined; // {{SQL CARBON EDIT}} @todo anthonydresser return to return; when we do strict null checks
|
||||
}
|
||||
|
||||
isAcceptHandled = true;
|
||||
isResolving = true;
|
||||
if (this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
|
||||
this.options.availableFileSystems.shift();
|
||||
}
|
||||
this.options.defaultUri = undefined;
|
||||
if (this.requiresTrailing) {
|
||||
return this.fileDialogService.showSaveDialog(this.options).then(result => {
|
||||
doResolve(this, result);
|
||||
});
|
||||
} else {
|
||||
return this.fileDialogService.showOpenDialog(this.options).then(result => {
|
||||
doResolve(this, result ? result[0] : undefined);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.filePickBox.onDidAccept(_ => {
|
||||
if (isAcceptHandled || this.filePickBox.busy) {
|
||||
return;
|
||||
@@ -247,15 +262,16 @@ export class RemoteFileDialog {
|
||||
this.filePickBox.onDidChangeValue(async value => {
|
||||
// onDidChangeValue can also be triggered by the auto complete, so if it looks like the auto complete, don't do anything
|
||||
if (this.isChangeFromUser()) {
|
||||
if (value !== this.constructFullUserPath()) {
|
||||
// If the user has just entered more bad path, don't change anything
|
||||
if (value !== this.constructFullUserPath() && !this.isBadSubpath(value)) {
|
||||
this.filePickBox.validationMessage = undefined;
|
||||
this.shouldOverwriteFile = false;
|
||||
const valueUri = this.remoteUriFrom(this.trimTrailingSlash(this.filePickBox.value));
|
||||
let isUpdate = false;
|
||||
let updated: UpdateResult = UpdateResult.NotUpdated;
|
||||
if (!resources.isEqual(this.remoteUriFrom(this.trimTrailingSlash(this.pathFromUri(this.currentFolder))), valueUri, true)) {
|
||||
isUpdate = await this.tryUpdateItems(value, this.remoteUriFrom(this.filePickBox.value));
|
||||
updated = await this.tryUpdateItems(value, this.remoteUriFrom(this.filePickBox.value));
|
||||
}
|
||||
if (!isUpdate) {
|
||||
if (updated === UpdateResult.NotUpdated) {
|
||||
this.setActiveItems(value);
|
||||
}
|
||||
} else {
|
||||
@@ -281,6 +297,10 @@ export class RemoteFileDialog {
|
||||
});
|
||||
}
|
||||
|
||||
private isBadSubpath(value: string) {
|
||||
return this.badPath && (value.length > this.badPath.length) && equalsIgnoreCase(value.substring(0, this.badPath.length), this.badPath);
|
||||
}
|
||||
|
||||
private isChangeFromUser(): boolean {
|
||||
if ((this.filePickBox.value === this.pathAppend(this.currentFolder, this.userEnteredPathSegment + this.autoCompletePathSegment))
|
||||
&& (this.activeItem === (this.filePickBox.activeItems ? this.filePickBox.activeItems[0] : undefined))) {
|
||||
@@ -294,24 +314,6 @@ export class RemoteFileDialog {
|
||||
}
|
||||
|
||||
private async onDidAccept(): Promise<URI | undefined> {
|
||||
// Check if Open Local has been selected
|
||||
const selectedItems: ReadonlyArray<FileQuickPickItem> = this.filePickBox.selectedItems;
|
||||
if (selectedItems && (selectedItems.length > 0) && (selectedItems[0] === this.fallbackListItem)) {
|
||||
if (this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
|
||||
this.options.availableFileSystems.shift();
|
||||
}
|
||||
this.options.defaultUri = undefined;
|
||||
if (this.requiresTrailing) {
|
||||
return this.fileDialogService.showSaveDialog(this.options).then(result => {
|
||||
return result;
|
||||
});
|
||||
} else {
|
||||
return this.fileDialogService.showOpenDialog(this.options).then(result => {
|
||||
return result ? result[0] : undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let resolveValue: URI | undefined;
|
||||
let navigateValue: URI | undefined;
|
||||
const trimmedPickBoxValue = ((this.filePickBox.value.length > 1) && this.endsWithSlash(this.filePickBox.value)) ? this.filePickBox.value.substr(0, this.filePickBox.value.length - 1) : this.filePickBox.value;
|
||||
@@ -360,10 +362,11 @@ export class RemoteFileDialog {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private async tryUpdateItems(value: string, valueUri: URI): Promise<boolean> {
|
||||
private async tryUpdateItems(value: string, valueUri: URI): Promise<UpdateResult> {
|
||||
if (value[value.length - 1] === '~') {
|
||||
await this.updateItems(this.userHome);
|
||||
return true;
|
||||
this.badPath = undefined;
|
||||
return UpdateResult.Updated;
|
||||
} else if (this.endsWithSlash(value) || (!resources.isEqual(this.currentFolder, resources.dirname(valueUri), true) && resources.isEqualOrParent(this.currentFolder, resources.dirname(valueUri), true))) {
|
||||
let stat: IFileStat | undefined;
|
||||
try {
|
||||
@@ -373,7 +376,14 @@ export class RemoteFileDialog {
|
||||
}
|
||||
if (stat && stat.isDirectory && (resources.basename(valueUri) !== '.') && this.endsWithSlash(value)) {
|
||||
await this.updateItems(valueUri);
|
||||
return true;
|
||||
return UpdateResult.Updated;
|
||||
} else if (this.endsWithSlash(value)) {
|
||||
// The input box contains a path that doesn't exist on the system.
|
||||
this.filePickBox.validationMessage = nls.localize('remoteFileDialog.badPath', 'The path does not exist.');
|
||||
// Save this bad path. It can take too long to to a stat on every user entered character, but once a user enters a bad path they are likely
|
||||
// to keep typing more bad path. We can compare against this bad path and see if the user entered path starts with it.
|
||||
this.badPath = value;
|
||||
return UpdateResult.InvalidPath;
|
||||
} else {
|
||||
const inputUriDirname = resources.dirname(valueUri);
|
||||
if (!resources.isEqual(this.remoteUriFrom(this.trimTrailingSlash(this.pathFromUri(this.currentFolder))), inputUriDirname, true)) {
|
||||
@@ -385,12 +395,14 @@ export class RemoteFileDialog {
|
||||
}
|
||||
if (statWithoutTrailing && statWithoutTrailing.isDirectory && (resources.basename(valueUri) !== '.')) {
|
||||
await this.updateItems(inputUriDirname, resources.basename(valueUri));
|
||||
return true;
|
||||
this.badPath = undefined;
|
||||
return UpdateResult.Updated;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
this.badPath = undefined;
|
||||
return UpdateResult.NotUpdated;
|
||||
}
|
||||
|
||||
private setActiveItems(value: string) {
|
||||
@@ -428,7 +440,7 @@ export class RemoteFileDialog {
|
||||
this.autoCompletePathSegment = '';
|
||||
return false;
|
||||
}
|
||||
const itemBasename = (quickPickItem.label === '..') ? quickPickItem.label : resources.basename(quickPickItem.uri);
|
||||
const itemBasename = quickPickItem.label;
|
||||
// Either force the autocomplete, or the old value should be one smaller than the new value and match the new value.
|
||||
if (!force && (itemBasename.length >= startingBasename.length) && equalsIgnoreCase(itemBasename.substr(0, startingBasename.length), startingBasename)) {
|
||||
this.userEnteredPathSegment = startingBasename;
|
||||
@@ -582,8 +594,11 @@ export class RemoteFileDialog {
|
||||
if (this.allowFolderSelection) {
|
||||
this.filePickBox.activeItems = [];
|
||||
}
|
||||
this.filePickBox.valueSelection = [0, this.filePickBox.value.length];
|
||||
this.insertText(newValue, newValue);
|
||||
if (!equalsIgnoreCase(this.filePickBox.value, newValue)) {
|
||||
this.filePickBox.valueSelection = [0, this.filePickBox.value.length];
|
||||
this.insertText(newValue, newValue);
|
||||
}
|
||||
this.filePickBox.valueSelection = [this.filePickBox.value.length, this.filePickBox.value.length];
|
||||
this.filePickBox.busy = false;
|
||||
});
|
||||
}
|
||||
@@ -687,10 +702,6 @@ export class RemoteFileDialog {
|
||||
if (backDir) {
|
||||
sorted.unshift(backDir);
|
||||
}
|
||||
|
||||
if (this.fallbackListItem) {
|
||||
sorted.push(this.fallbackListItem);
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
|
||||
@@ -724,11 +735,4 @@ export class RemoteFileDialog {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private getDialogIcons(name: string): { light: URI, dark: URI } {
|
||||
return {
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/services/dialogs/browser/media/dark/${name}.svg`)),
|
||||
light: URI.parse(require.toUrl(`vs/workbench/services/dialogs/browser/media/light/${name}.svg`))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/c
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IMessage } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { values } from 'vs/base/common/map';
|
||||
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
const schemaRegistry = Registry.as<IJSONContributionRegistry>(Extensions.JSONContribution);
|
||||
export type ExtensionKind = 'workspace' | 'ui' | undefined;
|
||||
|
||||
@@ -370,18 +370,14 @@ export interface IExtensionPointDescriptor {
|
||||
|
||||
export class ExtensionsRegistryImpl {
|
||||
|
||||
private _extensionPoints: { [extPoint: string]: ExtensionPoint<any>; };
|
||||
|
||||
constructor() {
|
||||
this._extensionPoints = {};
|
||||
}
|
||||
private readonly _extensionPoints = new Map<string, ExtensionPoint<any>>();
|
||||
|
||||
public registerExtensionPoint<T>(desc: IExtensionPointDescriptor): IExtensionPoint<T> {
|
||||
if (hasOwnProperty.call(this._extensionPoints, desc.extensionPoint)) {
|
||||
if (this._extensionPoints.has(desc.extensionPoint)) {
|
||||
throw new Error('Duplicate extension point: ' + desc.extensionPoint);
|
||||
}
|
||||
let result = new ExtensionPoint<T>(desc.extensionPoint, desc.defaultExtensionKind);
|
||||
this._extensionPoints[desc.extensionPoint] = result;
|
||||
const result = new ExtensionPoint<T>(desc.extensionPoint, desc.defaultExtensionKind);
|
||||
this._extensionPoints.set(desc.extensionPoint, result);
|
||||
|
||||
schema.properties['contributes'].properties[desc.extensionPoint] = desc.jsonSchema;
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
@@ -390,11 +386,7 @@ export class ExtensionsRegistryImpl {
|
||||
}
|
||||
|
||||
public getExtensionPoints(): ExtensionPoint<any>[] {
|
||||
return Object.keys(this._extensionPoints).map(point => this._extensionPoints[point]);
|
||||
}
|
||||
|
||||
public getExtensionPointsMap(): { [extPoint: string]: ExtensionPoint<any>; } {
|
||||
return this._extensionPoints;
|
||||
return values(this._extensionPoints);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { Dialog } from 'vs/base/browser/ui/dialog/dialog';
|
||||
import { attachDialogStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { EventHelper } from 'vs/base/browser/dom';
|
||||
|
||||
export class ProgressService2 implements IProgressService2 {
|
||||
|
||||
@@ -34,7 +37,8 @@ export class ProgressService2 implements IProgressService2 {
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IStatusbarService private readonly _statusbarService: IStatusbarService,
|
||||
@ILayoutService private readonly _layoutService: ILayoutService,
|
||||
@IThemeService private readonly _themeService: IThemeService
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService
|
||||
) { }
|
||||
|
||||
withProgress<R = unknown>(options: IProgressOptions, task: (progress: IProgress<IProgressStep>) => Promise<R>, onDidCancel?: () => void): Promise<R> {
|
||||
@@ -276,6 +280,10 @@ export class ProgressService2 implements IProgressService2 {
|
||||
|
||||
private _withDialogProgress<P extends Promise<R>, R = unknown>(options: IProgressOptions, task: (progress: IProgress<{ message?: string, increment?: number }>) => P, onDidCancel?: () => void): P {
|
||||
const disposables: IDisposable[] = [];
|
||||
const allowableCommands = [
|
||||
'workbench.action.quit',
|
||||
'workbench.action.reloadWindow'
|
||||
];
|
||||
|
||||
let dialog: Dialog;
|
||||
|
||||
@@ -284,7 +292,17 @@ export class ProgressService2 implements IProgressService2 {
|
||||
this._layoutService.container,
|
||||
message,
|
||||
[options.cancellable ? localize('cancel', "Cancel") : localize('dismiss', "Dismiss")],
|
||||
{ type: 'pending' }
|
||||
{
|
||||
type: 'pending',
|
||||
keyEventProcessor: (event: StandardKeyboardEvent) => {
|
||||
const resolved = this._keybindingService.softDispatch(event, this._layoutService.container);
|
||||
if (resolved && resolved.commandId) {
|
||||
if (allowableCommands.indexOf(resolved.commandId) === -1) {
|
||||
EventHelper.stop(event, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
disposables.push(dialog);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Client } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { connectRemoteAgentManagement, IConnectionOptions, IWebSocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { connectRemoteAgentManagement, IConnectionOptions, IWebSocketFactory, PersistenConnectionEvent } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { IRemoteAgentConnection, IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
@@ -73,15 +73,18 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
|
||||
private readonly _onReconnecting = this._register(new Emitter<void>());
|
||||
public readonly onReconnecting = this._onReconnecting.event;
|
||||
|
||||
private readonly _onDidStateChange = this._register(new Emitter<PersistenConnectionEvent>());
|
||||
public readonly onDidStateChange = this._onDidStateChange.event;
|
||||
|
||||
readonly remoteAuthority: string;
|
||||
private _connection: Promise<Client<RemoteAgentConnectionContext>> | null;
|
||||
|
||||
constructor(
|
||||
remoteAuthority: string,
|
||||
private _commit: string | undefined,
|
||||
private _webSocketFactory: IWebSocketFactory,
|
||||
private _environmentService: IEnvironmentService,
|
||||
private _remoteAuthorityResolverService: IRemoteAuthorityResolverService
|
||||
private readonly _commit: string | undefined,
|
||||
private readonly _webSocketFactory: IWebSocketFactory,
|
||||
private readonly _environmentService: IEnvironmentService,
|
||||
private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService
|
||||
) {
|
||||
super();
|
||||
this.remoteAuthority = remoteAuthority;
|
||||
@@ -121,8 +124,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
|
||||
}
|
||||
}
|
||||
};
|
||||
const connection = await connectRemoteAgentManagement(options, this.remoteAuthority, `renderer`);
|
||||
this._register(connection);
|
||||
const connection = this._register(await connectRemoteAgentManagement(options, this.remoteAuthority, `renderer`));
|
||||
this._register(connection.onDidStateChange(e => this._onDidStateChange.fire(e)));
|
||||
return connection.client;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { RemoteAgentConnectionContext, IRemoteAgentEnvironment } from 'vs/platfo
|
||||
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnosticsService';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { PersistenConnectionEvent } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
|
||||
export const RemoteExtensionLogFileName = 'remoteagent';
|
||||
|
||||
@@ -25,7 +26,9 @@ export interface IRemoteAgentService {
|
||||
export interface IRemoteAgentConnection {
|
||||
readonly remoteAuthority: string;
|
||||
|
||||
readonly onReconnecting: Event<void>;
|
||||
readonly onDidStateChange: Event<PersistenConnectionEvent>;
|
||||
|
||||
getChannel<T extends IChannel>(channelName: string): T;
|
||||
registerChannel<T extends IServerChannel<RemoteAgentConnectionContext>>(channelName: string, channel: T): void;
|
||||
onReconnecting: Event<void>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user