mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-30 11:00:11 +08:00
add delete event to File
component (#8417)
* fix param name * format * add delete event to File component * fix * add changeset * fix * fix * fix * add changeset * format * add changeset * file file layout * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
parent
63d36fbbf4
commit
96d8de2312
8
.changeset/full-flies-join.md
Normal file
8
.changeset/full-flies-join.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
"@gradio/file": minor
|
||||
"@gradio/tootils": minor
|
||||
"@gradio/upload": minor
|
||||
"gradio": minor
|
||||
---
|
||||
|
||||
feat:add delete event to `File` component
|
@ -1 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " \n", " with gr.Row():\n", " with gr.Column():\n", " file_component = gr.File(label=\"Upload Single File\", file_count=\"single\")\n", " with gr.Column():\n", " output_file_1 = gr.File(label=\"Upload Single File Output\", file_count=\"single\")\n", " num_load_btn_1 = gr.Number(label=\"# Load Upload Single File\", value=0)\n", " file_component.upload(lambda s,n: (s, n + 1), [file_component, num_load_btn_1], [output_file_1, num_load_btn_1])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_multiple = gr.File(label=\"Upload Multiple Files\", file_count=\"multiple\")\n", " with gr.Column():\n", " output_file_2 = gr.File(label=\"Upload Multiple Files Output\", file_count=\"multiple\")\n", " num_load_btn_2 = gr.Number(label=\"# Load Upload Multiple Files\", value=0)\n", " file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_specific = gr.File(label=\"Upload Multiple Files Image/Video\", file_count=\"multiple\", file_types=[\"image\", \"video\"])\n", " with gr.Column():\n", " output_file_3 = gr.File(label=\"Upload Multiple Files Output Image/Video\", file_count=\"multiple\")\n", " num_load_btn_3 = gr.Number(label=\"# Load Upload Multiple Files Image/Video\", value=0)\n", " file_component_specific.upload(lambda s,n: (s, n + 1), [file_component_specific, num_load_btn_3], [output_file_3, num_load_btn_3])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_pdf = gr.File(label=\"Upload PDF File\", file_types=[\"pdf\"])\n", " with gr.Column():\n", " output_file_4 = gr.File(label=\"Upload PDF File Output\")\n", " num_load_btn_4 = gr.Number(label=\"# Load Upload PDF File\", value=0)\n", " file_component_pdf.upload(lambda s,n: (s, n + 1), [file_component_pdf, num_load_btn_4], [output_file_4, num_load_btn_4])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_invalid = gr.File(label=\"Upload File with Invalid file_types\", file_types=[\"invalid file_type\"])\n", " with gr.Column():\n", " output_file_5 = gr.File(label=\"Upload File with Invalid file_types Output\")\n", " num_load_btn_5 = gr.Number(label=\"# Load Upload File with Invalid file_types\", value=0)\n", " file_component_invalid.upload(lambda s,n: (s, n + 1), [file_component_invalid, num_load_btn_5], [output_file_5, num_load_btn_5])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def delete_file(n: int, file: gr.DeletedFileData):\n", " return [file.file.path, n + 1]\n", "\n", "\n", "with gr.Blocks() as demo:\n", "\n", " with gr.Row():\n", " with gr.Column():\n", " file_component = gr.File(label=\"Upload Single File\", file_count=\"single\")\n", " with gr.Column():\n", " output_file_1 = gr.File(\n", " label=\"Upload Single File Output\", file_count=\"single\"\n", " )\n", " num_load_btn_1 = gr.Number(label=\"# Load Upload Single File\", value=0)\n", " file_component.upload(\n", " lambda s, n: (s, n + 1),\n", " [file_component, num_load_btn_1],\n", " [output_file_1, num_load_btn_1],\n", " )\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_multiple = gr.File(\n", " label=\"Upload Multiple Files\", file_count=\"multiple\"\n", " )\n", " with gr.Column():\n", " output_file_2 = gr.File(\n", " label=\"Upload Multiple Files Output\", file_count=\"multiple\"\n", " )\n", " num_load_btn_2 = gr.Number(label=\"# Load Upload Multiple Files\", value=0)\n", " file_component_multiple.upload(\n", " lambda s, n: (s, n + 1),\n", " [file_component_multiple, num_load_btn_2],\n", " [output_file_2, num_load_btn_2],\n", " )\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_specific = gr.File(\n", " label=\"Upload Multiple Files Image/Video\",\n", " file_count=\"multiple\",\n", " file_types=[\"image\", \"video\"],\n", " )\n", " with gr.Column():\n", " output_file_3 = gr.File(\n", " label=\"Upload Multiple Files Output Image/Video\", file_count=\"multiple\"\n", " )\n", " num_load_btn_3 = gr.Number(\n", " label=\"# Load Upload Multiple Files Image/Video\", value=0\n", " )\n", " file_component_specific.upload(\n", " lambda s, n: (s, n + 1),\n", " [file_component_specific, num_load_btn_3],\n", " [output_file_3, num_load_btn_3],\n", " )\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_pdf = gr.File(label=\"Upload PDF File\", file_types=[\"pdf\"])\n", " with gr.Column():\n", " output_file_4 = gr.File(label=\"Upload PDF File Output\")\n", " num_load_btn_4 = gr.Number(label=\"# Load Upload PDF File\", value=0)\n", " file_component_pdf.upload(\n", " lambda s, n: (s, n + 1),\n", " [file_component_pdf, num_load_btn_4],\n", " [output_file_4, num_load_btn_4],\n", " )\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_invalid = gr.File(\n", " label=\"Upload File with Invalid file_types\",\n", " file_types=[\"invalid file_type\"],\n", " )\n", " with gr.Column():\n", " output_file_5 = gr.File(label=\"Upload File with Invalid file_types Output\")\n", " num_load_btn_5 = gr.Number(\n", " label=\"# Load Upload File with Invalid file_types\", value=0\n", " )\n", " file_component_invalid.upload(\n", " lambda s, n: (s, n + 1),\n", " [file_component_invalid, num_load_btn_5],\n", " [output_file_5, num_load_btn_5],\n", " )\n", " with gr.Row():\n", " with gr.Column():\n", " del_file_input = gr.File(label=\"Delete File\", file_count=\"multiple\")\n", " with gr.Column():\n", " del_file_data = gr.Textbox(label=\"Delete file data\")\n", " num_load_btn_6 = gr.Number(label=\"# Deleted File\", value=0)\n", " del_file_input.delete(\n", " delete_file,\n", " [num_load_btn_6],\n", " [del_file_data, num_load_btn_6],\n", " )\n", " # f = gr.File(label=\"Upload many File\", file_count=\"multiple\")\n", " # # f.delete(delete_file)\n", " # f.delete(delete_file, inputs=None, outputs=None)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
@ -1,42 +1,100 @@
|
||||
import gradio as gr
|
||||
|
||||
|
||||
def delete_file(n: int, file: gr.DeletedFileData):
|
||||
return [file.file.path, n + 1]
|
||||
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
|
||||
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
file_component = gr.File(label="Upload Single File", file_count="single")
|
||||
with gr.Column():
|
||||
output_file_1 = gr.File(label="Upload Single File Output", file_count="single")
|
||||
output_file_1 = gr.File(
|
||||
label="Upload Single File Output", file_count="single"
|
||||
)
|
||||
num_load_btn_1 = gr.Number(label="# Load Upload Single File", value=0)
|
||||
file_component.upload(lambda s,n: (s, n + 1), [file_component, num_load_btn_1], [output_file_1, num_load_btn_1])
|
||||
file_component.upload(
|
||||
lambda s, n: (s, n + 1),
|
||||
[file_component, num_load_btn_1],
|
||||
[output_file_1, num_load_btn_1],
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
file_component_multiple = gr.File(label="Upload Multiple Files", file_count="multiple")
|
||||
file_component_multiple = gr.File(
|
||||
label="Upload Multiple Files", file_count="multiple"
|
||||
)
|
||||
with gr.Column():
|
||||
output_file_2 = gr.File(label="Upload Multiple Files Output", file_count="multiple")
|
||||
output_file_2 = gr.File(
|
||||
label="Upload Multiple Files Output", file_count="multiple"
|
||||
)
|
||||
num_load_btn_2 = gr.Number(label="# Load Upload Multiple Files", value=0)
|
||||
file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])
|
||||
file_component_multiple.upload(
|
||||
lambda s, n: (s, n + 1),
|
||||
[file_component_multiple, num_load_btn_2],
|
||||
[output_file_2, num_load_btn_2],
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
file_component_specific = gr.File(label="Upload Multiple Files Image/Video", file_count="multiple", file_types=["image", "video"])
|
||||
file_component_specific = gr.File(
|
||||
label="Upload Multiple Files Image/Video",
|
||||
file_count="multiple",
|
||||
file_types=["image", "video"],
|
||||
)
|
||||
with gr.Column():
|
||||
output_file_3 = gr.File(label="Upload Multiple Files Output Image/Video", file_count="multiple")
|
||||
num_load_btn_3 = gr.Number(label="# Load Upload Multiple Files Image/Video", value=0)
|
||||
file_component_specific.upload(lambda s,n: (s, n + 1), [file_component_specific, num_load_btn_3], [output_file_3, num_load_btn_3])
|
||||
output_file_3 = gr.File(
|
||||
label="Upload Multiple Files Output Image/Video", file_count="multiple"
|
||||
)
|
||||
num_load_btn_3 = gr.Number(
|
||||
label="# Load Upload Multiple Files Image/Video", value=0
|
||||
)
|
||||
file_component_specific.upload(
|
||||
lambda s, n: (s, n + 1),
|
||||
[file_component_specific, num_load_btn_3],
|
||||
[output_file_3, num_load_btn_3],
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
file_component_pdf = gr.File(label="Upload PDF File", file_types=["pdf"])
|
||||
with gr.Column():
|
||||
output_file_4 = gr.File(label="Upload PDF File Output")
|
||||
num_load_btn_4 = gr.Number(label="# Load Upload PDF File", value=0)
|
||||
file_component_pdf.upload(lambda s,n: (s, n + 1), [file_component_pdf, num_load_btn_4], [output_file_4, num_load_btn_4])
|
||||
file_component_pdf.upload(
|
||||
lambda s, n: (s, n + 1),
|
||||
[file_component_pdf, num_load_btn_4],
|
||||
[output_file_4, num_load_btn_4],
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
file_component_invalid = gr.File(label="Upload File with Invalid file_types", file_types=["invalid file_type"])
|
||||
file_component_invalid = gr.File(
|
||||
label="Upload File with Invalid file_types",
|
||||
file_types=["invalid file_type"],
|
||||
)
|
||||
with gr.Column():
|
||||
output_file_5 = gr.File(label="Upload File with Invalid file_types Output")
|
||||
num_load_btn_5 = gr.Number(label="# Load Upload File with Invalid file_types", value=0)
|
||||
file_component_invalid.upload(lambda s,n: (s, n + 1), [file_component_invalid, num_load_btn_5], [output_file_5, num_load_btn_5])
|
||||
num_load_btn_5 = gr.Number(
|
||||
label="# Load Upload File with Invalid file_types", value=0
|
||||
)
|
||||
file_component_invalid.upload(
|
||||
lambda s, n: (s, n + 1),
|
||||
[file_component_invalid, num_load_btn_5],
|
||||
[output_file_5, num_load_btn_5],
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
del_file_input = gr.File(label="Delete File", file_count="multiple")
|
||||
with gr.Column():
|
||||
del_file_data = gr.Textbox(label="Delete file data")
|
||||
num_load_btn_6 = gr.Number(label="# Deleted File", value=0)
|
||||
del_file_input.delete(
|
||||
delete_file,
|
||||
[num_load_btn_6],
|
||||
[del_file_data, num_load_btn_6],
|
||||
)
|
||||
# f = gr.File(label="Upload many File", file_count="multiple")
|
||||
# # f.delete(delete_file)
|
||||
# f.delete(delete_file, inputs=None, outputs=None)
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
||||
|
@ -60,7 +60,14 @@ from gradio.components import (
|
||||
from gradio.components.audio import WaveformOptions
|
||||
from gradio.components.image_editor import Brush, Eraser
|
||||
from gradio.data_classes import FileData
|
||||
from gradio.events import EventData, KeyUpData, LikeData, SelectData, on
|
||||
from gradio.events import (
|
||||
DeletedFileData,
|
||||
EventData,
|
||||
KeyUpData,
|
||||
LikeData,
|
||||
SelectData,
|
||||
on,
|
||||
)
|
||||
from gradio.exceptions import Error
|
||||
from gradio.external import load
|
||||
from gradio.flagging import (
|
||||
|
@ -26,7 +26,7 @@ class File(Component):
|
||||
Demo: zip_files, zip_to_json
|
||||
"""
|
||||
|
||||
EVENTS = [Events.change, Events.select, Events.clear, Events.upload]
|
||||
EVENTS = [Events.change, Events.select, Events.clear, Events.upload, Events.delete]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -8,7 +8,7 @@ import secrets
|
||||
import shutil
|
||||
from abc import ABC, abstractmethod
|
||||
from enum import Enum, auto
|
||||
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union
|
||||
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, TypedDict, Union
|
||||
|
||||
from fastapi import Request
|
||||
from gradio_client.utils import traverse
|
||||
@ -189,6 +189,16 @@ class GradioRootModel(GradioBaseModel, RootModel):
|
||||
GradioDataModel = Union[GradioModel, GradioRootModel]
|
||||
|
||||
|
||||
class FileDataDict(TypedDict):
|
||||
path: str # server filepath
|
||||
url: Optional[str] # normalised server url
|
||||
size: Optional[int] # size in bytes
|
||||
orig_name: Optional[str] # original filename
|
||||
mime_type: Optional[str]
|
||||
is_stream: bool
|
||||
meta: dict
|
||||
|
||||
|
||||
class FileData(GradioModel):
|
||||
path: str # server filepath
|
||||
url: Optional[str] = None # normalised server url
|
||||
|
@ -20,6 +20,8 @@ from typing import (
|
||||
from gradio_client.documentation import document
|
||||
from jinja2 import Template
|
||||
|
||||
from gradio.data_classes import FileData, FileDataDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from gradio.blocks import Block, Component
|
||||
|
||||
@ -149,6 +151,15 @@ class KeyUpData(EventData):
|
||||
"""
|
||||
|
||||
|
||||
class DeletedFileData(EventData):
|
||||
def __init__(self, target: Block | None, data: FileDataDict):
|
||||
super().__init__(target, data)
|
||||
self.file: FileData = FileData(**data)
|
||||
"""
|
||||
The file that was deleted.
|
||||
"""
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class EventListenerMethod:
|
||||
block: Block | None
|
||||
@ -585,6 +596,10 @@ class Events:
|
||||
"apply",
|
||||
doc="This listener is triggered when the user applies changes to the {{ component }} through an integrated UI action.",
|
||||
)
|
||||
delete = EventListener(
|
||||
"delete",
|
||||
doc="This listener is triggered when the user deletes and item from the {{ component }}. Uses event data gradio.DeletedFileData to carry `value` referring to the file that was deleted as an instance of FileData. See EventData documentation on how to use this event data",
|
||||
)
|
||||
|
||||
|
||||
class LikeData(EventData):
|
||||
|
@ -1,5 +1,13 @@
|
||||
import { test, expect, drag_and_drop_file } from "@gradio/tootils";
|
||||
|
||||
async function error_modal_showed(page) {
|
||||
const toast = page.getByTestId("toast-body");
|
||||
expect(toast).toContainText("error");
|
||||
const close = page.getByTestId("toast-close");
|
||||
await close.click();
|
||||
await expect(page.getByTestId("toast-body")).toHaveCount(0);
|
||||
}
|
||||
|
||||
test("File component properly dispatches load event for the single file case.", async ({
|
||||
page
|
||||
}) => {
|
||||
@ -63,11 +71,33 @@ test("File component properly handles drag and drop of pdf file.", async ({
|
||||
test("File component properly handles invalid file_types.", async ({
|
||||
page
|
||||
}) => {
|
||||
const uploader = await page.locator("input[type=file]").last();
|
||||
await uploader.setInputFiles(["./test/files/cheetah1.jpg"]);
|
||||
const locator = page.locator("input[type=file]").nth(4);
|
||||
await drag_and_drop_file(
|
||||
page,
|
||||
locator,
|
||||
"./test/files/cheetah1.jpg",
|
||||
"cheetah1.jpg",
|
||||
"image/jpeg"
|
||||
);
|
||||
|
||||
// Check that the pdf file was uploaded
|
||||
await expect(
|
||||
page.getByLabel("# Load Upload File with Invalid file_types")
|
||||
).toHaveValue("1");
|
||||
await error_modal_showed(page);
|
||||
});
|
||||
|
||||
test("Delete event is fired correctly", async ({ page }) => {
|
||||
const locator = page.locator("input[type=file]").nth(5);
|
||||
await drag_and_drop_file(
|
||||
page,
|
||||
locator,
|
||||
"./test/files/cheetah1.jpg",
|
||||
"cheetah1.jpg",
|
||||
"image/jpeg",
|
||||
2
|
||||
);
|
||||
|
||||
await page.getByLabel("Remove this file").first().click();
|
||||
|
||||
await expect(page.getByLabel("# Deleted File")).toHaveValue("1");
|
||||
expect(
|
||||
(await page.getByLabel("Delete file data").inputValue()).length
|
||||
).toBeGreaterThan(5);
|
||||
});
|
||||
|
@ -40,6 +40,7 @@
|
||||
clear: never;
|
||||
select: SelectData;
|
||||
clear_status: LoadingStatus;
|
||||
delete: FileData;
|
||||
}>;
|
||||
export let file_count: string;
|
||||
export let file_types: string[] = ["file"];
|
||||
@ -110,6 +111,9 @@
|
||||
loading_status.status = "error";
|
||||
gradio.dispatch("error", detail);
|
||||
}}
|
||||
on:delete={({ detail }) => {
|
||||
gradio.dispatch("delete", detail);
|
||||
}}
|
||||
i18n={gradio.i18n}
|
||||
>
|
||||
<UploadText i18n={gradio.i18n} type="file" />
|
||||
|
@ -8,6 +8,7 @@
|
||||
const dispatch = createEventDispatcher<{
|
||||
select: SelectData;
|
||||
change: FileData[] | FileData;
|
||||
delete: FileData;
|
||||
}>();
|
||||
export let value: FileData | FileData[];
|
||||
export let selectable = false;
|
||||
@ -46,9 +47,10 @@
|
||||
}
|
||||
|
||||
function remove_file(index: number): void {
|
||||
normalized_files.splice(index, 1);
|
||||
const removed = normalized_files.splice(index, 1);
|
||||
normalized_files = [...normalized_files];
|
||||
value = normalized_files;
|
||||
dispatch("delete", removed[0]);
|
||||
dispatch("change", normalized_files);
|
||||
}
|
||||
</script>
|
||||
|
@ -50,16 +50,19 @@
|
||||
$: dispatch("drag", dragging);
|
||||
</script>
|
||||
|
||||
<BlockLabel
|
||||
{show_label}
|
||||
Icon={File}
|
||||
float={value === null}
|
||||
label={label || "File"}
|
||||
/>
|
||||
<BlockLabel {show_label} Icon={File} float={!value} label={label || "File"} />
|
||||
|
||||
{#if value && (Array.isArray(value) ? value.length > 0 : true)}
|
||||
<ModifyUpload {i18n} on:clear={handle_clear} absolute />
|
||||
<FilePreview {i18n} on:select {selectable} {value} {height} on:change />
|
||||
<FilePreview
|
||||
{i18n}
|
||||
on:select
|
||||
{selectable}
|
||||
{value}
|
||||
{height}
|
||||
on:change
|
||||
on:delete
|
||||
/>
|
||||
{:else}
|
||||
<Upload
|
||||
on:load={handle_upload}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { test as base, type Page } from "@playwright/test";
|
||||
import { test as base, type Locator, type Page } from "@playwright/test";
|
||||
import { spy } from "tinyspy";
|
||||
import url from "url";
|
||||
import path from "path";
|
||||
@ -163,29 +163,40 @@ export * from "./render";
|
||||
|
||||
export const drag_and_drop_file = async (
|
||||
page: Page,
|
||||
selector: string,
|
||||
selector: string | Locator,
|
||||
filePath: string,
|
||||
fileName: string,
|
||||
fileType = ""
|
||||
fileType = "",
|
||||
count = 1
|
||||
): Promise<void> => {
|
||||
const buffer = (await fsPromises.readFile(filePath)).toString("base64");
|
||||
|
||||
const dataTransfer = await page.evaluateHandle(
|
||||
async ({ bufferData, localFileName, localFileType }) => {
|
||||
async ({ bufferData, localFileName, localFileType, count }) => {
|
||||
const dt = new DataTransfer();
|
||||
|
||||
const blobData = await fetch(bufferData).then((res) => res.blob());
|
||||
|
||||
const file = new File([blobData], localFileName, { type: localFileType });
|
||||
dt.items.add(file);
|
||||
const file = new File([blobData], localFileName, {
|
||||
type: localFileType
|
||||
});
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
dt.items.add(file);
|
||||
}
|
||||
return dt;
|
||||
},
|
||||
{
|
||||
bufferData: `data:application/octet-stream;base64,${buffer}`,
|
||||
localFileName: fileName,
|
||||
localFileType: fileType
|
||||
localFileType: fileType,
|
||||
count
|
||||
}
|
||||
);
|
||||
|
||||
await page.dispatchEvent(selector, "drop", { dataTransfer });
|
||||
if (typeof selector === "string") {
|
||||
await page.dispatchEvent(selector, "drop", { dataTransfer });
|
||||
} else {
|
||||
await selector.dispatchEvent("drop", { dataTransfer });
|
||||
}
|
||||
};
|
||||
|
@ -150,6 +150,7 @@
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
acceptArray.includes(uploaded_file_extension) ||
|
||||
acceptArray.some((type) => {
|
||||
|
Loading…
Reference in New Issue
Block a user