adf0d17497
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled
135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
"""Predefined button to copy a shareable link to the current Gradio Space."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import textwrap
|
|
import time
|
|
from collections.abc import Sequence
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING, Literal
|
|
|
|
from gradio_client.documentation import document
|
|
|
|
from gradio import utils
|
|
from gradio.components.base import Component
|
|
from gradio.components.button import Button
|
|
from gradio.context import get_blocks_context
|
|
|
|
if TYPE_CHECKING:
|
|
from gradio.components import Timer
|
|
|
|
|
|
@document()
|
|
class DeepLinkButton(Button):
|
|
"""
|
|
Creates a button that copies a shareable link to the current Gradio Space.
|
|
The link includes the current session hash as a query parameter.
|
|
"""
|
|
|
|
is_template = True
|
|
n_created = 0
|
|
|
|
def __init__(
|
|
self,
|
|
value: str = "Share via Link",
|
|
copied_value: str = "Link Copied!",
|
|
*,
|
|
inputs: Component | Sequence[Component] | set[Component] | None = None,
|
|
variant: Literal["primary", "secondary"] = "secondary",
|
|
size: Literal["sm", "md", "lg"] = "lg",
|
|
icon: str | Path | None = utils.get_icon_path("link.svg"),
|
|
link: str | None = None,
|
|
link_target: Literal["_self", "_blank", "_parent", "_top"] = "_self",
|
|
visible: bool | Literal["hidden"] = True,
|
|
interactive: bool = True,
|
|
elem_id: str | None = None, # noqa: ARG002
|
|
elem_classes: list[str] | str | None = None,
|
|
render: bool = True,
|
|
key: int | str | tuple[int | str, ...] | None = None,
|
|
preserved_by_key: list[str] | str | None = "value",
|
|
scale: int | None = None,
|
|
min_width: int | None = None,
|
|
every: Timer | float | None = None,
|
|
):
|
|
"""
|
|
Parameters:
|
|
value: The text to display on the button.
|
|
copied_value: The text to display on the button after the link has been copied.
|
|
"""
|
|
self.copied_value = copied_value
|
|
super().__init__(
|
|
value,
|
|
inputs=inputs,
|
|
variant=variant,
|
|
size=size,
|
|
icon=icon,
|
|
link=link,
|
|
link_target=link_target,
|
|
visible=visible,
|
|
interactive=interactive,
|
|
elem_id=f"gradio-share-link-button-{self.n_created}",
|
|
elem_classes=elem_classes,
|
|
render=render,
|
|
key=key,
|
|
preserved_by_key=preserved_by_key,
|
|
scale=scale,
|
|
min_width=min_width,
|
|
every=every,
|
|
)
|
|
self.elem_id: str
|
|
self.n_created += 1
|
|
if get_blocks_context():
|
|
self.activate()
|
|
|
|
def activate(self):
|
|
"""Attach the click event to copy the share link."""
|
|
_js = self.get_share_link(self.value, self.copied_value)
|
|
# Need to separate events because can't run .then in a pure js
|
|
# function.
|
|
self.click(fn=None, inputs=[], outputs=[self], js=_js, api_visibility="private")
|
|
self.click(
|
|
fn=lambda: time.sleep(1) or self.value,
|
|
inputs=[],
|
|
outputs=[self],
|
|
queue=False,
|
|
api_visibility="undocumented",
|
|
)
|
|
|
|
def get_share_link(
|
|
self, value: str = "Share via Link", copied_value: str = "Link Copied!"
|
|
):
|
|
delete_sign_line = (
|
|
"currentUrl.searchParams.delete('__sign');" if utils.get_space() else ""
|
|
)
|
|
return textwrap.dedent(
|
|
f"""
|
|
() => {{
|
|
const sessionHash = window.__gradio_session_hash__;
|
|
fetch(`gradio_api/deep_link?session_hash=${{sessionHash}}`)
|
|
.then(response => {{
|
|
if (!response.ok) {{
|
|
throw new Error('Network response was not ok');
|
|
}}
|
|
return response.text();
|
|
}})
|
|
.then(data => {{
|
|
const currentUrl = new URL(window.location.href);
|
|
const cleanData = data.replace(/^"|"$/g, '');
|
|
if (cleanData) {{
|
|
currentUrl.searchParams.set('deep_link', cleanData);
|
|
}}
|
|
{delete_sign_line}
|
|
navigator.clipboard.writeText(currentUrl.toString());
|
|
}})
|
|
.catch(error => {{
|
|
console.error('Error fetching deep link:', error);
|
|
return "Error";
|
|
}});
|
|
|
|
return "BUTTON_COPIED_VALUE";
|
|
}}
|
|
""".replace("BUTTON_DEFAULT_VALUE", value).replace(
|
|
"BUTTON_COPIED_VALUE", copied_value
|
|
)
|
|
).replace("ID", self.elem_id)
|