diff --git a/.changeset/giant-baboons-lick.md b/.changeset/giant-baboons-lick.md new file mode 100644 index 0000000000000..2a5b1f2581806 --- /dev/null +++ b/.changeset/giant-baboons-lick.md @@ -0,0 +1,6 @@ +--- +"@gradio/file": minor +"gradio": minor +--- + +feat:Add `.download()` event to `gr.File` diff --git a/gradio/__init__.py b/gradio/__init__.py index 5538d75cd36b3..e4087f575fb54 100644 --- a/gradio/__init__.py +++ b/gradio/__init__.py @@ -65,6 +65,7 @@ from gradio.data_classes import FileData from gradio.events import ( DeletedFileData, + DownloadData, EventData, KeyUpData, LikeData, diff --git a/gradio/components/file.py b/gradio/components/file.py index e0cc1c199870d..f6bce4661bda5 100644 --- a/gradio/components/file.py +++ b/gradio/components/file.py @@ -31,7 +31,14 @@ class File(Component): Demo: zip_files, zip_to_json """ - EVENTS = [Events.change, Events.select, Events.clear, Events.upload, Events.delete] + EVENTS = [ + Events.change, + Events.select, + Events.clear, + Events.upload, + Events.delete, + Events.download, + ] def __init__( self, diff --git a/gradio/events.py b/gradio/events.py index 5db8b910dc159..24e7085408e69 100644 --- a/gradio/events.py +++ b/gradio/events.py @@ -371,6 +371,31 @@ def __init__(self, target: Block | None, data: Any): """ +@document() +class DownloadData(EventData): + """ + The gr.DownloadData class is a subclass of gr.EventData that specifically carries information about the `.download()` event. When gr.DownloadData + is added as a type hint to an argument of an event listener method, a gr.DownloadData object will automatically be passed as the value of that argument. + The attributes of this object contains information about the event that triggered the listener. + Example: + import gradio as gr + def on_download(download_data: gr.DownloadData): + return f"Downloaded file: {download_data.file.path}" + with gr.Blocks() as demo: + files = gr.File() + textbox = gr.Textbox() + files.download(on_download, None, textbox) + demo.launch() + """ + + def __init__(self, target: Block | None, data: FileDataDict): + super().__init__(target, data) + self.file: FileData = FileData(**data) + """ + The file that was downloaded, as a FileData object. + """ + + @dataclasses.dataclass class EventListenerMethod: block: Block | None @@ -931,3 +956,7 @@ class Events: "collapse", doc="This listener is triggered when the {{ component }} is collapsed.", ) + download = EventListener( + "download", + doc="This listener is triggered when the user downloads a file from the {{ component }}. Uses event data gradio.DownloadData to carry information about the downloaded file as a FileData object. See EventData documentation on how to use this event data", + ) diff --git a/js/file/Index.svelte b/js/file/Index.svelte index 8febc9c6c8227..2a8f6b551d046 100644 --- a/js/file/Index.svelte +++ b/js/file/Index.svelte @@ -41,6 +41,7 @@ select: SelectData; clear_status: LoadingStatus; delete: FileData; + download: FileData; }>; export let file_count: "single" | "multiple" | "directory"; export let file_types: string[] = ["file"]; @@ -82,6 +83,7 @@ {#if !interactive} gradio.dispatch("select", detail)} + on:download={({ detail }) => gradio.dispatch("download", detail)} selectable={_selectable} {value} {label} diff --git a/js/file/shared/File.svelte b/js/file/shared/File.svelte index 8b9753891024d..583c896e83b2b 100644 --- a/js/file/shared/File.svelte +++ b/js/file/shared/File.svelte @@ -21,7 +21,7 @@ /> {#if value && (Array.isArray(value) ? value.length > 0 : true)} - + {:else} {/if} diff --git a/js/file/shared/FilePreview.svelte b/js/file/shared/FilePreview.svelte index a867287b2a34b..5d61bd86b2ca4 100644 --- a/js/file/shared/FilePreview.svelte +++ b/js/file/shared/FilePreview.svelte @@ -9,6 +9,7 @@ select: SelectData; change: FileData[] | FileData; delete: FileData; + download: FileData; }>(); export let value: FileData | FileData[]; export let selectable = false; @@ -56,6 +57,10 @@ dispatch("change", normalized_files); } + function handle_download(file: FileData): void { + dispatch("download", file); + } + const is_browser = typeof window !== "undefined"; @@ -82,6 +87,7 @@ {#if file.url} handle_download(file)} download={is_browser && window.__is_colab__ ? null : file.orig_name}