mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-24 10:54:04 +08:00
rework upload to be a class method + pass client into each component (#8179)
* rework upload to be a class method + pass client into each component * add changeset * Update client/js/src/utils/upload_files.ts * fix storybook * review comments * Apply suggestions from code review Co-authored-by: Hannah <hannahblair@users.noreply.github.com> * format * ts fix --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Hannah <hannahblair@users.noreply.github.com>
This commit is contained in:
parent
a0e70366a8
commit
6a218b4148
22
.changeset/huge-rivers-cough.md
Normal file
22
.changeset/huge-rivers-cough.md
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
"@gradio/app": patch
|
||||
"@gradio/audio": patch
|
||||
"@gradio/client": patch
|
||||
"@gradio/dataframe": patch
|
||||
"@gradio/file": patch
|
||||
"@gradio/gallery": patch
|
||||
"@gradio/image": patch
|
||||
"@gradio/imageeditor": patch
|
||||
"@gradio/model3d": patch
|
||||
"@gradio/multimodaltextbox": patch
|
||||
"@gradio/simpleimage": patch
|
||||
"@gradio/storybook": patch
|
||||
"@gradio/tootils": patch
|
||||
"@gradio/upload": patch
|
||||
"@gradio/uploadbutton": patch
|
||||
"@gradio/utils": patch
|
||||
"@gradio/video": patch
|
||||
"gradio": patch
|
||||
---
|
||||
|
||||
fix:rework upload to be a class method + pass client into each component
|
@ -14,6 +14,7 @@ import type {
|
||||
} from "./types";
|
||||
import { view_api } from "./utils/view_api";
|
||||
import { upload_files } from "./utils/upload_files";
|
||||
import { upload, FileData } from "./upload";
|
||||
import { handle_blob } from "./utils/handle_blob";
|
||||
import { post_data } from "./utils/post_data";
|
||||
import { predict } from "./utils/predict";
|
||||
@ -61,10 +62,11 @@ export class Client {
|
||||
return fetch(input, init);
|
||||
}
|
||||
|
||||
eventSource_factory(url: URL): EventSource | null {
|
||||
eventSource_factory(url: URL): EventSource {
|
||||
if (typeof window !== undefined && typeof EventSource !== "undefined") {
|
||||
return new EventSource(url.toString());
|
||||
}
|
||||
// @ts-ignore
|
||||
return null; // todo: polyfill eventsource for node envs
|
||||
}
|
||||
|
||||
@ -74,6 +76,12 @@ export class Client {
|
||||
files: (Blob | File)[],
|
||||
upload_id?: string
|
||||
) => Promise<UploadResponse>;
|
||||
upload: (
|
||||
file_data: FileData[],
|
||||
root_url: string,
|
||||
upload_id?: string,
|
||||
max_file_size?: number
|
||||
) => Promise<(FileData | null)[] | null>;
|
||||
handle_blob: (
|
||||
endpoint: string,
|
||||
data: unknown[],
|
||||
@ -109,6 +117,7 @@ export class Client {
|
||||
this.predict = predict.bind(this);
|
||||
this.open_stream = open_stream.bind(this);
|
||||
this.resolve_config = resolve_config.bind(this);
|
||||
this.upload = upload.bind(this);
|
||||
}
|
||||
|
||||
private async init(): Promise<void> {
|
||||
|
@ -1,16 +1,12 @@
|
||||
import type { UploadResponse } from "./types";
|
||||
import { upload_files } from ".";
|
||||
import type { Client } from "./client";
|
||||
|
||||
export async function upload(
|
||||
this: Client,
|
||||
file_data: FileData[],
|
||||
root_url: string,
|
||||
upload_id?: string,
|
||||
max_file_size?: number,
|
||||
upload_fn: (
|
||||
root_url: string,
|
||||
files: (Blob | File)[],
|
||||
upload_id?: string
|
||||
) => Promise<UploadResponse> = upload_files
|
||||
max_file_size?: number
|
||||
): Promise<(FileData | null)[] | null> {
|
||||
let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
|
||||
(file_data) => file_data.blob!
|
||||
@ -28,7 +24,7 @@ export async function upload(
|
||||
}
|
||||
|
||||
return await Promise.all(
|
||||
await upload_fn(root_url, files, upload_id).then(
|
||||
await this.upload_files(root_url, files, upload_id).then(
|
||||
async (response: { files?: string[]; error?: string }) => {
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
|
@ -11,9 +11,10 @@ export async function upload_files(
|
||||
const headers: {
|
||||
Authorization?: string;
|
||||
} = {};
|
||||
if (this.options.hf_token) {
|
||||
if (this?.options?.hf_token) {
|
||||
headers.Authorization = `Bearer ${this.options.hf_token}`;
|
||||
}
|
||||
|
||||
const chunkSize = 1000;
|
||||
const uploadResponses = [];
|
||||
let response: Response;
|
||||
|
@ -2,7 +2,6 @@
|
||||
import { tick } from "svelte";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { Client } from "@gradio/client";
|
||||
import { setContext } from "svelte";
|
||||
|
||||
import type { LoadingStatus, LoadingStatusCollection } from "./stores";
|
||||
|
||||
@ -522,8 +521,6 @@
|
||||
function isCustomEvent(event: Event): event is CustomEvent {
|
||||
return "detail" in event;
|
||||
}
|
||||
|
||||
setContext("upload_files", app.upload_files);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@ -562,6 +559,7 @@
|
||||
{version}
|
||||
{autoscroll}
|
||||
max_file_size={app.config.max_file_size}
|
||||
client={app}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -63,7 +63,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount, setContext, createEventDispatcher } from "svelte";
|
||||
import { onMount, createEventDispatcher } from "svelte";
|
||||
import type { SpaceStatus } from "@gradio/client";
|
||||
import Embed from "./Embed.svelte";
|
||||
import type { ThemeMode } from "./types";
|
||||
@ -100,11 +100,6 @@
|
||||
loading_text = (event as CustomEvent).detail + "...";
|
||||
});
|
||||
}
|
||||
export let fetch_implementation: typeof fetch = fetch;
|
||||
setContext("fetch_implementation", fetch_implementation);
|
||||
export let EventSource_factory: (url: URL) => EventSource = (url) =>
|
||||
new EventSource(url);
|
||||
setContext("EventSource_factory", EventSource_factory);
|
||||
|
||||
export let space: string | null;
|
||||
export let host: string | null;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount, createEventDispatcher } from "svelte";
|
||||
import type { Client } from "@gradio/client";
|
||||
import Render from "./Render.svelte";
|
||||
|
||||
export let rootNode: any;
|
||||
@ -9,6 +10,7 @@
|
||||
export let version: any;
|
||||
export let autoscroll: boolean;
|
||||
export let max_file_size: number | null = null;
|
||||
export let client: Client;
|
||||
|
||||
const dispatch = createEventDispatcher<{ mount?: never }>();
|
||||
onMount(() => {
|
||||
@ -24,4 +26,5 @@
|
||||
{version}
|
||||
{autoscroll}
|
||||
{max_file_size}
|
||||
{client}
|
||||
/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { Gradio, formatter } from "./gradio_helper";
|
||||
import { onMount, createEventDispatcher, setContext } from "svelte";
|
||||
import type { ComponentMeta, ThemeMode } from "./types";
|
||||
import type { Client } from "@gradio/client";
|
||||
import RenderComponent from "./RenderComponent.svelte";
|
||||
|
||||
export let root: string;
|
||||
@ -13,6 +14,7 @@
|
||||
export let version: string;
|
||||
export let autoscroll: boolean;
|
||||
export let max_file_size: number | null;
|
||||
export let client: Client;
|
||||
|
||||
const dispatch = createEventDispatcher<{ mount: number; destroy: number }>();
|
||||
let filtered_children: ComponentMeta[] = [];
|
||||
@ -45,12 +47,6 @@
|
||||
|
||||
setContext("BLOCK_KEY", parent);
|
||||
|
||||
function handle_prop_change(e: { detail: Record<string, any> }): void {
|
||||
// for (const k in e.detail) {
|
||||
// instance_map[id].props[k] = e.detail[k];
|
||||
// }
|
||||
}
|
||||
|
||||
$: {
|
||||
if (node.type === "form") {
|
||||
if (node.children?.every((c) => !c.props.visible)) {
|
||||
@ -70,7 +66,6 @@
|
||||
elem_id={("elem_id" in node.props && node.props.elem_id) ||
|
||||
`component-${node.id}`}
|
||||
elem_classes={("elem_classes" in node.props && node.props.elem_classes) || []}
|
||||
on:prop_change={handle_prop_change}
|
||||
{target}
|
||||
{...node.props}
|
||||
{theme_mode}
|
||||
@ -83,7 +78,8 @@
|
||||
root,
|
||||
autoscroll,
|
||||
max_file_size,
|
||||
formatter
|
||||
formatter,
|
||||
client
|
||||
)}
|
||||
>
|
||||
{#if node.children && node.children.length}
|
||||
@ -98,6 +94,7 @@
|
||||
on:destroy
|
||||
on:mount
|
||||
{max_file_size}
|
||||
{client}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
|
@ -23,9 +23,7 @@
|
||||
export let mount_css: typeof default_mount_css = default_mount_css;
|
||||
export let Client: typeof ClientType;
|
||||
export let worker_proxy: WorkerProxy | undefined = undefined;
|
||||
export let fetch_implementation: typeof fetch = fetch;
|
||||
export let EventSource_factory: (url: URL) => EventSource = (url) =>
|
||||
new EventSource(url);
|
||||
|
||||
export let space: string | null;
|
||||
export let host: string | null;
|
||||
export let src: string | null;
|
||||
@ -217,8 +215,6 @@
|
||||
{mount_css}
|
||||
{Client}
|
||||
bind:worker_proxy
|
||||
{fetch_implementation}
|
||||
{EventSource_factory}
|
||||
{space}
|
||||
{host}
|
||||
{src}
|
||||
|
@ -126,13 +126,6 @@ export function create(options: Options): GradioAppController {
|
||||
|
||||
mount_prebuilt_css(document.head);
|
||||
|
||||
const overridden_fetch: typeof fetch = (input, init?) => {
|
||||
return wasm_proxied_fetch(worker_proxy, input, init);
|
||||
};
|
||||
const EventSource_factory = (url: URL): EventSource => {
|
||||
return wasm_proxied_EventSource_factory(worker_proxy, url);
|
||||
};
|
||||
|
||||
class LiteClient extends Client {
|
||||
fetch_implementation(
|
||||
input: RequestInfo | URL,
|
||||
@ -222,8 +215,6 @@ export function create(options: Options): GradioAppController {
|
||||
worker_proxy,
|
||||
Client: LiteClient,
|
||||
mount_css: overridden_mount_css,
|
||||
fetch_implementation: overridden_fetch,
|
||||
EventSource_factory,
|
||||
// For playground
|
||||
layout: options.layout
|
||||
};
|
||||
|
@ -225,6 +225,8 @@
|
||||
{waveform_settings}
|
||||
{waveform_options}
|
||||
{trim_region_settings}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
>
|
||||
<UploadText i18n={gradio.i18n} type="audio" />
|
||||
</InteractiveAudio>
|
||||
|
@ -1,12 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { getContext, onDestroy, createEventDispatcher } from "svelte";
|
||||
import { onDestroy, createEventDispatcher } from "svelte";
|
||||
import { Upload, ModifyUpload } from "@gradio/upload";
|
||||
import {
|
||||
upload,
|
||||
prepare_files,
|
||||
type FileData,
|
||||
type upload_files
|
||||
} from "@gradio/client";
|
||||
import { prepare_files, type FileData, type Client } from "@gradio/client";
|
||||
import { BlockLabel } from "@gradio/atoms";
|
||||
import { Music } from "@gradio/icons";
|
||||
import AudioPlayer from "../player/AudioPlayer.svelte";
|
||||
@ -39,9 +34,8 @@
|
||||
export let handle_reset_value: () => void = () => {};
|
||||
export let editable = true;
|
||||
export let max_file_size: number | null = null;
|
||||
|
||||
// Needed for wasm support
|
||||
const upload_fn = getContext<typeof upload_files>("upload_files");
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
$: dispatch("drag", dragging);
|
||||
|
||||
@ -98,9 +92,9 @@
|
||||
let _audio_blob = new File(blobs, "audio.wav");
|
||||
const val = await prepare_files([_audio_blob], event === "stream");
|
||||
value = (
|
||||
(
|
||||
await upload(val, root, undefined, max_file_size ?? Infinity, upload_fn)
|
||||
)?.filter(Boolean) as FileData[]
|
||||
(await upload(val, root, undefined, max_file_size || undefined))?.filter(
|
||||
Boolean
|
||||
) as FileData[]
|
||||
)[0];
|
||||
|
||||
dispatch(event, value);
|
||||
@ -257,6 +251,8 @@
|
||||
on:error={({ detail }) => dispatch("error", detail)}
|
||||
{root}
|
||||
{max_file_size}
|
||||
{upload}
|
||||
{stream_handler}
|
||||
>
|
||||
<slot />
|
||||
</Upload>
|
||||
|
@ -150,5 +150,7 @@
|
||||
i18n={gradio.i18n}
|
||||
{line_breaks}
|
||||
{column_widths}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
/>
|
||||
</Block>
|
||||
|
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@gradio/atoms": "workspace:^",
|
||||
"@gradio/button": "workspace:^",
|
||||
"@gradio/client": "workspace:^",
|
||||
"@gradio/markdown": "workspace:^",
|
||||
"@gradio/statustracker": "workspace:^",
|
||||
"@gradio/upload": "workspace:^",
|
||||
|
@ -8,6 +8,7 @@
|
||||
import EditableCell from "./EditableCell.svelte";
|
||||
import type { SelectData } from "@gradio/utils";
|
||||
import type { I18nFormatter } from "js/app/src/gradio_helper";
|
||||
import { type Client } from "@gradio/client";
|
||||
import VirtualTable from "./VirtualTable.svelte";
|
||||
import type {
|
||||
Headers,
|
||||
@ -38,6 +39,8 @@
|
||||
export let height = 500;
|
||||
export let line_breaks = true;
|
||||
export let column_widths: string[] = [];
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
let selected: false | [number, number] = false;
|
||||
export let display_value: string[][] | null = null;
|
||||
@ -722,6 +725,8 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<Upload
|
||||
{upload}
|
||||
{stream_handler}
|
||||
flex={false}
|
||||
center={false}
|
||||
boundedheight={false}
|
||||
|
@ -87,6 +87,8 @@
|
||||
/>
|
||||
{:else}
|
||||
<FileUpload
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
{label}
|
||||
{show_label}
|
||||
{value}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, tick } from "svelte";
|
||||
import { Upload, ModifyUpload } from "@gradio/upload";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import { BlockLabel } from "@gradio/atoms";
|
||||
import { File } from "@gradio/icons";
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
export let height: number | undefined = undefined;
|
||||
export let i18n: I18nFormatter;
|
||||
export let max_file_size: number | null = null;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
async function handle_upload({
|
||||
detail
|
||||
@ -67,6 +69,8 @@
|
||||
{root}
|
||||
bind:dragging
|
||||
on:error
|
||||
{stream_handler}
|
||||
{upload}
|
||||
>
|
||||
<slot />
|
||||
</Upload>
|
||||
|
@ -77,6 +77,8 @@
|
||||
file_count={"multiple"}
|
||||
file_types={["image"]}
|
||||
i18n={gradio.i18n}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
on:upload={(e) => {
|
||||
const files = Array.isArray(e.detail) ? e.detail : [e.detail];
|
||||
value = files.map((x) => ({ image: x, caption: null }));
|
||||
@ -110,6 +112,7 @@
|
||||
{show_share_button}
|
||||
{show_download_button}
|
||||
i18n={gradio.i18n}
|
||||
fetch_implementation={gradio.client.fetch_implementation}
|
||||
/>
|
||||
{/if}
|
||||
</Block>
|
||||
|
@ -4,7 +4,7 @@
|
||||
import type { SelectData } from "@gradio/utils";
|
||||
import { Image } from "@gradio/image/shared";
|
||||
import { dequal } from "dequal";
|
||||
import { createEventDispatcher, getContext } from "svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { tick } from "svelte";
|
||||
|
||||
import { Download, Image as ImageIcon } from "@gradio/icons";
|
||||
@ -31,6 +31,7 @@
|
||||
export let i18n: I18nFormatter;
|
||||
export let selected_index: number | null = null;
|
||||
export let interactive: boolean;
|
||||
export let fetch_implementation: typeof fetch;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: undefined;
|
||||
@ -159,14 +160,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
let client_height = 0;
|
||||
let window_height = 0;
|
||||
|
||||
// Unlike `gr.Image()`, images specified via remote URLs are not cached in the server
|
||||
// and their remote URLs are directly passed to the client as `value[].image.url`.
|
||||
// The `download` attribute of the <a> tag doesn't work for remote URLs (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#download),
|
||||
// so we need to download the image via JS as below.
|
||||
const fetch_implementation = getContext<typeof fetch>("fetch_implementation");
|
||||
async function download(file_url: string, name: string): Promise<void> {
|
||||
let response;
|
||||
try {
|
||||
@ -279,11 +278,7 @@
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
bind:clientHeight={client_height}
|
||||
class="grid-wrap"
|
||||
class:fixed-height={!height || height == "auto"}
|
||||
>
|
||||
<div class="grid-wrap" class:fixed-height={!height || height == "auto"}>
|
||||
<div
|
||||
class="grid-container"
|
||||
style="--grid-cols:{columns}; --grid-rows:{rows}; --object-fit: {object_fit}; height: {height};"
|
||||
|
@ -156,6 +156,8 @@
|
||||
{mirror_webcam}
|
||||
max_file_size={gradio.max_file_size}
|
||||
i18n={gradio.i18n}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
>
|
||||
{#if active_source === "upload" || !active_source}
|
||||
<UploadText i18n={gradio.i18n} type="image" />
|
||||
|
@ -7,7 +7,7 @@
|
||||
import Webcam from "./Webcam.svelte";
|
||||
|
||||
import { Upload } from "@gradio/upload";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import ClearImage from "./ClearImage.svelte";
|
||||
import { SelectSource } from "@gradio/atoms";
|
||||
import Image from "./Image.svelte";
|
||||
@ -26,8 +26,10 @@
|
||||
export let root: string;
|
||||
export let i18n: I18nFormatter;
|
||||
export let max_file_size: number | null = null;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
let upload: Upload;
|
||||
let upload_input: Upload;
|
||||
let uploading = false;
|
||||
export let active_source: source_type = null;
|
||||
|
||||
@ -44,7 +46,9 @@
|
||||
|
||||
async function handle_save(img_blob: Blob | any): Promise<void> {
|
||||
pending = true;
|
||||
const f = await upload.load_files([new File([img_blob], `webcam.png`)]);
|
||||
const f = await upload_input.load_files([
|
||||
new File([img_blob], `webcam.png`)
|
||||
]);
|
||||
|
||||
value = f?.[0] || null;
|
||||
|
||||
@ -86,7 +90,7 @@
|
||||
): Promise<void> {
|
||||
switch (source) {
|
||||
case "clipboard":
|
||||
upload.paste_clipboard();
|
||||
upload_input.paste_clipboard();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -108,7 +112,7 @@
|
||||
<div class="upload-container">
|
||||
<Upload
|
||||
hidden={value !== null || active_source === "webcam"}
|
||||
bind:this={upload}
|
||||
bind:this={upload_input}
|
||||
bind:uploading
|
||||
bind:dragging
|
||||
filetype={active_source === "clipboard" ? "clipboard" : "image/*"}
|
||||
@ -117,6 +121,8 @@
|
||||
{root}
|
||||
{max_file_size}
|
||||
disable_click={!sources.includes("upload")}
|
||||
{upload}
|
||||
{stream_handler}
|
||||
>
|
||||
{#if value === null}
|
||||
<slot />
|
||||
@ -135,6 +141,7 @@
|
||||
mode="image"
|
||||
include_audio={false}
|
||||
{i18n}
|
||||
{upload}
|
||||
/>
|
||||
{:else if value !== null && !streaming}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events-->
|
||||
|
@ -2,8 +2,7 @@
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { Camera, Circle, Square, DropdownArrow } from "@gradio/icons";
|
||||
import type { I18nFormatter } from "@gradio/utils";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import { prepare_files, upload } from "@gradio/client";
|
||||
import { type FileData, type Client, prepare_files } from "@gradio/client";
|
||||
import WebcamPermissions from "./WebcamPermissions.svelte";
|
||||
import { fade } from "svelte/transition";
|
||||
import {
|
||||
@ -25,6 +24,7 @@
|
||||
export let mirror_webcam: boolean;
|
||||
export let include_audio: boolean;
|
||||
export let i18n: I18nFormatter;
|
||||
export let upload: Client["upload"];
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
stream: undefined;
|
||||
|
@ -199,11 +199,14 @@
|
||||
{brush}
|
||||
{eraser}
|
||||
changeable={attached_events.includes("apply")}
|
||||
realtime={attached_events.includes("change")}
|
||||
i18n={gradio.i18n}
|
||||
{transforms}
|
||||
accept_blobs={server.accept_blobs}
|
||||
{layers}
|
||||
status={loading_status?.status}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
></InteractiveImageEditor>
|
||||
</Block>
|
||||
{/if}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { type I18nFormatter } from "@gradio/utils";
|
||||
import { prepare_files, upload, type FileData } from "@gradio/client";
|
||||
import { prepare_files, type FileData, type Client } from "@gradio/client";
|
||||
|
||||
import ImageEditor from "./ImageEditor.svelte";
|
||||
import Layers from "./layers/Layers.svelte";
|
||||
@ -44,6 +44,9 @@
|
||||
export let layers: boolean;
|
||||
export let accept_blobs: (a: any) => void;
|
||||
export let status: "pending" | "complete" | "error" = "complete";
|
||||
export let realtime: boolean;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
clear?: never;
|
||||
@ -131,6 +134,7 @@
|
||||
let uploading = false;
|
||||
let pending = false;
|
||||
async function handle_change(e: CustomEvent<Blob | any>): Promise<void> {
|
||||
if (!realtime) return;
|
||||
if (uploading) {
|
||||
pending = true;
|
||||
return;
|
||||
@ -217,6 +221,8 @@
|
||||
{i18n}
|
||||
{root}
|
||||
{sources}
|
||||
{upload}
|
||||
{stream_handler}
|
||||
bind:bg
|
||||
bind:active_mode
|
||||
background_file={value?.background || value?.composite || null}
|
||||
|
@ -11,6 +11,7 @@
|
||||
import { Webcam } from "@gradio/image";
|
||||
import { type I18nFormatter } from "@gradio/utils";
|
||||
import { IconButton } from "@gradio/atoms";
|
||||
import { type Client } from "@gradio/client";
|
||||
|
||||
import { add_bg_color, add_bg_image } from "./sources";
|
||||
import type { FileData } from "@gradio/client";
|
||||
@ -24,6 +25,8 @@
|
||||
];
|
||||
export let mirror_webcam = true;
|
||||
export let i18n: I18nFormatter;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
const { active_tool } = getContext<ToolContext>(TOOL_KEY);
|
||||
const { pixi, dimensions, register_context, reset, editor_box } =
|
||||
@ -43,7 +46,7 @@
|
||||
order: 0,
|
||||
id: "bg_upload",
|
||||
cb() {
|
||||
upload.open_file_upload();
|
||||
upload_component.open_file_upload();
|
||||
|
||||
$active_tool = "bg";
|
||||
}
|
||||
@ -74,7 +77,7 @@
|
||||
.map((src) => sources_meta[src])
|
||||
.sort((a, b) => a.order - b.order);
|
||||
|
||||
let upload: Upload;
|
||||
let upload_component: Upload;
|
||||
|
||||
async function process_clipboard(): Promise<void> {
|
||||
const items = await navigator.clipboard.read();
|
||||
@ -179,13 +182,15 @@
|
||||
<div class="upload-container">
|
||||
<Upload
|
||||
hidden={true}
|
||||
bind:this={upload}
|
||||
bind:this={upload_component}
|
||||
filetype="image/*"
|
||||
on:load={handle_upload}
|
||||
on:error
|
||||
{root}
|
||||
disable_click={!sources.includes("upload")}
|
||||
format="blob"
|
||||
{upload}
|
||||
{stream_handler}
|
||||
></Upload>
|
||||
{#if active_mode === "webcam"}
|
||||
<div
|
||||
@ -196,6 +201,7 @@
|
||||
>
|
||||
<div class="modal-inner">
|
||||
<Webcam
|
||||
{upload}
|
||||
{root}
|
||||
on:capture={handle_upload}
|
||||
on:error
|
||||
|
@ -127,6 +127,8 @@
|
||||
}}
|
||||
i18n={gradio.i18n}
|
||||
max_file_size={gradio.max_file_size}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
>
|
||||
<UploadText i18n={gradio.i18n} type="file" />
|
||||
</Model3DUpload>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, tick } from "svelte";
|
||||
import { Upload, ModifyUpload } from "@gradio/upload";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import { BlockLabel } from "@gradio/atoms";
|
||||
import { File } from "@gradio/icons";
|
||||
import type { I18nFormatter } from "@gradio/utils";
|
||||
@ -24,6 +24,8 @@
|
||||
null,
|
||||
null
|
||||
];
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
async function handle_upload({
|
||||
detail
|
||||
@ -86,6 +88,8 @@
|
||||
|
||||
{#if value === null}
|
||||
<Upload
|
||||
{upload}
|
||||
{stream_handler}
|
||||
on:load={handle_upload}
|
||||
{root}
|
||||
{max_file_size}
|
||||
|
@ -97,5 +97,7 @@
|
||||
gradio.dispatch("error", detail);
|
||||
}}
|
||||
disabled={!interactive}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
/>
|
||||
</Block>
|
||||
|
@ -9,7 +9,7 @@
|
||||
import { BlockTitle } from "@gradio/atoms";
|
||||
import { Upload } from "@gradio/upload";
|
||||
import { Image } from "@gradio/image/shared";
|
||||
import type { FileData, upload } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import { Clear, File, Music, Video, Send } from "@gradio/icons";
|
||||
import type { SelectData } from "@gradio/utils";
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
export let root: string;
|
||||
export let file_types: string[] | null = null;
|
||||
export let max_file_size: number | null = null;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
let upload_component: Upload;
|
||||
let hidden_upload: HTMLInputElement;
|
||||
@ -215,6 +217,8 @@
|
||||
disable_click={true}
|
||||
bind:hidden_upload
|
||||
on:error
|
||||
{upload}
|
||||
{stream_handler}
|
||||
>
|
||||
{#if submit_btn !== null}
|
||||
<button class:disabled class="submit-button" on:click={handle_submit}
|
||||
|
@ -90,6 +90,8 @@
|
||||
/>
|
||||
|
||||
<ImageUploader
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
bind:value
|
||||
{root}
|
||||
on:clear={() => gradio.dispatch("clear")}
|
||||
|
@ -4,15 +4,17 @@
|
||||
import { Image as ImageIcon } from "@gradio/icons";
|
||||
|
||||
import { Upload } from "@gradio/upload";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import ClearImage from "./ClearImage.svelte";
|
||||
|
||||
export let value: null | FileData;
|
||||
export let label: string | undefined = undefined;
|
||||
export let show_label: boolean;
|
||||
export let root: string;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
let upload: Upload;
|
||||
let upload_component: Upload;
|
||||
let uploading = false;
|
||||
|
||||
function handle_upload({ detail }: CustomEvent<FileData>): void {
|
||||
@ -45,8 +47,10 @@
|
||||
{/if}
|
||||
<div class="upload-container">
|
||||
<Upload
|
||||
{upload}
|
||||
{stream_handler}
|
||||
hidden={value !== null}
|
||||
bind:this={upload}
|
||||
bind:this={upload_component}
|
||||
bind:uploading
|
||||
bind:dragging
|
||||
filetype="image/*"
|
||||
|
@ -21,7 +21,9 @@ const preview: Preview = {
|
||||
"localhost:9876",
|
||||
false,
|
||||
null,
|
||||
formatter
|
||||
formatter,
|
||||
// @ts-ignore
|
||||
{ client: { fetch_implementation() {}, upload() {} } }
|
||||
)
|
||||
},
|
||||
argTypes: {
|
||||
|
@ -92,6 +92,7 @@ export async function render<
|
||||
props: {
|
||||
loading_status,
|
||||
...(props || {}),
|
||||
//@ts-ignore
|
||||
gradio: new Gradio(
|
||||
id,
|
||||
target,
|
||||
@ -99,7 +100,11 @@ export async function render<
|
||||
"2.0.0",
|
||||
"http://localhost:8000",
|
||||
false,
|
||||
null
|
||||
null,
|
||||
//@ts-ignore
|
||||
(s) => s,
|
||||
// @ts-ignore
|
||||
{ client: {} }
|
||||
)
|
||||
}
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, tick, getContext } from "svelte";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import { upload_files, upload, prepare_files } from "@gradio/client";
|
||||
import { prepare_files, type Client } from "@gradio/client";
|
||||
import { _ } from "svelte-i18n";
|
||||
import UploadProgress from "./UploadProgress.svelte";
|
||||
|
||||
@ -19,14 +19,13 @@
|
||||
export let hidden_upload: HTMLInputElement | null = null;
|
||||
export let show_progress = true;
|
||||
export let max_file_size: number | null = null;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
let upload_id: string;
|
||||
let file_data: FileData[];
|
||||
let accept_file_types: string | null;
|
||||
|
||||
// Needed for wasm support
|
||||
const upload_fn = getContext<typeof upload_files>("upload_files");
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const validFileTypes = ["image", "video", "audio", "text", "file"];
|
||||
const processFileType = (type: string): string => {
|
||||
@ -89,8 +88,7 @@
|
||||
file_data,
|
||||
root,
|
||||
upload_id,
|
||||
max_file_size ?? Infinity,
|
||||
upload_fn
|
||||
max_file_size ?? Infinity
|
||||
);
|
||||
dispatch("load", file_count === "single" ? _file_data?.[0] : _file_data);
|
||||
uploading = false;
|
||||
@ -201,7 +199,7 @@
|
||||
</button>
|
||||
{:else if uploading && show_progress}
|
||||
{#if !hidden}
|
||||
<UploadProgress {root} {upload_id} files={file_data} />
|
||||
<UploadProgress {root} {upload_id} files={file_data} {stream_handler} />
|
||||
{/if}
|
||||
{:else}
|
||||
<button
|
||||
|
@ -1,19 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { FileData } from "@gradio/client";
|
||||
import {
|
||||
onMount,
|
||||
createEventDispatcher,
|
||||
getContext,
|
||||
onDestroy
|
||||
} from "svelte";
|
||||
import { FileData, type Client } from "@gradio/client";
|
||||
import { onMount, createEventDispatcher, onDestroy } from "svelte";
|
||||
|
||||
type FileDataWithProgress = FileData & { progress: number };
|
||||
|
||||
export let upload_id: string;
|
||||
export let root: string;
|
||||
export let files: FileData[];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
let event_source: EventSource;
|
||||
let event_source: ReturnType<Client["eventSource_factory"]>;
|
||||
let progress = false;
|
||||
let current_file_upload: FileDataWithProgress;
|
||||
let file_to_display: FileDataWithProgress;
|
||||
@ -41,13 +37,14 @@
|
||||
return (file.progress * 100) / (file.size || 0) || 0;
|
||||
}
|
||||
|
||||
const EventSource_factory = getContext<(url: URL) => EventSource>(
|
||||
"EventSource_factory"
|
||||
);
|
||||
onMount(() => {
|
||||
event_source = EventSource_factory(
|
||||
event_source = stream_handler(
|
||||
new URL(`${root}/upload_progress?upload_id=${upload_id}`)
|
||||
);
|
||||
|
||||
if (event_source == null) {
|
||||
throw new Error("Event source is not defined");
|
||||
}
|
||||
// Event listener for progress updates
|
||||
event_source.onmessage = async function (event) {
|
||||
const _data = JSON.parse(event.data);
|
||||
|
@ -61,6 +61,7 @@
|
||||
on:error={({ detail }) => {
|
||||
gradio.dispatch("error", detail);
|
||||
}}
|
||||
upload={gradio.client.upload}
|
||||
>
|
||||
{label ? gradio.i18n(label) : ""}
|
||||
</UploadButton>
|
||||
|
@ -1,12 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { tick, createEventDispatcher, getContext } from "svelte";
|
||||
import { tick, createEventDispatcher } from "svelte";
|
||||
import { BaseButton } from "@gradio/button";
|
||||
import {
|
||||
upload,
|
||||
prepare_files,
|
||||
type FileData,
|
||||
type upload_files
|
||||
} from "@gradio/client";
|
||||
import { prepare_files, type FileData, type Client } from "@gradio/client";
|
||||
|
||||
export let elem_id = "";
|
||||
export let elem_classes: string[] = [];
|
||||
@ -23,12 +18,10 @@
|
||||
export let variant: "primary" | "secondary" | "stop" = "secondary";
|
||||
export let disabled = false;
|
||||
export let max_file_size: number | null = null;
|
||||
export let upload: Client["upload"];
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
// Needed for wasm support
|
||||
const upload_fn = getContext<typeof upload_files>("upload_files");
|
||||
|
||||
let hidden_upload: HTMLInputElement;
|
||||
let accept_file_types: string | null;
|
||||
|
||||
@ -63,13 +56,7 @@
|
||||
|
||||
try {
|
||||
all_file_data = (
|
||||
await upload(
|
||||
all_file_data,
|
||||
root,
|
||||
undefined,
|
||||
max_file_size ?? Infinity,
|
||||
upload_fn
|
||||
)
|
||||
await upload(all_file_data, root, undefined, max_file_size ?? Infinity)
|
||||
)?.filter((x) => x !== null) as FileData[];
|
||||
} catch (e) {
|
||||
dispatch("error", (e as Error).message);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { ActionReturn } from "svelte/action";
|
||||
import type { Client } from "@gradio/client";
|
||||
export interface SelectData {
|
||||
index: number | [number, number];
|
||||
value: any;
|
||||
@ -181,6 +182,7 @@ export class Gradio<T extends Record<string, any> = Record<string, any>> {
|
||||
root: string;
|
||||
autoscroll: boolean;
|
||||
max_file_size: number | null;
|
||||
client: Client;
|
||||
|
||||
constructor(
|
||||
id: number,
|
||||
@ -190,7 +192,8 @@ export class Gradio<T extends Record<string, any> = Record<string, any>> {
|
||||
root: string,
|
||||
autoscroll: boolean,
|
||||
max_file_size: number | null,
|
||||
i18n: I18nFormatter = (x: string): string => x
|
||||
i18n: I18nFormatter = (x: string): string => x,
|
||||
client: Client
|
||||
) {
|
||||
this.#id = id;
|
||||
this.theme = theme;
|
||||
@ -201,6 +204,7 @@ export class Gradio<T extends Record<string, any> = Record<string, any>> {
|
||||
this.i18n = i18n;
|
||||
this.root = root;
|
||||
this.autoscroll = autoscroll;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
dispatch<E extends keyof T>(event_name: E, data?: T[E]): void {
|
||||
|
@ -156,6 +156,7 @@
|
||||
on:share={({ detail }) => gradio.dispatch("share", detail)}
|
||||
on:error={({ detail }) => gradio.dispatch("error", detail)}
|
||||
i18n={gradio.i18n}
|
||||
upload={gradio.client.upload}
|
||||
/>
|
||||
</Block>
|
||||
{:else}
|
||||
@ -206,6 +207,8 @@
|
||||
on:stop_recording={() => gradio.dispatch("stop_recording")}
|
||||
i18n={gradio.i18n}
|
||||
max_file_size={gradio.max_file_size}
|
||||
upload={gradio.client.upload}
|
||||
stream_handler={gradio.client.eventSource_factory}
|
||||
>
|
||||
<UploadText i18n={gradio.i18n} type="video" />
|
||||
</Video>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { Upload, ModifyUpload } from "@gradio/upload";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import { BlockLabel } from "@gradio/atoms";
|
||||
import { Webcam } from "@gradio/image";
|
||||
import { Video } from "@gradio/icons";
|
||||
@ -29,6 +29,8 @@
|
||||
export let active_source: "webcam" | "upload" = "webcam";
|
||||
export let handle_reset_value: () => void = () => {};
|
||||
export let max_file_size: number | null = null;
|
||||
export let upload: Client["upload"];
|
||||
export let stream_handler: Client["eventSource_factory"];
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: FileData | null;
|
||||
@ -81,6 +83,8 @@
|
||||
{max_file_size}
|
||||
on:error={({ detail }) => dispatch("error", detail)}
|
||||
{root}
|
||||
{upload}
|
||||
{stream_handler}
|
||||
>
|
||||
<slot />
|
||||
</Upload>
|
||||
@ -95,6 +99,7 @@
|
||||
on:start_recording
|
||||
on:stop_recording
|
||||
{i18n}
|
||||
{upload}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
@ -107,6 +112,7 @@
|
||||
{#if playable()}
|
||||
{#key value?.url}
|
||||
<Player
|
||||
{upload}
|
||||
{root}
|
||||
interactive
|
||||
{autoplay}
|
||||
|
@ -3,8 +3,8 @@
|
||||
import { Play, Pause, Maximise, Undo } from "@gradio/icons";
|
||||
import Video from "./Video.svelte";
|
||||
import VideoControls from "./VideoControls.svelte";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import { prepare_files, upload } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import { prepare_files } from "@gradio/client";
|
||||
import { format_time } from "@gradio/utils";
|
||||
|
||||
export let root = "";
|
||||
@ -16,6 +16,7 @@
|
||||
export let interactive = false;
|
||||
export let handle_change: (video: FileData) => void = () => {};
|
||||
export let handle_reset_value: () => void = () => {};
|
||||
export let upload: Client["upload"];
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
play: undefined;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, afterUpdate, tick } from "svelte";
|
||||
import { BlockLabel, Empty, IconButton, ShareButton } from "@gradio/atoms";
|
||||
import type { FileData } from "@gradio/client";
|
||||
import type { FileData, Client } from "@gradio/client";
|
||||
import { Video, Download } from "@gradio/icons";
|
||||
import { uploadToHuggingFace } from "@gradio/utils";
|
||||
import { DownloadLink } from "@gradio/wasm/svelte";
|
||||
@ -17,6 +17,7 @@
|
||||
export let show_share_button = true;
|
||||
export let show_download_button = true;
|
||||
export let i18n: I18nFormatter;
|
||||
export let upload: Client["upload"];
|
||||
|
||||
let old_value: FileData | null = null;
|
||||
let old_subtitle: FileData | null = null;
|
||||
@ -64,6 +65,7 @@
|
||||
mirror={false}
|
||||
{label}
|
||||
interactive={false}
|
||||
{upload}
|
||||
/>
|
||||
{/key}
|
||||
<div class="icon-buttons" data-testid="download-div">
|
||||
|
@ -809,6 +809,9 @@ importers:
|
||||
'@gradio/button':
|
||||
specifier: workspace:^
|
||||
version: link:../button
|
||||
'@gradio/client':
|
||||
specifier: workspace:^
|
||||
version: link:../../client/js
|
||||
'@gradio/markdown':
|
||||
specifier: workspace:^
|
||||
version: link:../markdown
|
||||
|
Loading…
Reference in New Issue
Block a user