diff --git a/.changeset/modern-clubs-march.md b/.changeset/modern-clubs-march.md new file mode 100644 index 0000000000..e45079e16b --- /dev/null +++ b/.changeset/modern-clubs-march.md @@ -0,0 +1,7 @@ +--- +"@gradio/model3d": patch +"@gradio/upload": patch +"gradio": patch +--- + +fix:Fixes Drag and Drop for Upload diff --git a/js/app/test/model3d_component_events.spec.ts b/js/app/test/model3d_component_events.spec.ts index 98d73843e7..76a69817e1 100644 --- a/js/app/test/model3d_component_events.spec.ts +++ b/js/app/test/model3d_component_events.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from "@gradio/tootils"; +import { test, expect, drag_and_drop_file } from "@gradio/tootils"; test("Model3D click-to-upload uploads file successfuly. Upload and clear events work correctly. Downloading works.", async ({ page @@ -25,3 +25,17 @@ test("Model3D click-to-upload uploads file successfuly. Upload and clear events const download = await downloadPromise; await expect(download.suggestedFilename()).toBe("face.obj"); }); + +test("Model3D drag-and-drop uploads a file to the server correctly.", async ({ + page +}) => { + await drag_and_drop_file( + page, + "input[type=file]", + "./test/files/face.obj", + "face.obj" + ); + await page.waitForResponse("**/upload?*"); + await expect(page.getByLabel("# Change Events")).toHaveValue("1"); + await expect(page.getByLabel("# Upload Events")).toHaveValue("1"); +}); diff --git a/js/model3D/shared/Model3DUpload.svelte b/js/model3D/shared/Model3DUpload.svelte index 89816faac3..4977602457 100644 --- a/js/model3D/shared/Model3DUpload.svelte +++ b/js/model3D/shared/Model3DUpload.svelte @@ -109,7 +109,7 @@ diff --git a/js/upload/src/Upload.svelte b/js/upload/src/Upload.svelte index d7feddc3f3..be104c5cdc 100644 --- a/js/upload/src/Upload.svelte +++ b/js/upload/src/Upload.svelte @@ -5,7 +5,7 @@ import { _ } from "svelte-i18n"; import UploadProgress from "./UploadProgress.svelte"; - export let filetype: string | null = null; + export let filetype: string | string[] | null = null; export let dragging = false; export let boundedheight = true; export let center = true; @@ -20,6 +20,7 @@ let upload_id: string; let file_data: FileData[]; + let accept_file_types: string | null; // Needed for wasm support const upload_fn = getContext("upload_files"); @@ -28,6 +29,17 @@ const dispatch = createEventDispatcher(); + $: if (filetype == null || typeof filetype === "string") { + accept_file_types = filetype; + } else { + filetype = filetype.map((x) => { + if (x.startsWith(".")) { + return x; + } + return x + "/*"; + }); + accept_file_types = filetype.join(", "); + } function updateDragging(): void { dragging = !dragging; } @@ -76,17 +88,23 @@ } function is_valid_mimetype( - file_accept: string | null, + file_accept: string | string[] | null, mime_type: string ): boolean { - if (!file_accept) { + if (!file_accept || file_accept === "*" || file_accept === "file/*") { return true; } - if (file_accept === "*") { - return true; + if (typeof file_accept === "string" && file_accept.endsWith("/*")) { + file_accept = file_accept.split(","); } - if (file_accept.endsWith("/*")) { - return mime_type.startsWith(file_accept.slice(0, -1)); + if (Array.isArray(file_accept)) { + return ( + file_accept.includes(mime_type) || + file_accept.some((type) => { + const [category] = type.split("/"); + return type.endsWith("/*") && mime_type.startsWith(category + "/"); + }) + ); } return file_accept === mime_type; } @@ -96,13 +114,14 @@ if (!e.dataTransfer?.files) return; const files_to_load = Array.from(e.dataTransfer.files).filter((f) => { - if (filetype?.split(",").some((m) => is_valid_mimetype(m, f.type))) { + const file_extension = + f.type !== "" ? f.type : "." + f.name.split(".").pop(); + if (file_extension && is_valid_mimetype(filetype, file_extension)) { return true; } dispatch("error", `Invalid file type only ${filetype} allowed.`); return false; }); - await load_files(files_to_load); } @@ -137,7 +156,7 @@ type="file" bind:this={hidden_upload} on:change={load_files_from_upload} - accept={filetype} + accept={accept_file_types} multiple={file_count === "multiple" || undefined} webkitdirectory={file_count === "directory" || undefined} mozdirectory={file_count === "directory" || undefined}