Allow creating multiple files or attachments on paste (#181975)

This commit is contained in:
Matt Bierner
2023-05-09 17:20:37 -07:00
committed by GitHub
parent bbc33498b3
commit 83c12a2da2
3 changed files with 102 additions and 54 deletions

View File

@@ -4,13 +4,17 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { coalesce } from '../../util/arrays';
import { Schemes } from '../../util/schemes';
import { getNewFileName } from './copyFiles';
import { NewFilePathGenerator } from './copyFiles';
import { createUriListSnippet, tryGetUriListSnippet } from './dropIntoEditor';
const supportedImageMimes = new Set([
'image/bmp',
'image/gif',
'image/jpeg',
'image/png',
'image/jpg',
'image/webp',
]);
class PasteEditProvider implements vscode.DocumentPasteEditProvider {
@@ -26,53 +30,63 @@ class PasteEditProvider implements vscode.DocumentPasteEditProvider {
return;
}
for (const imageMime of supportedImageMimes) {
const item = dataTransfer.get(imageMime);
const file = item?.asFile();
if (item && file) {
const edit = await this._makeCreateImagePasteEdit(document, file, token);
if (token.isCancellationRequested) {
return;
}
if (edit) {
return edit;
}
}
const edit = await this._makeCreateImagePasteEdit(document, dataTransfer, token);
if (edit) {
return edit;
}
const snippet = await tryGetUriListSnippet(document, dataTransfer, token);
return snippet ? new vscode.DocumentPasteEdit(snippet.snippet, snippet.label) : undefined;
}
private async _makeCreateImagePasteEdit(document: vscode.TextDocument, file: vscode.DataTransferFile, token: vscode.CancellationToken): Promise<vscode.DocumentPasteEdit | undefined> {
private async _makeCreateImagePasteEdit(document: vscode.TextDocument, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.DocumentPasteEdit | undefined> {
if (document.uri.scheme === Schemes.untitled) {
return undefined;
return;
}
if (file.uri) {
// If file is already in workspace, we don't want to create a copy of it
const workspaceFolder = vscode.workspace.getWorkspaceFolder(file.uri);
if (workspaceFolder) {
const snippet = createUriListSnippet(document, [file.uri]);
return snippet ? new vscode.DocumentPasteEdit(snippet.snippet, snippet.label) : undefined;
interface FileEntry {
readonly uri: vscode.Uri;
readonly newFileContents?: vscode.DataTransferFile;
}
const pathGenerator = new NewFilePathGenerator();
const fileEntries = coalesce(await Promise.all(Array.from(dataTransfer, async ([mime, item]): Promise<FileEntry | undefined> => {
if (!supportedImageMimes.has(mime)) {
return;
}
const file = item?.asFile();
if (!file) {
return;
}
if (file.uri) {
// If the file is already in a workspace, we don't want to create a copy of it
const workspaceFolder = vscode.workspace.getWorkspaceFolder(file.uri);
if (workspaceFolder) {
return { uri: file.uri };
}
}
const uri = await pathGenerator.getNewFilePath(document, file, token);
return uri ? { uri, newFileContents: file } : undefined;
})));
if (!fileEntries.length) {
return;
}
const workspaceEdit = new vscode.WorkspaceEdit();
for (const entry of fileEntries) {
if (entry.newFileContents) {
workspaceEdit.createFile(entry.uri, { contents: entry.newFileContents });
}
}
const uri = await getNewFileName(document, file);
if (token.isCancellationRequested) {
return;
}
const snippet = createUriListSnippet(document, [uri]);
const snippet = createUriListSnippet(document, fileEntries.map(entry => entry.uri));
if (!snippet) {
return;
}
// Note that there is currently no way to undo the file creation :/
const workspaceEdit = new vscode.WorkspaceEdit();
workspaceEdit.createFile(uri, { contents: file });
const pasteEdit = new vscode.DocumentPasteEdit(snippet.snippet, snippet.label);
pasteEdit.additionalEdit = workspaceEdit;
return pasteEdit;