Files
vscode/src/vs/base/common/dataTransfer.ts
T
Matt BiernerandGitHub 528ee1ae3d Allow multiple entries with the same mimetype in dataTransfer (#150425)
Currently our data transfer implementation only allows a single entry of each mimeType. There can only be a single `image/gif` file for example.

However this doesn't match how the DOM apis work. If you drop multiple gifs into VS Code for example, the DataTransfer you get contains entries for each of the gifs.

This change allows us to also support DataTransfers that have multiple entries with the same mime type. Just like with the DOM, we support constructing these duplicate mime data transfers internally, but do not allow extensions to create them

As part of this change, I've also made a few clean ups:

- Add helpers for creating dataTransfer items
- Clarify when adding a data transfer item should `append` or `replace`
- Adopt some helper functions in a few more places
2022-05-25 18:29:28 -07:00

91 lines
2.4 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
export interface IDataTransferFile {
readonly name: string;
readonly uri?: URI;
data(): Promise<Uint8Array>;
}
export interface IDataTransferItem {
asString(): Thenable<string>;
asFile(): IDataTransferFile | undefined;
value: any;
}
export function createStringDataTransferItem(stringOrPromise: string | Promise<string>): IDataTransferItem {
return {
asString: async () => stringOrPromise,
asFile: () => undefined,
value: typeof stringOrPromise === 'string' ? stringOrPromise : undefined,
};
}
export function createFileDataTransferItem(fileName: string, uri: URI | undefined, data: () => Promise<Uint8Array>): IDataTransferItem {
return {
asString: async () => '',
asFile: () => ({ name: fileName, uri, data }),
value: undefined,
};
}
export class VSDataTransfer {
private readonly _entries = new Map<string, IDataTransferItem[]>();
public get size(): number {
return this._entries.size;
}
public has(mimeType: string): boolean {
return this._entries.has(this.toKey(mimeType));
}
public get(mimeType: string): IDataTransferItem | undefined {
return this._entries.get(this.toKey(mimeType))?.[0];
}
public append(mimeType: string, value: IDataTransferItem): void {
const existing = this._entries.get(mimeType);
if (existing) {
existing.push(value);
} else {
this._entries.set(this.toKey(mimeType), [value]);
}
}
public replace(mimeType: string, value: IDataTransferItem): void {
this._entries.set(this.toKey(mimeType), [value]);
}
public delete(mimeType: string) {
this._entries.delete(this.toKey(mimeType));
}
public *entries(): Iterable<[string, IDataTransferItem]> {
for (const [mine, items] of this._entries.entries()) {
for (const item of items) {
yield [mine, item];
}
}
}
public values(): Iterable<IDataTransferItem> {
return Array.from(this._entries.values()).flat();
}
public forEach(f: (value: IDataTransferItem, key: string) => void) {
for (const [mime, item] of this.entries()) {
f(item, mime);
}
}
private toKey(mimeType: string): string {
return mimeType.toLowerCase();
}
}