Explorer: allow to drag and drop files between windows to copy them over (fixes #43307)

This commit is contained in:
Benjamin Pasero 2018-02-09 12:09:50 +01:00
parent 38ab734646
commit c761649fa4
3 changed files with 37 additions and 11 deletions

View file

@ -50,10 +50,15 @@ export const DataTransfers = {
RESOURCES: 'ResourceURLs',
/**
* Browser specific transfer type to download.
* Browser specific transfer type to download
*/
DOWNLOAD_URL: 'DownloadURL',
/**
* Browser specific transfer type for files
*/
FILES: 'Files',
/**
* Typicaly transfer type for copy/paste transfers.
*/

View file

@ -60,7 +60,8 @@ export interface ISerializedDraggedEditor {
}
export const CodeDataTransfers = {
EDITORS: 'CodeEditors'
EDITORS: 'CodeEditors',
FILES: 'CodeFiles'
};
export function extractResources(e: DragEvent, externalOnly?: boolean): (IDraggedResource | IDraggedEditor)[] {
@ -79,7 +80,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): (IDragge
resources.push({ resource: URI.parse(draggedEditor.resource), backupResource: URI.parse(draggedEditor.backupResource), viewState: draggedEditor.viewState, isExternal: false });
});
} catch (error) {
// Invalid URI
// Invalid transfer
}
}
@ -92,7 +93,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): (IDragge
resources.push(...uriStrArray.map(uriStr => ({ resource: URI.parse(uriStr), isExternal: false })));
}
} catch (error) {
// Invalid Resources
// Invalid transfer
}
}
}
@ -101,7 +102,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): (IDragge
if (e.dataTransfer && e.dataTransfer.files) {
for (let i = 0; i < e.dataTransfer.files.length; i++) {
const file = e.dataTransfer.files[i] as { path: string };
if (file && file.path) {
if (file && file.path && !resources.some(r => r.resource.fsPath === file.path) /* prevent duplicates */) {
try {
resources.push({ resource: URI.file(file.path), isExternal: true });
} catch (error) {
@ -110,6 +111,21 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): (IDragge
}
}
}
// Check for CodeFiles transfer
const rawCodeFiles = e.dataTransfer.getData(CodeDataTransfers.FILES);
if (rawCodeFiles) {
try {
const codeFiles = JSON.parse(rawCodeFiles) as string[];
codeFiles.forEach(codeFile => {
if (!resources.some(r => r.resource.fsPath === codeFile) /* prevent duplicates */) {
resources.push({ resource: URI.file(codeFile), isExternal: true });
}
});
} catch (error) {
// Invalid transfer
}
}
}
return resources;

View file

@ -50,11 +50,13 @@ import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { extractResources, SimpleFileResourceDragAndDrop } from 'vs/workbench/browser/dnd';
import { extractResources, SimpleFileResourceDragAndDrop, CodeDataTransfers } from 'vs/workbench/browser/dnd';
import { relative } from 'path';
import { distinctParents } from 'vs/base/common/resources';
import { WorkbenchTree, WorkbenchTreeController } from 'vs/platform/list/browser/listService';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { DataTransfers } from 'vs/base/browser/dnd';
import { Schemas } from 'vs/base/common/network';
export class FileDataSource implements IDataSource {
constructor(
@ -728,6 +730,11 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop {
// Apply some datatransfer types to allow for dragging the element outside of the application
super.onDragStart(tree, data, originalEvent);
// The only custom data transfer we set from the explorer is a file transfer
// to be able to DND between multiple code file explorers across windows
const fileResources = sources.filter(s => !s.isDirectory && s.resource.scheme === Schemas.file).map(r => r.resource.fsPath);
originalEvent.dataTransfer.setData(CodeDataTransfers.FILES, JSON.stringify(fileResources));
}
}
@ -741,15 +748,13 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop {
// Desktop DND
if (fromDesktop) {
const dragData = (<DesktopDragAndDropData>data).getData();
const types = dragData.types;
const types: string[] = originalEvent.dataTransfer.types;
const typesArray: string[] = [];
for (let i = 0; i < types.length; i++) {
typesArray.push(types[i]);
typesArray.push(types[i].toLowerCase()); // somehow the types are lowercase
}
if (typesArray.length === 0 || !typesArray.some(type => { return type === 'Files'; })) {
if (typesArray.indexOf(DataTransfers.FILES.toLowerCase()) === -1 && typesArray.indexOf(CodeDataTransfers.FILES.toLowerCase()) === -1) {
return DRAG_OVER_REJECT;
}
}