mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-11-11 16:24:38 +01:00
fix: pasting not working in firefox (#9947)
This commit is contained in:
@@ -324,7 +324,13 @@ import {
|
||||
isEraserActive,
|
||||
isHandToolActive,
|
||||
} from "../appState";
|
||||
import { copyTextToSystemClipboard, parseClipboard } from "../clipboard";
|
||||
import {
|
||||
copyTextToSystemClipboard,
|
||||
parseClipboard,
|
||||
parseDataTransferEvent,
|
||||
type ParsedDataTransferFile,
|
||||
} from "../clipboard";
|
||||
|
||||
import { exportCanvas, loadFromBlob } from "../data";
|
||||
import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
|
||||
import { restore, restoreElements } from "../data/restore";
|
||||
@@ -346,7 +352,6 @@ import {
|
||||
generateIdFromFile,
|
||||
getDataURL,
|
||||
getDataURL_sync,
|
||||
getFilesFromEvent,
|
||||
ImageURLToFile,
|
||||
isImageFileHandle,
|
||||
isSupportedImageFile,
|
||||
@@ -3070,7 +3075,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
// TODO: Cover with tests
|
||||
private async insertClipboardContent(
|
||||
data: ClipboardData,
|
||||
filesData: Awaited<ReturnType<typeof getFilesFromEvent>>,
|
||||
dataTransferFiles: ParsedDataTransferFile[],
|
||||
isPlainPaste: boolean,
|
||||
) {
|
||||
const { x: sceneX, y: sceneY } = viewportCoordsToSceneCoords(
|
||||
@@ -3088,7 +3093,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
|
||||
// ------------------- Mixed content with no files -------------------
|
||||
if (filesData.length === 0 && !isPlainPaste && data.mixedContent) {
|
||||
if (dataTransferFiles.length === 0 && !isPlainPaste && data.mixedContent) {
|
||||
await this.addElementsFromMixedContentPaste(data.mixedContent, {
|
||||
isPlainPaste,
|
||||
sceneX,
|
||||
@@ -3109,9 +3114,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
|
||||
// ------------------- Images or SVG code -------------------
|
||||
const imageFiles = filesData
|
||||
.map((data) => data.file)
|
||||
.filter((file): file is File => isSupportedImageFile(file));
|
||||
const imageFiles = dataTransferFiles.map((data) => data.file);
|
||||
|
||||
if (imageFiles.length === 0 && data.text && !isPlainPaste) {
|
||||
const trimmedText = data.text.trim();
|
||||
@@ -3256,8 +3259,11 @@ class App extends React.Component<AppProps, AppState> {
|
||||
// must be called in the same frame (thus before any awaits) as the paste
|
||||
// event else some browsers (FF...) will clear the clipboardData
|
||||
// (something something security)
|
||||
const filesData = await getFilesFromEvent(event);
|
||||
const data = await parseClipboard(event, isPlainPaste);
|
||||
const dataTransferList = await parseDataTransferEvent(event);
|
||||
|
||||
const filesList = dataTransferList.getFiles();
|
||||
|
||||
const data = await parseClipboard(dataTransferList, isPlainPaste);
|
||||
|
||||
if (this.props.onPaste) {
|
||||
try {
|
||||
@@ -3269,7 +3275,8 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
}
|
||||
|
||||
await this.insertClipboardContent(data, filesData, isPlainPaste);
|
||||
await this.insertClipboardContent(data, filesList, isPlainPaste);
|
||||
|
||||
this.setActiveTool({ type: this.defaultSelectionTool }, true);
|
||||
event?.preventDefault();
|
||||
},
|
||||
@@ -10479,12 +10486,13 @@ class App extends React.Component<AppProps, AppState> {
|
||||
event,
|
||||
this.state,
|
||||
);
|
||||
const dataTransferList = await parseDataTransferEvent(event);
|
||||
|
||||
// must be retrieved first, in the same frame
|
||||
const filesData = await getFilesFromEvent(event);
|
||||
const fileItems = dataTransferList.getFiles();
|
||||
|
||||
if (filesData.length === 1) {
|
||||
const { file, fileHandle } = filesData[0];
|
||||
if (fileItems.length === 1) {
|
||||
const { file, fileHandle } = fileItems[0];
|
||||
|
||||
if (
|
||||
file &&
|
||||
@@ -10516,15 +10524,15 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
}
|
||||
|
||||
const imageFiles = filesData
|
||||
const imageFiles = fileItems
|
||||
.map((data) => data.file)
|
||||
.filter((file): file is File => isSupportedImageFile(file));
|
||||
.filter((file) => isSupportedImageFile(file));
|
||||
|
||||
if (imageFiles.length > 0 && this.isToolSupported("image")) {
|
||||
return this.insertImages(imageFiles, sceneX, sceneY);
|
||||
}
|
||||
|
||||
const libraryJSON = event.dataTransfer.getData(MIME_TYPES.excalidrawlib);
|
||||
const libraryJSON = dataTransferList.getData(MIME_TYPES.excalidrawlib);
|
||||
if (libraryJSON && typeof libraryJSON === "string") {
|
||||
try {
|
||||
const libraryItems = parseLibraryJSON(libraryJSON);
|
||||
@@ -10539,16 +10547,18 @@ class App extends React.Component<AppProps, AppState> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (filesData.length > 0) {
|
||||
const { file, fileHandle } = filesData[0];
|
||||
if (fileItems.length > 0) {
|
||||
const { file, fileHandle } = fileItems[0];
|
||||
if (file) {
|
||||
// Attempt to parse an excalidraw/excalidrawlib file
|
||||
await this.loadFileToCanvas(file, fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (event.dataTransfer?.types?.includes("text/plain")) {
|
||||
const text = event.dataTransfer?.getData("text");
|
||||
const textItem = dataTransferList.findByType(MIME_TYPES.text);
|
||||
|
||||
if (textItem) {
|
||||
const text = textItem.value;
|
||||
if (
|
||||
text &&
|
||||
embeddableURLValidator(text, this.props.validateEmbeddable) &&
|
||||
|
||||
Reference in New Issue
Block a user