mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-11 18:48:33 -05:00
Merge from vscode 591842cc4b71958c81947b254924a215fe3edcbd (#4886)
This commit is contained in:
@@ -110,10 +110,13 @@ export class RemoteFileDialog {
|
||||
let defaultUri = options.defaultUri;
|
||||
const filename = (defaultUri && isSave && (resources.dirname(defaultUri).path === '/')) ? resources.basename(defaultUri) : undefined;
|
||||
if (!defaultUri || filename) {
|
||||
const env = await this.remoteAgentService.getEnvironment();
|
||||
if (env) {
|
||||
defaultUri = env.userHome;
|
||||
} else {
|
||||
if (this.scheme !== Schemas.file) {
|
||||
const env = await this.remoteAgentService.getEnvironment();
|
||||
if (env) {
|
||||
defaultUri = env.userHome;
|
||||
}
|
||||
}
|
||||
if (!defaultUri) {
|
||||
defaultUri = URI.from({ scheme: this.scheme, path: this.environmentService.userHome });
|
||||
}
|
||||
if (filename) {
|
||||
@@ -192,7 +195,7 @@ export class RemoteFileDialog {
|
||||
if (validated) {
|
||||
isResolving = true;
|
||||
this.filePickBox.hide();
|
||||
resolve(resolveValue);
|
||||
doResolve(this, resolveValue);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -200,6 +203,13 @@ export class RemoteFileDialog {
|
||||
this.filePickBox.title = this.options.title;
|
||||
this.filePickBox.value = this.pathFromUri(this.currentFolder);
|
||||
this.filePickBox.items = [];
|
||||
|
||||
function doResolve(dialog: RemoteFileDialog, uri: URI | undefined) {
|
||||
resolve(uri);
|
||||
dialog.contextKey.set(false);
|
||||
dialog.filePickBox.dispose();
|
||||
}
|
||||
|
||||
this.filePickBox.onDidAccept(_ => {
|
||||
if (isAcceptHandled || this.filePickBox.busy) {
|
||||
return;
|
||||
@@ -210,9 +220,9 @@ export class RemoteFileDialog {
|
||||
this.onDidAccept().then(resolveValue => {
|
||||
if (resolveValue) {
|
||||
this.filePickBox.hide();
|
||||
resolve(resolveValue);
|
||||
doResolve(this, resolveValue);
|
||||
} else if (this.hidden) {
|
||||
resolve(undefined);
|
||||
doResolve(this, undefined);
|
||||
} else {
|
||||
isResolving = false;
|
||||
isAcceptHandled = false;
|
||||
@@ -221,6 +231,10 @@ export class RemoteFileDialog {
|
||||
});
|
||||
this.filePickBox.onDidChangeActive(i => {
|
||||
isAcceptHandled = false;
|
||||
// update input box to match the first selected item
|
||||
if (i.length === 1) {
|
||||
this.setAutoComplete(this.userValue, resources.basename(this.remoteUriFrom(this.userValue)), i[0], true);
|
||||
}
|
||||
});
|
||||
|
||||
this.filePickBox.onDidChangeValue(async value => {
|
||||
@@ -229,13 +243,11 @@ export class RemoteFileDialog {
|
||||
if (value !== this.userValue) {
|
||||
this.filePickBox.validationMessage = undefined;
|
||||
this.shouldOverwriteFile = false;
|
||||
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;
|
||||
const valueUri = this.remoteUriFrom(trimmedPickBoxValue);
|
||||
if (!resources.isEqual(this.currentFolder, valueUri, true)) {
|
||||
const valueUri = this.remoteUriFrom(this.trimTrailingSlash(this.filePickBox.value));
|
||||
if (!resources.isEqual(this.remoteUriFrom(this.trimTrailingSlash(this.pathFromUri(this.currentFolder))), valueUri, true)) {
|
||||
await this.tryUpdateItems(value, this.remoteUriFrom(this.filePickBox.value));
|
||||
}
|
||||
this.setActiveItems(value);
|
||||
this.userValue = value;
|
||||
} else {
|
||||
this.filePickBox.activeItems = [];
|
||||
}
|
||||
@@ -244,10 +256,8 @@ export class RemoteFileDialog {
|
||||
this.filePickBox.onDidHide(() => {
|
||||
this.hidden = true;
|
||||
if (!isResolving) {
|
||||
resolve(undefined);
|
||||
doResolve(this, undefined);
|
||||
}
|
||||
this.contextKey.set(false);
|
||||
this.filePickBox.dispose();
|
||||
});
|
||||
|
||||
this.filePickBox.show();
|
||||
@@ -361,15 +371,8 @@ export class RemoteFileDialog {
|
||||
let hasMatch = false;
|
||||
for (let i = 0; i < this.filePickBox.items.length; i++) {
|
||||
const item = <FileQuickPickItem>this.filePickBox.items[i];
|
||||
const itemBasename = (item.label === '..') ? item.label : resources.basename(item.uri);
|
||||
if ((itemBasename.length >= inputBasename.length) && (itemBasename.substr(0, inputBasename.length).toLowerCase() === inputBasename.toLowerCase())) {
|
||||
if (this.setAutoComplete(value, inputBasename, item)) {
|
||||
this.filePickBox.activeItems = [item];
|
||||
const insertValue = itemBasename.substr(inputBasename.length);
|
||||
this.autoComplete = value + insertValue;
|
||||
if (this.filePickBox.inputHasFocus()) {
|
||||
document.execCommand('insertText', false, insertValue);
|
||||
this.filePickBox.valueSelection = [value.length, this.filePickBox.value.length];
|
||||
}
|
||||
hasMatch = true;
|
||||
break;
|
||||
}
|
||||
@@ -377,6 +380,44 @@ export class RemoteFileDialog {
|
||||
if (!hasMatch) {
|
||||
this.filePickBox.activeItems = [];
|
||||
}
|
||||
} else {
|
||||
this.userValue = value;
|
||||
this.autoComplete = '';
|
||||
}
|
||||
}
|
||||
|
||||
private setAutoComplete(startingValue: string, startingBasename: string, quickPickItem: FileQuickPickItem, force: boolean = false): boolean {
|
||||
const itemBasename = (quickPickItem.label === '..') ? quickPickItem.label : resources.basename(quickPickItem.uri);
|
||||
const itemPathLabel = (itemBasename === '..') ? this.pathAppend(this.currentFolder, itemBasename) : this.pathFromUri(quickPickItem.uri);
|
||||
if (this.trimTrailingSlash(this.filePickBox.value) !== itemPathLabel) {
|
||||
// Either foce 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) && (itemBasename.substr(0, startingBasename.length).toLowerCase() === startingBasename.toLowerCase())) {
|
||||
this.userValue = startingValue;
|
||||
const autoCompleteValue = itemBasename.substr(startingBasename.length);
|
||||
this.autoComplete = startingValue + autoCompleteValue;
|
||||
this.insertText(this.autoComplete, autoCompleteValue);
|
||||
this.filePickBox.valueSelection = [startingValue.length, this.filePickBox.value.length];
|
||||
return true;
|
||||
} else if (force) {
|
||||
this.userValue = this.pathFromUri(this.currentFolder, true);
|
||||
this.autoComplete = this.pathAppend(this.currentFolder, itemBasename);
|
||||
this.filePickBox.valueSelection = [this.userValue.length, this.filePickBox.value.length];
|
||||
// use insert text to preserve undo buffer
|
||||
this.insertText(this.autoComplete, itemBasename);
|
||||
this.filePickBox.valueSelection = [this.filePickBox.value.length - itemBasename.length, this.filePickBox.value.length];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.userValue = startingValue;
|
||||
this.autoComplete = '';
|
||||
return false;
|
||||
}
|
||||
|
||||
private insertText(wholeValue: string, insertText: string) {
|
||||
if (this.filePickBox.inputHasFocus()) {
|
||||
document.execCommand('insertText', false, insertText);
|
||||
} else {
|
||||
this.filePickBox.value = wholeValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,6 +447,39 @@ export class RemoteFileDialog {
|
||||
return result;
|
||||
}
|
||||
|
||||
private trimTrailingSlash(path: string): string {
|
||||
return ((path.length > 1) && this.endsWithSlash(path)) ? path.substr(0, path.length - 1) : path;
|
||||
}
|
||||
|
||||
private yesNoPrompt(message: string): Promise<boolean> {
|
||||
interface YesNoItem extends IQuickPickItem {
|
||||
value: boolean;
|
||||
}
|
||||
const prompt = this.quickInputService.createQuickPick<YesNoItem>();
|
||||
const no = nls.localize('remoteFileDialog.no', 'No');
|
||||
prompt.items = [{ label: no, value: false }, { label: nls.localize('remoteFileDialog.yes', 'Yes'), value: true }];
|
||||
prompt.title = message;
|
||||
prompt.placeholder = no;
|
||||
let isResolving = false;
|
||||
return new Promise<boolean>(resolve => {
|
||||
prompt.onDidAccept(() => {
|
||||
isResolving = true;
|
||||
prompt.hide();
|
||||
resolve(prompt.selectedItems ? prompt.selectedItems[0].value : false);
|
||||
});
|
||||
prompt.onDidHide(() => {
|
||||
if (!isResolving) {
|
||||
resolve(false);
|
||||
}
|
||||
this.filePickBox.show();
|
||||
this.hidden = false;
|
||||
this.filePickBox.items = this.filePickBox.items;
|
||||
prompt.dispose();
|
||||
});
|
||||
prompt.show();
|
||||
});
|
||||
}
|
||||
|
||||
private async validate(uri: URI): Promise<boolean> {
|
||||
let stat: IFileStat | undefined;
|
||||
let statDirname: IFileStat | undefined;
|
||||
@@ -424,8 +498,9 @@ export class RemoteFileDialog {
|
||||
} else if (stat && !this.shouldOverwriteFile) {
|
||||
// Replacing a file.
|
||||
this.shouldOverwriteFile = true;
|
||||
this.filePickBox.validationMessage = nls.localize('remoteFileDialog.validateExisting', '{0} already exists. Are you sure you want to overwrite it?', resources.basename(uri));
|
||||
return Promise.resolve(false);
|
||||
// Show a yes/no prompt
|
||||
const message = nls.localize('remoteFileDialog.validateExisting', '{0} already exists. Are you sure you want to overwrite it?', resources.basename(uri));
|
||||
return this.yesNoPrompt(message);
|
||||
} else if (!this.isValidBaseName(resources.basename(uri))) {
|
||||
// Filename not allowed
|
||||
this.filePickBox.validationMessage = nls.localize('remoteFileDialog.validateBadFilename', 'Please enter a valid file name.');
|
||||
@@ -455,7 +530,11 @@ export class RemoteFileDialog {
|
||||
|
||||
private updateItems(newFolder: URI, trailing?: string) {
|
||||
this.currentFolder = newFolder;
|
||||
this.filePickBox.value = trailing ? this.pathFromUri(resources.joinPath(newFolder, trailing)) : this.pathFromUri(newFolder, true);
|
||||
this.userValue = this.pathFromUri(newFolder);
|
||||
this.autoComplete = '';
|
||||
this.filePickBox.valueSelection = [0, this.filePickBox.value.length];
|
||||
const newValue = trailing ? this.pathFromUri(resources.joinPath(newFolder, trailing)) : this.pathFromUri(newFolder, true);
|
||||
this.insertText(newValue, newValue);
|
||||
this.filePickBox.busy = true;
|
||||
this.createItems(this.currentFolder).then(items => {
|
||||
this.filePickBox.items = items;
|
||||
@@ -480,6 +559,14 @@ export class RemoteFileDialog {
|
||||
return result;
|
||||
}
|
||||
|
||||
private pathAppend(uri: URI, additional: string): string {
|
||||
if (additional === '..') {
|
||||
return this.pathFromUri(uri) + this.labelService.getSeparator(uri.scheme, uri.authority) + additional;
|
||||
} else {
|
||||
return this.pathFromUri(resources.joinPath(uri, additional));
|
||||
}
|
||||
}
|
||||
|
||||
private isValidBaseName(name: string): boolean {
|
||||
if (!name || name.length === 0 || /^\s+$/.test(name)) {
|
||||
return false; // require a name that is not just whitespace
|
||||
|
||||
Reference in New Issue
Block a user