提交 ba5c3150 编写于 作者: B Benjamin Pasero

multi select - add and use distinctParents method to avoid duplicates

上级 c19a86f9
......@@ -12,9 +12,9 @@ export function basenameOrAuthority(resource: uri): string {
return paths.basename(resource.fsPath) || resource.authority;
}
export function isEqualOrParent(first: uri, second: uri, ignoreCase?: boolean): boolean {
if (first.scheme === second.scheme && first.authority === second.authority) {
return paths.isEqualOrParent(first.fsPath, second.fsPath, ignoreCase);
export function isEqualOrParent(resource: uri, candidate: uri, ignoreCase?: boolean): boolean {
if (resource.scheme === candidate.scheme && resource.authority === candidate.authority) {
return paths.isEqualOrParent(resource.fsPath, candidate.fsPath, ignoreCase);
}
return false;
......@@ -42,3 +42,23 @@ export function dirname(resource: uri): uri {
path: paths.dirname(resource.path)
});
}
export function distinctParents<T>(items: T[], resourceAccessor: (item: T) => uri): T[] {
const distinctParents: T[] = [];
for (let i = 0; i < items.length; i++) {
const candidateResource = resourceAccessor(items[i]);
if (items.some((otherItem, index) => {
if (index === i) {
return false;
}
return isEqualOrParent(candidateResource, resourceAccessor(otherItem));
})) {
continue;
}
distinctParents.push(items[i]);
}
return distinctParents;
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 * as assert from 'assert';
import URI from 'vs/base/common/uri';
import { distinctParents } from 'vs/base/common/resources';
suite('Resources', () => {
test('distinctParents', () => {
// Basic
let resources = [
URI.file('/some/folderA/file.txt'),
URI.file('/some/folderB/file.txt'),
URI.file('/some/folderC/file.txt')
];
let distinct = distinctParents(resources, r => r);
assert.equal(distinct.length, 3);
assert.equal(distinct[0].toString(), resources[0].toString());
assert.equal(distinct[1].toString(), resources[1].toString());
assert.equal(distinct[2].toString(), resources[2].toString());
// Parent / Child
resources = [
URI.file('/some/folderA'),
URI.file('/some/folderA/file.txt'),
URI.file('/some/folderA/child/file.txt'),
URI.file('/some/folderA2/file.txt'),
URI.file('/some/file.txt')
];
distinct = distinctParents(resources, r => r);
assert.equal(distinct.length, 3);
assert.equal(distinct[0].toString(), resources[0].toString());
assert.equal(distinct[1].toString(), resources[3].toString());
assert.equal(distinct[2].toString(), resources[4].toString());
});
});
\ No newline at end of file
......@@ -51,6 +51,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IListService, ListWidget } from 'vs/platform/list/browser/listService';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { distinctParents } from 'vs/base/common/resources';
export interface IEditableData {
action: IAction;
......@@ -659,14 +660,16 @@ class BaseDeleteFileAction extends BaseFileAction {
primaryButton = nls.localize({ key: 'deleteButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Delete");
}
const distinctElements = distinctParents(this.elements, e => e.resource);
// Handle dirty
let confirmDirtyPromise: TPromise<boolean> = TPromise.as(true);
const dirty = this.textFileService.getDirty().filter(d => this.elements.some(e => resources.isEqualOrParent(d, e.resource, !isLinux /* ignorecase */)));
const dirty = this.textFileService.getDirty().filter(d => distinctElements.some(e => resources.isEqualOrParent(d, e.resource, !isLinux /* ignorecase */)));
if (dirty.length) {
let message: string;
if (this.elements.length > 1) {
if (distinctElements.length > 1) {
message = nls.localize('dirtyMessageFilesDelete', "You are deleting files with unsaved changes. Do you want to continue?");
} else if (this.elements[0].isDirectory) {
} else if (distinctElements[0].isDirectory) {
if (dirty.length === 1) {
message = nls.localize('dirtyMessageFolderOneDelete', "You are deleting a folder with unsaved changes in 1 file. Do you want to continue?");
} else {
......@@ -706,9 +709,9 @@ class BaseDeleteFileAction extends BaseFileAction {
// Confirm for moving to trash
else if (this.useTrash) {
const message = this.elements.length > 1 ? getConfirmMessage(nls.localize('confirmMoveTrashMessageMultiple', "Are you sure you want to delete the following {0} files?", this.elements.length), this.elements.map(e => e.resource))
: this.elements[0].isDirectory ? nls.localize('confirmMoveTrashMessageFolder', "Are you sure you want to delete '{0}' and its contents?", this.elements[0].name)
: nls.localize('confirmMoveTrashMessageFile', "Are you sure you want to delete '{0}'?", this.elements[0].name);
const message = distinctElements.length > 1 ? getConfirmMessage(nls.localize('confirmMoveTrashMessageMultiple', "Are you sure you want to delete the following {0} files?", distinctElements.length), distinctElements.map(e => e.resource))
: distinctElements[0].isDirectory ? nls.localize('confirmMoveTrashMessageFolder', "Are you sure you want to delete '{0}' and its contents?", distinctElements[0].name)
: nls.localize('confirmMoveTrashMessageFile', "Are you sure you want to delete '{0}'?", distinctElements[0].name);
confirmDeletePromise = this.messageService.confirmWithCheckbox({
message,
detail: isWindows ? nls.localize('undoBin', "You can restore from the recycle bin.") : nls.localize('undoTrash', "You can restore from the trash."),
......@@ -722,9 +725,9 @@ class BaseDeleteFileAction extends BaseFileAction {
// Confirm for deleting permanently
else {
const message = this.elements.length > 1 ? getConfirmMessage(nls.localize('confirmDeleteMessageMultiple', "Are you sure you want to permanently delete the following {0} files?", this.elements.length), this.elements.map(e => e.resource))
: this.elements[0].isDirectory ? nls.localize('confirmDeleteMessageFolder', "Are you sure you want to permanently delete '{0}' and its contents?", this.elements[0].name)
: nls.localize('confirmDeleteMessageFile', "Are you sure you want to permanently delete '{0}'?", this.elements[0].name);
const message = distinctElements.length > 1 ? getConfirmMessage(nls.localize('confirmDeleteMessageMultiple', "Are you sure you want to permanently delete the following {0} files?", distinctElements.length), distinctElements.map(e => e.resource))
: distinctElements[0].isDirectory ? nls.localize('confirmDeleteMessageFolder', "Are you sure you want to permanently delete '{0}' and its contents?", distinctElements[0].name)
: nls.localize('confirmDeleteMessageFile', "Are you sure you want to permanently delete '{0}'?", distinctElements[0].name);
confirmDeletePromise = this.messageService.confirmWithCheckbox({
message,
detail: nls.localize('irreversible', "This action is irreversible!"),
......@@ -749,21 +752,20 @@ class BaseDeleteFileAction extends BaseFileAction {
}
// Call function
const servicePromise = TPromise.join(this.elements.map(e => this.fileService.del(e.resource, this.useTrash))).then(() => {
if (this.elements[0].parent) {
this.tree.setFocus(this.elements[0].parent); // move focus to parent
const servicePromise = TPromise.join(distinctElements.map(e => this.fileService.del(e.resource, this.useTrash))).then(() => {
if (distinctElements[0].parent) {
this.tree.setFocus(distinctElements[0].parent); // move focus to parent
}
}, (error: any) => {
if (this.elements.length === 1) {
// Allow to retry
let extraAction: Action;
if (this.useTrash) {
extraAction = new Action('permanentDelete', nls.localize('permDelete', "Delete Permanently"), null, true, () => { this.useTrash = false; this.skipConfirm = true; return this.run(); });
}
this.onErrorWithRetry(error, () => this.run(), extraAction);
// Allow to retry
let extraAction: Action;
if (this.useTrash) {
extraAction = new Action('permanentDelete', nls.localize('permDelete', "Delete Permanently"), null, true, () => { this.useTrash = false; this.skipConfirm = true; return this.run(); });
}
this.onErrorWithRetry(error, () => this.run(), extraAction);
// Focus back to tree
this.tree.DOMFocus();
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册