Skip to content

Commit

Permalink
Add download button to selected images in Gallery (#5025)
Browse files Browse the repository at this point in the history
* add download button to gallery selected images

* add changeset

* add story

* tweak

* fix href val for internal file paths

* set show_download_button to True by default

* lint backend

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
hannahblair and gradio-pr-bot committed Jul 31, 2023
1 parent 5244c58 commit 6693660
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 3 deletions.
7 changes: 7 additions & 0 deletions .changeset/curly-nights-yawn.md
@@ -0,0 +1,7 @@
---
"@gradio/app": minor
"@gradio/gallery": minor
"gradio": minor
---

feat:Add download button to selected images in `Gallery`
11 changes: 11 additions & 0 deletions gradio/components/gallery.py
Expand Up @@ -54,6 +54,7 @@ def __init__(
| None = None,
allow_preview: bool = True,
show_share_button: bool | None = None,
show_download_button: bool | None = True,
**kwargs,
):
"""
Expand All @@ -75,13 +76,20 @@ def __init__(
object_fit: CSS object-fit property for the thumbnail images in the gallery. Can be "contain", "cover", "fill", "none", or "scale-down".
allow_preview: If True, images in the gallery will be enlarged when they are clicked. Default is True.
show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise.
show_download_button: If True, will show a download button in the corner of the selected image. If False, the icon does not appear. Default is True.
"""
self.grid_cols = columns
self.grid_rows = rows
self.height = height
self.preview = preview
self.object_fit = object_fit
self.allow_preview = allow_preview
self.show_download_button = (
(utils.get_space() is not None)
if show_download_button is None
else show_download_button
)
self.select: EventListenerMethod
"""
Event listener for when the user selects image within Gallery.
Expand Down Expand Up @@ -125,6 +133,7 @@ def update(
| None = None,
allow_preview: bool | None = None,
show_share_button: bool | None = None,
show_download_button: bool | None = None,
):
updated_config = {
"label": label,
Expand All @@ -141,6 +150,7 @@ def update(
"object_fit": object_fit,
"allow_preview": allow_preview,
"show_share_button": show_share_button,
"show_download_button": show_download_button,
"__type__": "update",
}
return updated_config
Expand All @@ -155,6 +165,7 @@ def get_config(self):
"object_fit": self.object_fit,
"allow_preview": self.allow_preview,
"show_share_button": self.show_share_button,
"show_download_button": self.show_download_button,
**IOComponent.get_config(self),
}

Expand Down
13 changes: 13 additions & 0 deletions js/app/src/components/Gallery/Gallery.stories.svelte
Expand Up @@ -196,3 +196,16 @@
],
}}
/>

<Story
name="Gallery with download button"
args={{
label: "My Cheetah Gallery",
grid_rows: 2,
height: 400,
show_download_button: true,
value: [
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-002.jpg",
],
}}
/>
2 changes: 2 additions & 0 deletions js/app/src/components/Gallery/Gallery.svelte
Expand Up @@ -26,6 +26,7 @@
export let object_fit: "contain" | "cover" | "fill" | "none" | "scale-down" =
"cover";
export let show_share_button = false;
export let show_download_button = false;
</script>

<Block
Expand Down Expand Up @@ -57,5 +58,6 @@
{object_fit}
{allow_preview}
{show_share_button}
{show_download_button}
/>
</Block>
45 changes: 42 additions & 3 deletions js/gallery/src/Gallery.svelte
Expand Up @@ -6,10 +6,11 @@
import { createEventDispatcher } from "svelte";
import { tick } from "svelte";
import { Image } from "@gradio/icons";
import { Download, Image } from "@gradio/icons";
import type { FileData } from "@gradio/upload";
import { normalise_file } from "@gradio/upload";
import { format_gallery_for_sharing } from "./utils";
import { IconButton } from "@gradio/atoms";
export let show_label = true;
export let label: string;
Expand All @@ -25,6 +26,7 @@
export let object_fit: "contain" | "cover" | "fill" | "none" | "scale-down" =
"cover";
export let show_share_button = false;
export let show_download_button = false;
const dispatch = createEventDispatcher<{
select: SelectData;
Expand Down Expand Up @@ -105,6 +107,19 @@
}
}
function isFileData(obj: any): obj is FileData {
return typeof obj === "object" && obj !== null && "data" in obj;
}
function getHrefValue(selected: any): string {
if (isFileData(selected)) {
return selected.data;
} else if (typeof selected === "string") {
return selected;
}
return "";
}
$: {
if (selected_image !== old_selected_image) {
old_selected_image = selected_image;
Expand Down Expand Up @@ -163,8 +178,22 @@
{#if selected_image !== null && allow_preview}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div on:keydown={on_keydown} class="preview">
<ModifyUpload on:clear={() => (selected_image = null)} />

<div class="icon-buttons">
{#if show_download_button}
<a
href={getHrefValue(value[selected_image])}
target={window.__is_colab__ ? "_blank" : null}
download="image"
>
<IconButton Icon={Download} label="Download" />
</a>
{/if}

<ModifyUpload
absolute={false}
on:clear={() => (selected_image = null)}
/>
</div>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<img
Expand Down Expand Up @@ -399,4 +428,14 @@
right: 0px;
z-index: var(--layer-1);
}
.icon-buttons {
display: flex;
position: absolute;
right: 0;
}
.icon-buttons a {
margin: var(--size-1) 0;
}
</style>

1 comment on commit 6693660

@vercel
Copy link

@vercel vercel bot commented on 6693660 Jul 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.